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/DebugInfoMetadata.h"
11 #include "llvm/IR/LLVMContext.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, DINode::FlagZero, nullptr, 0, nullptr, 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, 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, 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, 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
TEST(DebugTypeODRUniquingTest,buildODRType)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, 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, 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, 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, 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, nullptr));
100 EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
101 }
102
TEST(DebugTypeODRUniquingTest,buildODRTypeFields)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, 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, nullptr));
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