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/IR/DebugInfoMetadata.h"
10 #include "llvm/IR/LLVMContext.h"
11 #include "gtest/gtest.h"
16 TEST(DebugTypeODRUniquingTest
, enableDebugTypeODRUniquing
) {
18 EXPECT_FALSE(Context
.isODRUniquingDebugTypes());
19 Context
.enableDebugTypeODRUniquing();
20 EXPECT_TRUE(Context
.isODRUniquingDebugTypes());
21 Context
.disableDebugTypeODRUniquing();
22 EXPECT_FALSE(Context
.isODRUniquingDebugTypes());
25 TEST(DebugTypeODRUniquingTest
, getODRType
) {
27 MDString
&UUID
= *MDString::get(Context
, "string");
29 // Without a type map, this should return null.
30 EXPECT_FALSE(DICompositeType::getODRType(
31 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr, 0, nullptr,
32 nullptr, 0, 0, 0, DINode::FlagZero
, nullptr, 0, nullptr, nullptr, nullptr));
34 // Enable the mapping. There still shouldn't be a type.
35 Context
.enableDebugTypeODRUniquing();
36 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
38 // Create some ODR-uniqued type.
39 auto &CT
= *DICompositeType::getODRType(
40 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr, 0, nullptr,
41 nullptr, 0, 0, 0, DINode::FlagZero
, nullptr, 0, nullptr, nullptr, nullptr);
42 EXPECT_EQ(UUID
.getString(), CT
.getIdentifier());
44 // Check that we get it back, even if we change a field.
45 EXPECT_EQ(&CT
, DICompositeType::getODRTypeIfExists(Context
, UUID
));
46 EXPECT_EQ(&CT
, DICompositeType::getODRType(
47 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
48 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero
, nullptr, 0,
49 nullptr, nullptr, nullptr));
51 DICompositeType::getODRType(
52 Context
, UUID
, dwarf::DW_TAG_class_type
,
53 MDString::get(Context
, "name"), nullptr, 0, nullptr, nullptr, 0,
54 0, 0, DINode::FlagZero
, nullptr, 0, nullptr, nullptr, nullptr));
56 // Check that it's discarded with the type map.
57 Context
.disableDebugTypeODRUniquing();
58 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
60 // And it shouldn't magically reappear...
61 Context
.enableDebugTypeODRUniquing();
62 EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context
, UUID
));
65 TEST(DebugTypeODRUniquingTest
, buildODRType
) {
67 Context
.enableDebugTypeODRUniquing();
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, nullptr);
74 EXPECT_EQ(&CT
, DICompositeType::getODRTypeIfExists(Context
, UUID
));
75 EXPECT_EQ(dwarf::DW_TAG_class_type
, CT
.getTag());
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, nullptr));
81 EXPECT_EQ(dwarf::DW_TAG_class_type
, CT
.getTag());
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,
86 nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero
,
87 nullptr, 0, nullptr, nullptr, nullptr));
88 EXPECT_EQ(dwarf::DW_TAG_structure_type
, CT
.getTag());
90 // Further updates should be ignored.
91 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
92 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr, 0, nullptr,
93 nullptr, 0, 0, 0, DINode::FlagFwdDecl
, nullptr, 0, nullptr, nullptr, nullptr));
94 EXPECT_EQ(dwarf::DW_TAG_structure_type
, CT
.getTag());
95 EXPECT_EQ(&CT
, DICompositeType::buildODRType(
96 Context
, UUID
, dwarf::DW_TAG_class_type
, nullptr, nullptr,
97 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero
, nullptr, 0,
98 nullptr, nullptr, nullptr));
99 EXPECT_EQ(dwarf::DW_TAG_structure_type
, CT
.getTag());
102 TEST(DebugTypeODRUniquingTest
, buildODRTypeFields
) {
104 Context
.enableDebugTypeODRUniquing();
106 // Build an ODR type that's a forward decl with no other fields set.
107 MDString
&UUID
= *MDString::get(Context
, "UUID");
108 auto &CT
= *DICompositeType::buildODRType(
109 Context
, UUID
, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
110 DINode::FlagFwdDecl
, nullptr, 0, nullptr, nullptr, nullptr);
112 // Create macros for running through all the fields except Identifier and Flags.
113 #define FOR_EACH_MDFIELD() \
116 DO_FOR_FIELD(Scope) \
117 DO_FOR_FIELD(BaseType) \
118 DO_FOR_FIELD(Elements) \
119 DO_FOR_FIELD(VTableHolder) \
120 DO_FOR_FIELD(TemplateParams)
121 #define FOR_EACH_INLINEFIELD() \
124 DO_FOR_FIELD(SizeInBits) \
125 DO_FOR_FIELD(AlignInBits) \
126 DO_FOR_FIELD(OffsetInBits) \
127 DO_FOR_FIELD(RuntimeLang)
129 // Create all the fields.
130 #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
133 unsigned NonZeroInit
= 0;
134 #define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
135 FOR_EACH_INLINEFIELD();
138 // Replace all the fields with new values that are distinct from each other.
140 DICompositeType::buildODRType(
141 Context
, UUID
, Tag
, Name
, File
, Line
, Scope
, BaseType
,
142 SizeInBits
, AlignInBits
, OffsetInBits
, DINode::FlagArtificial
,
143 Elements
, RuntimeLang
, VTableHolder
, TemplateParams
, nullptr));
145 // Confirm that all the right fields got updated.
146 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
149 #undef FOR_EACH_MDFIELD
150 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
151 FOR_EACH_INLINEFIELD();
153 #undef FOR_EACH_INLINEFIELD
154 EXPECT_EQ(DINode::FlagArtificial
, CT
.getFlags());
155 EXPECT_EQ(&UUID
, CT
.getRawIdentifier());