1 //===- DebugTypeODRUniquingTest.cpp - Debug type ODR uniquing tests -------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/BinaryFormat/Dwarf.h"
10 #include "llvm/IR/DebugInfoMetadata.h"
11 #include "llvm/IR/LLVMContext.h"
12 #include "gtest/gtest.h"
17 TEST(DebugTypeODRUniquingTest
, enableDebugTypeODRUniquing
) {
19 EXPECT_FALSE(Context
.isODRUniquingDebugTypes());
20 Context
.enableDebugTypeODRUniquing();
21 EXPECT_TRUE(Context
.isODRUniquingDebugTypes());
22 Context
.disableDebugTypeODRUniquing();
23 EXPECT_FALSE(Context
.isODRUniquingDebugTypes());
26 TEST(DebugTypeODRUniquingTest
, getODRType
) {
28 MDString
&UUID
= *MDString::get(Context
, "string");
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, nullptr, 0, DINode::FlagZero
, nullptr, 0, nullptr,
34 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
36 // Enable the mapping. There still shouldn't be a type.
37 Context
.enableDebugTypeODRUniquing();
38 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
40 // Create some ODR-uniqued type.
41 auto &CT
= *DICompositeType::getODRType(
42 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr, 0, nullptr,
43 nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero
, nullptr, 0, nullptr,
44 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
45 EXPECT_EQ(UUID
.getString(), CT
.getIdentifier());
47 // Check that we get it back, even if we change a field.
48 EXPECT_EQ(&CT
, DICompositeType::getODRTypeIfExists(Context
, UUID
));
49 EXPECT_EQ(&CT
, DICompositeType::getODRType(
50 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
51 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero
,
52 nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
53 nullptr, nullptr, nullptr));
55 DICompositeType::getODRType(
56 Context
, UUID
, dwarf::DW_TAG_class_type
,
57 MDString::get(Context
, "name"), nullptr, 0, nullptr, nullptr, 0,
58 0, 0, nullptr, 0, DINode::FlagZero
, nullptr, 0, nullptr,
59 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
61 // Check that it's discarded with the type map.
62 Context
.disableDebugTypeODRUniquing();
63 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
65 // And it shouldn't magically reappear...
66 Context
.enableDebugTypeODRUniquing();
67 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
70 TEST(DebugTypeODRUniquingTest
, buildODRType
) {
72 Context
.enableDebugTypeODRUniquing();
74 // Build an ODR type that's a forward decl.
75 MDString
&UUID
= *MDString::get(Context
, "Type");
76 auto &CT
= *DICompositeType::buildODRType(
77 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr, 0, nullptr,
78 nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl
, nullptr, 0, nullptr,
79 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
80 EXPECT_EQ(&CT
, DICompositeType::getODRTypeIfExists(Context
, UUID
));
81 EXPECT_EQ(dwarf::DW_TAG_class_type
, CT
.getTag());
83 // Update with another forward decl. This should be a no-op.
84 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
85 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
86 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
87 DINode::FlagFwdDecl
, nullptr, 0, nullptr, nullptr, nullptr,
88 nullptr, nullptr, nullptr, nullptr, nullptr));
90 EXPECT_FALSE(DICompositeType::buildODRType(
91 Context
, UUID
, dwarf::DW_TAG_structure_type
, nullptr, nullptr, 0, nullptr,
92 nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl
, nullptr, 0, nullptr,
93 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
95 // Update with a definition. This time we should see a change.
96 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
97 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
98 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero
,
99 nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
100 nullptr, nullptr, nullptr));
101 EXPECT_FALSE(CT
.isForwardDecl());
103 // Further updates should be ignored.
104 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
105 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
106 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
107 DINode::FlagFwdDecl
, nullptr, 0, nullptr, nullptr, nullptr,
108 nullptr, nullptr, nullptr, nullptr, nullptr));
109 EXPECT_FALSE(CT
.isForwardDecl());
110 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
111 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
112 111u, nullptr, nullptr, 0, 0, 0, nullptr, 0,
113 DINode::FlagZero
, nullptr, 0, nullptr, nullptr, nullptr,
114 nullptr, nullptr, nullptr, nullptr, nullptr));
115 EXPECT_NE(111u, CT
.getLine());
118 TEST(DebugTypeODRUniquingTest
, buildODRTypeFields
) {
120 Context
.enableDebugTypeODRUniquing();
122 // Build an ODR type that's a forward decl with no other fields set.
123 MDString
&UUID
= *MDString::get(Context
, "UUID");
124 auto &CT
= *DICompositeType::buildODRType(
125 Context
, UUID
, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr,
126 0, DINode::FlagFwdDecl
, nullptr, 0, nullptr, nullptr, nullptr, nullptr,
127 nullptr, nullptr, nullptr, nullptr);
129 // Create macros for running through all the fields except Identifier and Flags.
130 #define FOR_EACH_MDFIELD() \
133 DO_FOR_FIELD(Scope) \
134 DO_FOR_FIELD(BaseType) \
135 DO_FOR_FIELD(Elements) \
136 DO_FOR_FIELD(VTableHolder) \
137 DO_FOR_FIELD(TemplateParams)
138 #define FOR_EACH_INLINEFIELD() \
140 DO_FOR_FIELD(SizeInBits) \
141 DO_FOR_FIELD(AlignInBits) \
142 DO_FOR_FIELD(OffsetInBits) \
143 DO_FOR_FIELD(NumExtraInhabitants) \
144 DO_FOR_FIELD(RuntimeLang)
146 // Create all the fields.
147 #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
150 unsigned NonZeroInit
= 0;
151 #define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
152 FOR_EACH_INLINEFIELD();
155 // Replace all the fields with new values that are distinct from each other.
156 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
157 Context
, UUID
, 0, Name
, File
, Line
, Scope
, BaseType
,
158 SizeInBits
, AlignInBits
, OffsetInBits
, nullptr,
159 NumExtraInhabitants
, DINode::FlagArtificial
, Elements
,
160 RuntimeLang
, VTableHolder
, TemplateParams
, nullptr,
161 nullptr, nullptr, nullptr, nullptr, nullptr));
163 // Confirm that all the right fields got updated.
164 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
167 #undef FOR_EACH_MDFIELD
168 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
169 FOR_EACH_INLINEFIELD();
171 #undef FOR_EACH_INLINEFIELD
172 EXPECT_EQ(DINode::FlagArtificial
, CT
.getFlags());
173 EXPECT_EQ(&UUID
, CT
.getRawIdentifier());