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
TEST(DebugTypeODRUniquingTest,enableDebugTypeODRUniquing)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
TEST(DebugTypeODRUniquingTest,getODRType)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, 0, 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, 0, 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(
48 &CT, DICompositeType::getODRType(Context, UUID, dwarf::DW_TAG_class_type,
49 nullptr, nullptr, 0, nullptr, nullptr, 0,
50 0, 0, 0, nullptr, 0, nullptr, nullptr));
51 EXPECT_EQ(&CT, DICompositeType::getODRType(
52 Context, UUID, dwarf::DW_TAG_class_type,
53 MDString::get(Context, "name"), nullptr, 0, nullptr,
54 nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
55
56 // Check that it's discarded with the type map.
57 Context.disableDebugTypeODRUniquing();
58 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
59
60 // And it shouldn't magically reappear...
61 Context.enableDebugTypeODRUniquing();
62 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
63 }
64
TEST(DebugTypeODRUniquingTest,buildODRType)65 TEST(DebugTypeODRUniquingTest, buildODRType) {
66 LLVMContext Context;
67 Context.enableDebugTypeODRUniquing();
68
69 // Build an ODR type that's a forward decl.
70 MDString &UUID = *MDString::get(Context, "Type");
71 auto &CT = *DICompositeType::buildODRType(
72 Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
73 nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
74 EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
75 EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
76
77 // Update with another forward decl. This should be a no-op.
78 EXPECT_EQ(&CT, DICompositeType::buildODRType(
79 Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
80 nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
81 EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
82
83 // Update with a definition. This time we should see a change.
84 EXPECT_EQ(&CT, DICompositeType::buildODRType(
85 Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
86 nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
87 EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
88
89 // Further updates should be ignored.
90 EXPECT_EQ(&CT, DICompositeType::buildODRType(
91 Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
92 nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
93 EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
94 EXPECT_EQ(&CT, DICompositeType::buildODRType(
95 Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
96 nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
97 EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
98 }
99
TEST(DebugTypeODRUniquingTest,buildODRTypeFields)100 TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
101 LLVMContext Context;
102 Context.enableDebugTypeODRUniquing();
103
104 // Build an ODR type that's a forward decl with no other fields set.
105 MDString &UUID = *MDString::get(Context, "UUID");
106 auto &CT = *DICompositeType::buildODRType(
107 Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
108 DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
109
110 // Create macros for running through all the fields except Identifier and Flags.
111 #define FOR_EACH_MDFIELD() \
112 DO_FOR_FIELD(Name) \
113 DO_FOR_FIELD(File) \
114 DO_FOR_FIELD(Scope) \
115 DO_FOR_FIELD(BaseType) \
116 DO_FOR_FIELD(Elements) \
117 DO_FOR_FIELD(VTableHolder) \
118 DO_FOR_FIELD(TemplateParams)
119 #define FOR_EACH_INLINEFIELD() \
120 DO_FOR_FIELD(Tag) \
121 DO_FOR_FIELD(Line) \
122 DO_FOR_FIELD(SizeInBits) \
123 DO_FOR_FIELD(AlignInBits) \
124 DO_FOR_FIELD(OffsetInBits) \
125 DO_FOR_FIELD(RuntimeLang)
126
127 // Create all the fields.
128 #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
129 FOR_EACH_MDFIELD();
130 #undef DO_FOR_FIELD
131 unsigned NonZeroInit = 0;
132 #define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
133 FOR_EACH_INLINEFIELD();
134 #undef DO_FOR_FIELD
135
136 // Replace all the fields with new values that are distinct from each other.
137 EXPECT_EQ(&CT,
138 DICompositeType::buildODRType(
139 Context, UUID, Tag, Name, File, Line, Scope, BaseType,
140 SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
141 Elements, RuntimeLang, VTableHolder, TemplateParams));
142
143 // Confirm that all the right fields got updated.
144 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
145 FOR_EACH_MDFIELD();
146 #undef DO_FOR_FIELD
147 #undef FOR_EACH_MDFIELD
148 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
149 FOR_EACH_INLINEFIELD();
150 #undef DO_FOR_FIELD
151 #undef FOR_EACH_INLINEFIELD
152 EXPECT_EQ(DINode::FlagArtificial, CT.getFlags());
153 EXPECT_EQ(&UUID, CT.getRawIdentifier());
154 }
155
156 } // end namespace
157