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 "llvm/ADT/STLExtras.h"
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/CodeGen/DIE.h"
13 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Format.h"
16 #include "gtest/gtest.h"
23 class DIEHashTest
: public testing::Test
{
25 BumpPtrAllocator Alloc
;
28 StringMap
<DwarfStringPoolEntry
> Pool
;
31 DIEString
getString(StringRef S
) {
32 DwarfStringPoolEntry Entry
= {nullptr, 1, 1};
33 return DIEString(DwarfStringPoolEntryRef(
34 *Pool
.insert(std::make_pair(S
, Entry
)).first
, Entry
.isIndexed()));
38 TEST_F(DIEHashTest
, Data1
) {
40 DIE
&Die
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
42 Die
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Size
);
43 uint64_t MD5Res
= Hash
.computeTypeSignature(Die
);
44 ASSERT_EQ(0x1AFE116E83701108ULL
, MD5Res
);
48 TEST_F(DIEHashTest
, TrivialType
) {
49 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
51 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
53 // Line and file number are ignored.
54 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
55 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
56 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
58 // The exact same hash GCC produces for this DIE.
59 ASSERT_EQ(0x715305ce6cfd9ad1ULL
, MD5Res
);
63 TEST_F(DIEHashTest
, NamedType
) {
64 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
66 DIEString FooStr
= getString("foo");
67 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
68 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
70 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
72 // The exact same hash GCC produces for this DIE.
73 ASSERT_EQ(0xd566dbd2ca5265ffULL
, MD5Res
);
76 // namespace space { struct foo { }; }
77 TEST_F(DIEHashTest
, NamespacedType
) {
78 DIE
&CU
= *DIE::get(Alloc
, dwarf::DW_TAG_compile_unit
);
80 auto Space
= DIE::get(Alloc
, dwarf::DW_TAG_namespace
);
82 DIEString SpaceStr
= getString("space");
83 Space
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, SpaceStr
);
84 // DW_AT_declaration is ignored.
85 Space
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
89 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
90 DIEString FooStr
= getString("foo");
91 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
92 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
95 Space
->addChild(std::move(Foo
));
96 CU
.addChild(std::move(Space
));
98 uint64_t MD5Res
= DIEHash().computeTypeSignature(N
);
100 // The exact same hash GCC produces for this DIE.
101 ASSERT_EQ(0x7b80381fd17f1e33ULL
, MD5Res
);
104 // struct { int member; };
105 TEST_F(DIEHashTest
, TypeWithMember
) {
106 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
108 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
110 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
111 DIEString IntStr
= getString("int");
112 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
113 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
115 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
117 DIEEntry
IntRef(Int
);
119 auto Member
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
120 DIEString MemberStr
= getString("member");
121 Member
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemberStr
);
123 Member
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
124 dwarf::DW_FORM_data1
, Zero
);
125 Member
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
127 Unnamed
.addChild(std::move(Member
));
129 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
131 ASSERT_EQ(0x5646aa436b7e07c6ULL
, MD5Res
);
134 // struct foo { int mem1, mem2; };
135 TEST_F(DIEHashTest
, ReusedType
) {
136 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
138 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
141 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
142 DIEString IntStr
= getString("int");
143 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
144 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
146 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
148 DIEEntry
IntRef(Int
);
150 auto Mem1
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
151 DIEString Mem1Str
= getString("mem1");
152 Mem1
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem1Str
);
154 Mem1
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
156 Mem1
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
158 Unnamed
.addChild(std::move(Mem1
));
160 auto Mem2
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
161 DIEString Mem2Str
= getString("mem2");
162 Mem2
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem2Str
);
163 Mem2
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
165 Mem2
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
167 Unnamed
.addChild(std::move(Mem2
));
169 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
171 ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL
, MD5Res
);
174 // struct foo { static foo f; };
175 TEST_F(DIEHashTest
, RecursiveType
) {
176 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
178 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
179 DIEString FooStr
= getString("foo");
180 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
182 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
183 DIEString MemStr
= getString("mem");
184 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
185 DIEEntry
FooRef(Foo
);
186 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
187 // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
189 Foo
.addChild(std::move(Mem
));
191 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
193 ASSERT_EQ(0x73d8b25aef227b06ULL
, MD5Res
);
196 // struct foo { foo *mem; };
197 TEST_F(DIEHashTest
, Pointer
) {
198 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
200 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
201 DIEString FooStr
= getString("foo");
202 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
204 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
205 DIEString MemStr
= getString("mem");
206 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
208 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
211 DIE
&FooPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
212 FooPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
213 DIEEntry
FooRef(Foo
);
214 FooPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
216 DIEEntry
FooPtrRef(FooPtr
);
217 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooPtrRef
);
219 Foo
.addChild(std::move(Mem
));
221 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
223 ASSERT_EQ(0x74ea73862e8708d2ULL
, MD5Res
);
226 // struct foo { foo &mem; };
227 TEST_F(DIEHashTest
, Reference
) {
228 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
230 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
231 DIEString FooStr
= getString("foo");
232 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
234 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
235 DIEString MemStr
= getString("mem");
236 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
238 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
241 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_reference_type
);
242 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
243 DIEEntry
FooEntry(Foo
);
244 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
246 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
247 DIEEntry
FooRefRef(FooRef
);
248 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
251 DIEEntry
FooRefConstRef(FooRefConst
);
252 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
254 Foo
.addChild(std::move(Mem
));
256 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
258 ASSERT_EQ(0xa0b15f467ad4525bULL
, MD5Res
);
261 // struct foo { foo &&mem; };
262 TEST_F(DIEHashTest
, RValueReference
) {
263 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
265 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
266 DIEString FooStr
= getString("foo");
267 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
269 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
270 DIEString MemStr
= getString("mem");
271 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
273 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
276 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_rvalue_reference_type
);
277 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
278 DIEEntry
FooEntry(Foo
);
279 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
281 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
282 DIEEntry
FooRefRef(FooRef
);
283 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
286 DIEEntry
FooRefConstRef(FooRefConst
);
287 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
289 Foo
.addChild(std::move(Mem
));
291 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
293 ASSERT_EQ(0xad211c8c3b31e57ULL
, MD5Res
);
296 // struct foo { foo foo::*mem; };
297 TEST_F(DIEHashTest
, PtrToMember
) {
298 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
300 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
301 DIEString FooStr
= getString("foo");
302 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
304 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
305 DIEString MemStr
= getString("mem");
306 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
308 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
311 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
312 DIEEntry
FooEntry(Foo
);
313 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
314 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
, dwarf::DW_FORM_ref4
,
317 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
318 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PtrToFooMemRef
);
320 Foo
.addChild(std::move(Mem
));
322 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
324 ASSERT_EQ(0x852e0c9ff7c04ebULL
, MD5Res
);
327 // Check that the hash for a pointer-to-member matches regardless of whether the
328 // pointed-to type is a declaration or a definition.
330 // struct bar; // { };
331 // struct foo { bar foo::*mem; };
332 TEST_F(DIEHashTest
, PtrToMemberDeclDefMatch
) {
336 DIEString FooStr
= getString("foo");
337 DIEString BarStr
= getString("bar");
338 DIEString MemStr
= getString("mem");
341 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
342 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
343 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
346 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
347 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
348 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
350 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
351 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
352 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
353 dwarf::DW_FORM_data1
, Zero
);
355 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
356 DIEEntry
BarEntry(Bar
);
357 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
359 DIEEntry
FooEntry(Foo
);
360 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
361 dwarf::DW_FORM_ref4
, FooEntry
);
363 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
364 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
367 Foo
.addChild(std::move(Mem
));
369 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
373 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
374 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
375 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
377 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
378 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
379 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
381 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
382 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
383 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
384 dwarf::DW_FORM_data1
, Zero
);
386 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
387 DIEEntry
BarEntry(Bar
);
388 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
390 DIEEntry
FooEntry(Foo
);
391 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
392 dwarf::DW_FORM_ref4
, FooEntry
);
394 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
395 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
398 Foo
.addChild(std::move(Mem
));
400 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
402 ASSERT_EQ(MD5ResDef
, MD5ResDecl
);
405 // Check that the hash for a pointer-to-member matches regardless of whether the
406 // pointed-to type is a declaration or a definition.
408 // struct bar; // { };
409 // struct foo { bar bar::*mem; };
410 TEST_F(DIEHashTest
, PtrToMemberDeclDefMisMatch
) {
414 DIEString FooStr
= getString("foo");
415 DIEString BarStr
= getString("bar");
416 DIEString MemStr
= getString("mem");
419 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
420 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
421 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
424 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
425 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
426 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
428 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
429 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
430 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
431 dwarf::DW_FORM_data1
, Zero
);
433 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
434 DIEEntry
BarEntry(Bar
);
435 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
437 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
438 dwarf::DW_FORM_ref4
, BarEntry
);
440 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
441 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
444 Foo
.addChild(std::move(Mem
));
446 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
450 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
451 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
452 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
454 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
455 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
456 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
458 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
459 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
460 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
461 dwarf::DW_FORM_data1
, Zero
);
463 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
464 DIEEntry
BarEntry(Bar
);
465 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
467 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
468 dwarf::DW_FORM_ref4
, BarEntry
);
470 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
471 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
474 Foo
.addChild(std::move(Mem
));
476 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
478 // FIXME: This seems to be a bug in the DWARF type hashing specification that
479 // only uses the brief name hashing for types referenced via DW_AT_type. In
480 // this case the type is referenced via DW_AT_containing_type and full hashing
481 // causes a hash to differ when the containing type is a declaration in one TU
482 // and a definition in another.
483 ASSERT_NE(MD5ResDef
, MD5ResDecl
);
487 // struct foo { decltype(a) mem; };
488 TEST_F(DIEHashTest
, RefUnnamedType
) {
492 DIEString FooStr
= getString("foo");
493 DIEString MemStr
= getString("mem");
495 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
496 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
498 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
499 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
500 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
502 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
503 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
504 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
507 DIE
&UnnamedPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
508 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
510 DIEEntry
UnnamedRef(Unnamed
);
511 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
514 DIEEntry
UnnamedPtrRef(UnnamedPtr
);
515 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, UnnamedPtrRef
);
517 Foo
.addChild(std::move(Mem
));
519 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
521 ASSERT_EQ(0x954e026f01c02529ULL
, MD5Res
);
524 // struct { struct foo { }; };
525 TEST_F(DIEHashTest
, NestedType
) {
526 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
528 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
530 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
531 DIEString FooStr
= getString("foo");
532 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
533 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
535 Unnamed
.addChild(std::move(Foo
));
537 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
539 // The exact same hash GCC produces for this DIE.
540 ASSERT_EQ(0xde8a3b7b43807f4aULL
, MD5Res
);
543 // struct { static void func(); };
544 TEST_F(DIEHashTest
, MemberFunc
) {
545 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
547 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
549 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
550 DIEString FuncStr
= getString("func");
551 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
553 Unnamed
.addChild(std::move(Func
));
555 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
557 // The exact same hash GCC produces for this DIE.
558 ASSERT_EQ(0xd36a1b6dfb604ba0ULL
, MD5Res
);
562 // static void func();
564 TEST_F(DIEHashTest
, MemberFuncFlag
) {
565 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
567 DIEString AStr
= getString("A");
568 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
569 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
570 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
571 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
573 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
574 DIEString FuncStr
= getString("func");
575 DIEString FuncLinkage
= getString("_ZN1A4funcEv");
577 Func
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
,
579 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
580 Func
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
581 Func
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
582 Func
->addValue(Alloc
, dwarf::DW_AT_linkage_name
, dwarf::DW_FORM_strp
,
584 Func
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
587 A
.addChild(std::move(Func
));
589 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
591 // The exact same hash GCC produces for this DIE.
592 ASSERT_EQ(0x8f78211ddce3df10ULL
, MD5Res
);
597 // const static int PI = -3;
600 TEST_F(DIEHashTest
, MemberSdata
) {
601 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
603 DIEString AStr
= getString("A");
604 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
605 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
606 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
607 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
611 DIEString FStr
= getString("int");
612 DIE
&IntTyDIE
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
613 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
614 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
615 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
617 DIEEntry
IntTy(IntTyDIE
);
618 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
619 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntTy
);
621 DIEEntry
PITy(*PITyDIE
);
622 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
623 DIEString PIStr
= getString("PI");
625 DIEInteger
NegThree(-3);
626 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
627 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
628 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
629 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
630 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
631 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
633 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_sdata
, NegThree
);
635 A
.addChild(std::move(PI
));
637 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
638 ASSERT_EQ(0x9a216000dd3788a7ULL
, MD5Res
);
643 // const static float PI = 3.14;
646 TEST_F(DIEHashTest
, MemberBlock
) {
647 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
649 DIEString AStr
= getString("A");
650 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
651 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
652 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
653 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
656 DIEString FStr
= getString("float");
657 auto FloatTyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
658 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
660 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
,
662 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
663 DIEEntry
FloatTy(*FloatTyDIE
);
664 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
665 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FloatTy
);
667 DIEEntry
PITy(*PITyDIE
);
668 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
669 DIEString PIStr
= getString("PI");
671 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
672 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
673 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
674 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
675 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
676 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
680 DIEInteger
Blk1(0xc3);
681 DIEInteger
Blk2(0xf5);
682 DIEInteger
Blk3(0x48);
683 DIEInteger
Blk4(0x40);
685 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk1
);
686 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk2
);
687 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk3
);
688 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk4
);
690 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_block1
,
693 A
.addChild(std::move(PI
));
695 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
696 ASSERT_EQ(0x493af53ad3d3f651ULL
, MD5Res
);