DebugTypeODRUniquingTest.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //===- DebugTypeODRUniquingTest.cpp - Debug type ODR uniquing tests -------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/IR/DebugInfoMetadata.h"
  9. #include "llvm/IR/LLVMContext.h"
  10. #include "gtest/gtest.h"
  11. using namespace llvm;
  12. namespace {
  13. TEST(DebugTypeODRUniquingTest, enableDebugTypeODRUniquing) {
  14. LLVMContext Context;
  15. EXPECT_FALSE(Context.isODRUniquingDebugTypes());
  16. Context.enableDebugTypeODRUniquing();
  17. EXPECT_TRUE(Context.isODRUniquingDebugTypes());
  18. Context.disableDebugTypeODRUniquing();
  19. EXPECT_FALSE(Context.isODRUniquingDebugTypes());
  20. }
  21. TEST(DebugTypeODRUniquingTest, getODRType) {
  22. LLVMContext Context;
  23. MDString &UUID = *MDString::get(Context, "string");
  24. // Without a type map, this should return null.
  25. EXPECT_FALSE(DICompositeType::getODRType(
  26. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
  27. nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
  28. // Enable the mapping. There still shouldn't be a type.
  29. Context.enableDebugTypeODRUniquing();
  30. EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
  31. // Create some ODR-uniqued type.
  32. auto &CT = *DICompositeType::getODRType(
  33. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
  34. nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr);
  35. EXPECT_EQ(UUID.getString(), CT.getIdentifier());
  36. // Check that we get it back, even if we change a field.
  37. EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
  38. EXPECT_EQ(&CT, DICompositeType::getODRType(
  39. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
  40. 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
  41. nullptr, nullptr, nullptr));
  42. EXPECT_EQ(&CT,
  43. DICompositeType::getODRType(
  44. Context, UUID, dwarf::DW_TAG_class_type,
  45. MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0,
  46. 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr));
  47. // Check that it's discarded with the type map.
  48. Context.disableDebugTypeODRUniquing();
  49. EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
  50. // And it shouldn't magically reappear...
  51. Context.enableDebugTypeODRUniquing();
  52. EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
  53. }
  54. TEST(DebugTypeODRUniquingTest, buildODRType) {
  55. LLVMContext Context;
  56. Context.enableDebugTypeODRUniquing();
  57. // Build an ODR type that's a forward decl.
  58. MDString &UUID = *MDString::get(Context, "Type");
  59. auto &CT = *DICompositeType::buildODRType(
  60. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
  61. nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
  62. EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
  63. EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
  64. // Update with another forward decl. This should be a no-op.
  65. EXPECT_EQ(&CT, DICompositeType::buildODRType(
  66. Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
  67. nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
  68. EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
  69. // Update with a definition. This time we should see a change.
  70. EXPECT_EQ(&CT, DICompositeType::buildODRType(
  71. Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
  72. nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero,
  73. nullptr, 0, nullptr, nullptr, nullptr));
  74. EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
  75. // Further updates should be ignored.
  76. EXPECT_EQ(&CT, DICompositeType::buildODRType(
  77. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
  78. nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr));
  79. EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
  80. EXPECT_EQ(&CT, DICompositeType::buildODRType(
  81. Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
  82. 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
  83. nullptr, nullptr, nullptr));
  84. EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
  85. }
  86. TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
  87. LLVMContext Context;
  88. Context.enableDebugTypeODRUniquing();
  89. // Build an ODR type that's a forward decl with no other fields set.
  90. MDString &UUID = *MDString::get(Context, "UUID");
  91. auto &CT = *DICompositeType::buildODRType(
  92. Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
  93. DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr);
  94. // Create macros for running through all the fields except Identifier and Flags.
  95. #define FOR_EACH_MDFIELD() \
  96. DO_FOR_FIELD(Name) \
  97. DO_FOR_FIELD(File) \
  98. DO_FOR_FIELD(Scope) \
  99. DO_FOR_FIELD(BaseType) \
  100. DO_FOR_FIELD(Elements) \
  101. DO_FOR_FIELD(VTableHolder) \
  102. DO_FOR_FIELD(TemplateParams)
  103. #define FOR_EACH_INLINEFIELD() \
  104. DO_FOR_FIELD(Tag) \
  105. DO_FOR_FIELD(Line) \
  106. DO_FOR_FIELD(SizeInBits) \
  107. DO_FOR_FIELD(AlignInBits) \
  108. DO_FOR_FIELD(OffsetInBits) \
  109. DO_FOR_FIELD(RuntimeLang)
  110. // Create all the fields.
  111. #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
  112. FOR_EACH_MDFIELD();
  113. #undef DO_FOR_FIELD
  114. unsigned NonZeroInit = 0;
  115. #define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
  116. FOR_EACH_INLINEFIELD();
  117. #undef DO_FOR_FIELD
  118. // Replace all the fields with new values that are distinct from each other.
  119. EXPECT_EQ(&CT,
  120. DICompositeType::buildODRType(
  121. Context, UUID, Tag, Name, File, Line, Scope, BaseType,
  122. SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
  123. Elements, RuntimeLang, VTableHolder, TemplateParams, nullptr));
  124. // Confirm that all the right fields got updated.
  125. #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
  126. FOR_EACH_MDFIELD();
  127. #undef DO_FOR_FIELD
  128. #undef FOR_EACH_MDFIELD
  129. #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
  130. FOR_EACH_INLINEFIELD();
  131. #undef DO_FOR_FIELD
  132. #undef FOR_EACH_INLINEFIELD
  133. EXPECT_EQ(DINode::FlagArtificial, CT.getFlags());
  134. EXPECT_EQ(&UUID, CT.getRawIdentifier());
  135. }
  136. } // end namespace