1 //===- llvm/unittest/CodeGen/DIEHashTest.cpp ------------------------------===//
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 "../lib/CodeGen/AsmPrinter/DIEHash.h"
10 #include "TestAsmPrinter.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/CodeGen/DIE.h"
14 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/TargetParser/Host.h"
18 #include "llvm/Testing/Support/Error.h"
19 #include "gtest/gtest.h"
26 class DIEHashTest
: public testing::Test
{
28 BumpPtrAllocator Alloc
;
31 StringMap
<DwarfStringPoolEntry
> Pool
;
32 std::unique_ptr
<TestAsmPrinter
> TestPrinter
;
34 void setupTestPrinter() {
35 auto ExpectedTestPrinter
= TestAsmPrinter::create(
36 sys::getDefaultTargetTriple(), /*DwarfVersion=*/4, dwarf::DWARF32
);
37 ASSERT_THAT_EXPECTED(ExpectedTestPrinter
, Succeeded());
38 TestPrinter
= std::move(ExpectedTestPrinter
.get());
42 DIEString
getString(StringRef S
) {
43 DwarfStringPoolEntry Entry
= {nullptr, 1, 1};
45 DwarfStringPoolEntryRef(*Pool
.insert(std::make_pair(S
, Entry
)).first
));
48 AsmPrinter
*getAsmPrinter() {
51 return TestPrinter
? TestPrinter
->getAP() : nullptr;
55 TEST_F(DIEHashTest
, Data1
) {
57 DIE
&Die
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
59 Die
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Size
);
60 uint64_t MD5Res
= Hash
.computeTypeSignature(Die
);
61 ASSERT_EQ(0x1AFE116E83701108ULL
, MD5Res
);
65 TEST_F(DIEHashTest
, TrivialType
) {
66 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
68 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
70 // Line and file number are ignored.
71 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
72 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
73 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
75 // The exact same hash GCC produces for this DIE.
76 ASSERT_EQ(0x715305CE6CFD9AD1ULL
, MD5Res
);
80 TEST_F(DIEHashTest
, NamedType
) {
81 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
83 DIEString FooStr
= getString("foo");
84 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
85 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
87 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
89 // The exact same hash GCC produces for this DIE.
90 ASSERT_EQ(0xD566DBD2CA5265FFULL
, MD5Res
);
93 // namespace space { struct foo { }; }
94 TEST_F(DIEHashTest
, NamespacedType
) {
95 DIE
&CU
= *DIE::get(Alloc
, dwarf::DW_TAG_compile_unit
);
97 auto Space
= DIE::get(Alloc
, dwarf::DW_TAG_namespace
);
99 DIEString SpaceStr
= getString("space");
100 Space
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, SpaceStr
);
101 // DW_AT_declaration is ignored.
102 Space
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
106 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
107 DIEString FooStr
= getString("foo");
108 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
109 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
112 Space
->addChild(std::move(Foo
));
113 CU
.addChild(std::move(Space
));
115 uint64_t MD5Res
= DIEHash().computeTypeSignature(N
);
117 // The exact same hash GCC produces for this DIE.
118 ASSERT_EQ(0x7b80381fd17f1e33ULL
, MD5Res
);
121 // struct { int member; };
122 TEST_F(DIEHashTest
, TypeWithMember
) {
123 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
125 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
127 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
128 DIEString IntStr
= getString("int");
129 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
130 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
132 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
134 DIEEntry
IntRef(Int
);
136 auto Member
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
137 DIEString MemberStr
= getString("member");
138 Member
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemberStr
);
140 Member
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
141 dwarf::DW_FORM_data1
, Zero
);
142 Member
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
144 Unnamed
.addChild(std::move(Member
));
146 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
148 ASSERT_EQ(0x5646aa436b7e07c6ULL
, MD5Res
);
151 // struct foo { int mem1, mem2; };
152 TEST_F(DIEHashTest
, ReusedType
) {
153 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
155 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
158 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
159 DIEString IntStr
= getString("int");
160 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
161 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
163 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
165 DIEEntry
IntRef(Int
);
167 auto Mem1
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
168 DIEString Mem1Str
= getString("mem1");
169 Mem1
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem1Str
);
171 Mem1
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
173 Mem1
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
175 Unnamed
.addChild(std::move(Mem1
));
177 auto Mem2
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
178 DIEString Mem2Str
= getString("mem2");
179 Mem2
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem2Str
);
180 Mem2
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
182 Mem2
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
184 Unnamed
.addChild(std::move(Mem2
));
186 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
188 ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL
, MD5Res
);
191 // struct foo { static foo f; };
192 TEST_F(DIEHashTest
, RecursiveType
) {
193 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
195 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
196 DIEString FooStr
= getString("foo");
197 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
199 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
200 DIEString MemStr
= getString("mem");
201 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
202 DIEEntry
FooRef(Foo
);
203 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
204 // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
206 Foo
.addChild(std::move(Mem
));
208 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
210 ASSERT_EQ(0x73d8b25aef227b06ULL
, MD5Res
);
213 // struct foo { foo *mem; };
214 TEST_F(DIEHashTest
, Pointer
) {
215 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
217 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
218 DIEString FooStr
= getString("foo");
219 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
221 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
222 DIEString MemStr
= getString("mem");
223 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
225 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
228 DIE
&FooPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
229 FooPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
230 DIEEntry
FooRef(Foo
);
231 FooPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
233 DIEEntry
FooPtrRef(FooPtr
);
234 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooPtrRef
);
236 Foo
.addChild(std::move(Mem
));
238 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
240 ASSERT_EQ(0x74ea73862e8708d2ULL
, MD5Res
);
243 // struct foo { foo &mem; };
244 TEST_F(DIEHashTest
, Reference
) {
245 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
247 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
248 DIEString FooStr
= getString("foo");
249 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
251 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
252 DIEString MemStr
= getString("mem");
253 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
255 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
258 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_reference_type
);
259 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
260 DIEEntry
FooEntry(Foo
);
261 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
263 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
264 DIEEntry
FooRefRef(FooRef
);
265 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
268 DIEEntry
FooRefConstRef(FooRefConst
);
269 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
271 Foo
.addChild(std::move(Mem
));
273 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
275 ASSERT_EQ(0xa0b15f467ad4525bULL
, MD5Res
);
278 // struct foo { foo &&mem; };
279 TEST_F(DIEHashTest
, RValueReference
) {
280 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
282 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
283 DIEString FooStr
= getString("foo");
284 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
286 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
287 DIEString MemStr
= getString("mem");
288 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
290 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
293 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_rvalue_reference_type
);
294 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
295 DIEEntry
FooEntry(Foo
);
296 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
298 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
299 DIEEntry
FooRefRef(FooRef
);
300 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
303 DIEEntry
FooRefConstRef(FooRefConst
);
304 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
306 Foo
.addChild(std::move(Mem
));
308 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
310 ASSERT_EQ(0xad211c8c3b31e57ULL
, MD5Res
);
313 // struct foo { foo foo::*mem; };
314 TEST_F(DIEHashTest
, PtrToMember
) {
315 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
317 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
318 DIEString FooStr
= getString("foo");
319 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
321 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
322 DIEString MemStr
= getString("mem");
323 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
325 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
328 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
329 DIEEntry
FooEntry(Foo
);
330 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
331 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
, dwarf::DW_FORM_ref4
,
334 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
335 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PtrToFooMemRef
);
337 Foo
.addChild(std::move(Mem
));
339 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
341 ASSERT_EQ(0x852e0c9ff7c04ebULL
, MD5Res
);
344 // Check that the hash for a pointer-to-member matches regardless of whether the
345 // pointed-to type is a declaration or a definition.
347 // struct bar; // { };
348 // struct foo { bar foo::*mem; };
349 TEST_F(DIEHashTest
, PtrToMemberDeclDefMatch
) {
353 DIEString FooStr
= getString("foo");
354 DIEString BarStr
= getString("bar");
355 DIEString MemStr
= getString("mem");
358 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
359 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
360 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
363 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
364 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
365 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
367 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
368 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
369 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
370 dwarf::DW_FORM_data1
, Zero
);
372 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
373 DIEEntry
BarEntry(Bar
);
374 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
376 DIEEntry
FooEntry(Foo
);
377 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
378 dwarf::DW_FORM_ref4
, FooEntry
);
380 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
381 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
384 Foo
.addChild(std::move(Mem
));
386 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
390 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
391 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
392 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
394 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
395 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
396 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
398 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
399 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
400 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
401 dwarf::DW_FORM_data1
, Zero
);
403 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
404 DIEEntry
BarEntry(Bar
);
405 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
407 DIEEntry
FooEntry(Foo
);
408 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
409 dwarf::DW_FORM_ref4
, FooEntry
);
411 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
412 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
415 Foo
.addChild(std::move(Mem
));
417 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
419 ASSERT_EQ(MD5ResDef
, MD5ResDecl
);
422 // Check that the hash for a pointer-to-member matches regardless of whether the
423 // pointed-to type is a declaration or a definition.
425 // struct bar; // { };
426 // struct foo { bar bar::*mem; };
427 TEST_F(DIEHashTest
, PtrToMemberDeclDefMisMatch
) {
431 DIEString FooStr
= getString("foo");
432 DIEString BarStr
= getString("bar");
433 DIEString MemStr
= getString("mem");
436 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
437 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
438 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
441 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
442 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
443 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
445 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
446 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
447 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
448 dwarf::DW_FORM_data1
, Zero
);
450 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
451 DIEEntry
BarEntry(Bar
);
452 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
454 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
455 dwarf::DW_FORM_ref4
, BarEntry
);
457 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
458 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
461 Foo
.addChild(std::move(Mem
));
463 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
467 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
468 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
469 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
471 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
472 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
473 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
475 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
476 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
477 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
478 dwarf::DW_FORM_data1
, Zero
);
480 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
481 DIEEntry
BarEntry(Bar
);
482 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
484 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
485 dwarf::DW_FORM_ref4
, BarEntry
);
487 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
488 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
491 Foo
.addChild(std::move(Mem
));
493 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
495 // FIXME: This seems to be a bug in the DWARF type hashing specification that
496 // only uses the brief name hashing for types referenced via DW_AT_type. In
497 // this case the type is referenced via DW_AT_containing_type and full hashing
498 // causes a hash to differ when the containing type is a declaration in one TU
499 // and a definition in another.
500 ASSERT_NE(MD5ResDef
, MD5ResDecl
);
504 // struct foo { decltype(a) mem; };
505 TEST_F(DIEHashTest
, RefUnnamedType
) {
509 DIEString FooStr
= getString("foo");
510 DIEString MemStr
= getString("mem");
512 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
513 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
515 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
516 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
517 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
519 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
520 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
521 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
524 DIE
&UnnamedPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
525 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
527 DIEEntry
UnnamedRef(Unnamed
);
528 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
531 DIEEntry
UnnamedPtrRef(UnnamedPtr
);
532 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, UnnamedPtrRef
);
534 Foo
.addChild(std::move(Mem
));
536 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
538 ASSERT_EQ(0x954e026f01c02529ULL
, MD5Res
);
541 // struct { struct foo { }; };
542 TEST_F(DIEHashTest
, NestedType
) {
543 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
545 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
547 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
548 DIEString FooStr
= getString("foo");
549 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
550 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
552 Unnamed
.addChild(std::move(Foo
));
554 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
556 // The exact same hash GCC produces for this DIE.
557 ASSERT_EQ(0xde8a3b7b43807f4aULL
, MD5Res
);
560 // struct { static void func(); };
561 TEST_F(DIEHashTest
, MemberFunc
) {
562 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
564 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
566 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
567 DIEString FuncStr
= getString("func");
568 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
570 Unnamed
.addChild(std::move(Func
));
572 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
574 // The exact same hash GCC produces for this DIE.
575 ASSERT_EQ(0xd36a1b6dfb604ba0ULL
, MD5Res
);
579 // static void func();
581 TEST_F(DIEHashTest
, MemberFuncFlag
) {
582 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
584 DIEString AStr
= getString("A");
585 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
586 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
587 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
588 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
590 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
591 DIEString FuncStr
= getString("func");
592 DIEString FuncLinkage
= getString("_ZN1A4funcEv");
594 Func
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
,
596 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
597 Func
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
598 Func
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
599 Func
->addValue(Alloc
, dwarf::DW_AT_linkage_name
, dwarf::DW_FORM_strp
,
601 Func
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
604 A
.addChild(std::move(Func
));
606 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
608 // The exact same hash GCC produces for this DIE.
609 ASSERT_EQ(0x8F78211DDCE3DF10ULL
, MD5Res
);
614 // const static int PI = -3;
617 TEST_F(DIEHashTest
, MemberSdata
) {
618 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
620 DIEString AStr
= getString("A");
621 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
622 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
623 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
624 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
628 DIEString FStr
= getString("int");
629 DIE
&IntTyDIE
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
630 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
631 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
632 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
634 DIEEntry
IntTy(IntTyDIE
);
635 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
636 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntTy
);
638 DIEEntry
PITy(*PITyDIE
);
639 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
640 DIEString PIStr
= getString("PI");
642 DIEInteger
NegThree(-3);
643 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
644 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
645 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
646 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
647 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
648 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
650 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_sdata
, NegThree
);
652 A
.addChild(std::move(PI
));
654 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
655 ASSERT_EQ(0x9A216000DD3788A7ULL
, MD5Res
);
660 // const static float PI = 3.14;
663 TEST_F(DIEHashTest
, MemberBlock
) {
664 if (!this->getAsmPrinter())
667 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
669 DIEString AStr
= getString("A");
670 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
671 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
672 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
673 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
676 DIEString FStr
= getString("float");
677 auto FloatTyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
678 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
680 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
,
682 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
683 DIEEntry
FloatTy(*FloatTyDIE
);
684 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
685 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FloatTy
);
687 DIEEntry
PITy(*PITyDIE
);
688 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
689 DIEString PIStr
= getString("PI");
691 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
692 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
693 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
694 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
695 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
696 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
700 DIEInteger
Blk1(0xc3);
701 DIEInteger
Blk2(0xf5);
702 DIEInteger
Blk3(0x48);
703 DIEInteger
Blk4(0x40);
705 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk1
);
706 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk2
);
707 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk3
);
708 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk4
);
710 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_block1
,
713 A
.addChild(std::move(PI
));
715 uint64_t MD5Res
= DIEHash(this->getAsmPrinter()).computeTypeSignature(A
);
716 ASSERT_EQ(0x493AF53AD3D3F651ULL
, MD5Res
);