• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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