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