1 //===- llvm/unittest/CodeGen/DIEHashTest.cpp ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "../lib/CodeGen/AsmPrinter/DIEHash.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 "gtest/gtest.h"
24 class DIEHashTest
: public testing::Test
{
26 BumpPtrAllocator Alloc
;
29 StringMap
<DwarfStringPoolEntry
> Pool
;
32 DIEString
getString(StringRef S
) {
33 DwarfStringPoolEntry Entry
= {nullptr, 1, 1};
34 return DIEString(DwarfStringPoolEntryRef(
35 *Pool
.insert(std::make_pair(S
, Entry
)).first
, Entry
.isIndexed()));
39 TEST_F(DIEHashTest
, Data1
) {
41 DIE
&Die
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
43 Die
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Size
);
44 uint64_t MD5Res
= Hash
.computeTypeSignature(Die
);
45 ASSERT_EQ(0x1AFE116E83701108ULL
, MD5Res
);
49 TEST_F(DIEHashTest
, TrivialType
) {
50 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
52 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
54 // Line and file number are ignored.
55 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
56 Unnamed
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
57 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
59 // The exact same hash GCC produces for this DIE.
60 ASSERT_EQ(0x715305ce6cfd9ad1ULL
, MD5Res
);
64 TEST_F(DIEHashTest
, NamedType
) {
65 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
67 DIEString FooStr
= getString("foo");
68 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
69 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
71 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
73 // The exact same hash GCC produces for this DIE.
74 ASSERT_EQ(0xd566dbd2ca5265ffULL
, MD5Res
);
77 // namespace space { struct foo { }; }
78 TEST_F(DIEHashTest
, NamespacedType
) {
79 DIE
&CU
= *DIE::get(Alloc
, dwarf::DW_TAG_compile_unit
);
81 auto Space
= DIE::get(Alloc
, dwarf::DW_TAG_namespace
);
83 DIEString SpaceStr
= getString("space");
84 Space
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, SpaceStr
);
85 // DW_AT_declaration is ignored.
86 Space
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
90 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
91 DIEString FooStr
= getString("foo");
92 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
93 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
96 Space
->addChild(std::move(Foo
));
97 CU
.addChild(std::move(Space
));
99 uint64_t MD5Res
= DIEHash().computeTypeSignature(N
);
101 // The exact same hash GCC produces for this DIE.
102 ASSERT_EQ(0x7b80381fd17f1e33ULL
, MD5Res
);
105 // struct { int member; };
106 TEST_F(DIEHashTest
, TypeWithMember
) {
107 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
109 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
111 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
112 DIEString IntStr
= getString("int");
113 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
114 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
116 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
118 DIEEntry
IntRef(Int
);
120 auto Member
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
121 DIEString MemberStr
= getString("member");
122 Member
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemberStr
);
124 Member
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
125 dwarf::DW_FORM_data1
, Zero
);
126 Member
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
128 Unnamed
.addChild(std::move(Member
));
130 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
132 ASSERT_EQ(0x5646aa436b7e07c6ULL
, MD5Res
);
135 // struct foo { int mem1, mem2; };
136 TEST_F(DIEHashTest
, ReusedType
) {
137 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
139 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
142 DIE
&Int
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
143 DIEString IntStr
= getString("int");
144 Int
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, IntStr
);
145 Int
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
147 Int
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
149 DIEEntry
IntRef(Int
);
151 auto Mem1
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
152 DIEString Mem1Str
= getString("mem1");
153 Mem1
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem1Str
);
155 Mem1
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
157 Mem1
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
159 Unnamed
.addChild(std::move(Mem1
));
161 auto Mem2
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
162 DIEString Mem2Str
= getString("mem2");
163 Mem2
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, Mem2Str
);
164 Mem2
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
166 Mem2
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntRef
);
168 Unnamed
.addChild(std::move(Mem2
));
170 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
172 ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL
, MD5Res
);
175 // struct foo { static foo f; };
176 TEST_F(DIEHashTest
, RecursiveType
) {
177 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
179 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
180 DIEString FooStr
= getString("foo");
181 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
183 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
184 DIEString MemStr
= getString("mem");
185 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
186 DIEEntry
FooRef(Foo
);
187 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
188 // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
190 Foo
.addChild(std::move(Mem
));
192 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
194 ASSERT_EQ(0x73d8b25aef227b06ULL
, MD5Res
);
197 // struct foo { foo *mem; };
198 TEST_F(DIEHashTest
, Pointer
) {
199 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
201 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
202 DIEString FooStr
= getString("foo");
203 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
205 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
206 DIEString MemStr
= getString("mem");
207 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
209 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
212 DIE
&FooPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
213 FooPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
214 DIEEntry
FooRef(Foo
);
215 FooPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRef
);
217 DIEEntry
FooPtrRef(FooPtr
);
218 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooPtrRef
);
220 Foo
.addChild(std::move(Mem
));
222 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
224 ASSERT_EQ(0x74ea73862e8708d2ULL
, MD5Res
);
227 // struct foo { foo &mem; };
228 TEST_F(DIEHashTest
, Reference
) {
229 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
231 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
232 DIEString FooStr
= getString("foo");
233 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
235 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
236 DIEString MemStr
= getString("mem");
237 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
239 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
242 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_reference_type
);
243 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
244 DIEEntry
FooEntry(Foo
);
245 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
247 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
248 DIEEntry
FooRefRef(FooRef
);
249 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
252 DIEEntry
FooRefConstRef(FooRefConst
);
253 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
255 Foo
.addChild(std::move(Mem
));
257 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
259 ASSERT_EQ(0xa0b15f467ad4525bULL
, MD5Res
);
262 // struct foo { foo &&mem; };
263 TEST_F(DIEHashTest
, RValueReference
) {
264 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
266 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
267 DIEString FooStr
= getString("foo");
268 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
270 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
271 DIEString MemStr
= getString("mem");
272 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
274 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
277 DIE
&FooRef
= *DIE::get(Alloc
, dwarf::DW_TAG_rvalue_reference_type
);
278 FooRef
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
279 DIEEntry
FooEntry(Foo
);
280 FooRef
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
282 DIE
&FooRefConst
= *DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
283 DIEEntry
FooRefRef(FooRef
);
284 FooRefConst
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
287 DIEEntry
FooRefConstRef(FooRefConst
);
288 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooRefConstRef
);
290 Foo
.addChild(std::move(Mem
));
292 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
294 ASSERT_EQ(0xad211c8c3b31e57ULL
, MD5Res
);
297 // struct foo { foo foo::*mem; };
298 TEST_F(DIEHashTest
, PtrToMember
) {
299 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
301 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
302 DIEString FooStr
= getString("foo");
303 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
305 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
306 DIEString MemStr
= getString("mem");
307 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
309 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
312 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
313 DIEEntry
FooEntry(Foo
);
314 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FooEntry
);
315 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
, dwarf::DW_FORM_ref4
,
318 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
319 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PtrToFooMemRef
);
321 Foo
.addChild(std::move(Mem
));
323 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
325 ASSERT_EQ(0x852e0c9ff7c04ebULL
, MD5Res
);
328 // Check that the hash for a pointer-to-member matches regardless of whether the
329 // pointed-to type is a declaration or a definition.
331 // struct bar; // { };
332 // struct foo { bar foo::*mem; };
333 TEST_F(DIEHashTest
, PtrToMemberDeclDefMatch
) {
337 DIEString FooStr
= getString("foo");
338 DIEString BarStr
= getString("bar");
339 DIEString MemStr
= getString("mem");
342 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
343 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
344 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
347 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
348 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
349 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
351 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
352 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
353 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
354 dwarf::DW_FORM_data1
, Zero
);
356 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
357 DIEEntry
BarEntry(Bar
);
358 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
360 DIEEntry
FooEntry(Foo
);
361 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
362 dwarf::DW_FORM_ref4
, FooEntry
);
364 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
365 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
368 Foo
.addChild(std::move(Mem
));
370 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
374 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
375 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
376 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
378 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
379 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
380 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
382 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
383 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
384 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
385 dwarf::DW_FORM_data1
, Zero
);
387 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
388 DIEEntry
BarEntry(Bar
);
389 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
391 DIEEntry
FooEntry(Foo
);
392 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
393 dwarf::DW_FORM_ref4
, FooEntry
);
395 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
396 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
399 Foo
.addChild(std::move(Mem
));
401 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
403 ASSERT_EQ(MD5ResDef
, MD5ResDecl
);
406 // Check that the hash for a pointer-to-member matches regardless of whether the
407 // pointed-to type is a declaration or a definition.
409 // struct bar; // { };
410 // struct foo { bar bar::*mem; };
411 TEST_F(DIEHashTest
, PtrToMemberDeclDefMisMatch
) {
415 DIEString FooStr
= getString("foo");
416 DIEString BarStr
= getString("bar");
417 DIEString MemStr
= getString("mem");
420 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
421 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
422 Bar
.addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
425 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
426 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
427 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
429 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
430 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
431 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
432 dwarf::DW_FORM_data1
, Zero
);
434 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
435 DIEEntry
BarEntry(Bar
);
436 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
438 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
439 dwarf::DW_FORM_ref4
, BarEntry
);
441 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
442 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
445 Foo
.addChild(std::move(Mem
));
447 MD5ResDecl
= DIEHash().computeTypeSignature(Foo
);
451 DIE
&Bar
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
452 Bar
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, BarStr
);
453 Bar
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
455 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
456 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
457 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
459 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
460 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
461 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
,
462 dwarf::DW_FORM_data1
, Zero
);
464 DIE
&PtrToFooMem
= *DIE::get(Alloc
, dwarf::DW_TAG_ptr_to_member_type
);
465 DIEEntry
BarEntry(Bar
);
466 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
468 PtrToFooMem
.addValue(Alloc
, dwarf::DW_AT_containing_type
,
469 dwarf::DW_FORM_ref4
, BarEntry
);
471 DIEEntry
PtrToFooMemRef(PtrToFooMem
);
472 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
475 Foo
.addChild(std::move(Mem
));
477 MD5ResDef
= DIEHash().computeTypeSignature(Foo
);
479 // FIXME: This seems to be a bug in the DWARF type hashing specification that
480 // only uses the brief name hashing for types referenced via DW_AT_type. In
481 // this case the type is referenced via DW_AT_containing_type and full hashing
482 // causes a hash to differ when the containing type is a declaration in one TU
483 // and a definition in another.
484 ASSERT_NE(MD5ResDef
, MD5ResDecl
);
488 // struct foo { decltype(a) mem; };
489 TEST_F(DIEHashTest
, RefUnnamedType
) {
493 DIEString FooStr
= getString("foo");
494 DIEString MemStr
= getString("mem");
496 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
497 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
499 DIE
&Foo
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
500 Foo
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Eight
);
501 Foo
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
503 auto Mem
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
504 Mem
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, MemStr
);
505 Mem
->addValue(Alloc
, dwarf::DW_AT_data_member_location
, dwarf::DW_FORM_data1
,
508 DIE
&UnnamedPtr
= *DIE::get(Alloc
, dwarf::DW_TAG_pointer_type
);
509 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
511 DIEEntry
UnnamedRef(Unnamed
);
512 UnnamedPtr
.addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
,
515 DIEEntry
UnnamedPtrRef(UnnamedPtr
);
516 Mem
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, UnnamedPtrRef
);
518 Foo
.addChild(std::move(Mem
));
520 uint64_t MD5Res
= DIEHash().computeTypeSignature(Foo
);
522 ASSERT_EQ(0x954e026f01c02529ULL
, MD5Res
);
525 // struct { struct foo { }; };
526 TEST_F(DIEHashTest
, NestedType
) {
527 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
529 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
531 auto Foo
= DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
532 DIEString FooStr
= getString("foo");
533 Foo
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FooStr
);
534 Foo
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
536 Unnamed
.addChild(std::move(Foo
));
538 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
540 // The exact same hash GCC produces for this DIE.
541 ASSERT_EQ(0xde8a3b7b43807f4aULL
, MD5Res
);
544 // struct { static void func(); };
545 TEST_F(DIEHashTest
, MemberFunc
) {
546 DIE
&Unnamed
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
548 Unnamed
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
550 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
551 DIEString FuncStr
= getString("func");
552 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
554 Unnamed
.addChild(std::move(Func
));
556 uint64_t MD5Res
= DIEHash().computeTypeSignature(Unnamed
);
558 // The exact same hash GCC produces for this DIE.
559 ASSERT_EQ(0xd36a1b6dfb604ba0ULL
, MD5Res
);
563 // static void func();
565 TEST_F(DIEHashTest
, MemberFuncFlag
) {
566 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
568 DIEString AStr
= getString("A");
569 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
570 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
571 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
572 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
574 auto Func
= DIE::get(Alloc
, dwarf::DW_TAG_subprogram
);
575 DIEString FuncStr
= getString("func");
576 DIEString FuncLinkage
= getString("_ZN1A4funcEv");
578 Func
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
,
580 Func
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FuncStr
);
581 Func
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
582 Func
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
583 Func
->addValue(Alloc
, dwarf::DW_AT_linkage_name
, dwarf::DW_FORM_strp
,
585 Func
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
588 A
.addChild(std::move(Func
));
590 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
592 // The exact same hash GCC produces for this DIE.
593 ASSERT_EQ(0x8f78211ddce3df10ULL
, MD5Res
);
598 // const static int PI = -3;
601 TEST_F(DIEHashTest
, MemberSdata
) {
602 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
604 DIEString AStr
= getString("A");
605 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
606 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
607 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
608 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
612 DIEString FStr
= getString("int");
613 DIE
&IntTyDIE
= *DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
614 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, Four
);
615 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
, Five
);
616 IntTyDIE
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
618 DIEEntry
IntTy(IntTyDIE
);
619 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
620 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, IntTy
);
622 DIEEntry
PITy(*PITyDIE
);
623 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
624 DIEString PIStr
= getString("PI");
626 DIEInteger
NegThree(-3);
627 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
628 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
629 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
630 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
631 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
632 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
634 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_sdata
, NegThree
);
636 A
.addChild(std::move(PI
));
638 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
639 ASSERT_EQ(0x9a216000dd3788a7ULL
, MD5Res
);
644 // const static float PI = 3.14;
647 TEST_F(DIEHashTest
, MemberBlock
) {
648 DIE
&A
= *DIE::get(Alloc
, dwarf::DW_TAG_structure_type
);
650 DIEString AStr
= getString("A");
651 A
.addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, AStr
);
652 A
.addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
, One
);
653 A
.addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
654 A
.addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, One
);
657 DIEString FStr
= getString("float");
658 auto FloatTyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_base_type
);
659 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_byte_size
, dwarf::DW_FORM_data1
,
661 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_encoding
, dwarf::DW_FORM_data1
,
663 FloatTyDIE
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, FStr
);
664 DIEEntry
FloatTy(*FloatTyDIE
);
665 auto PITyDIE
= DIE::get(Alloc
, dwarf::DW_TAG_const_type
);
666 PITyDIE
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, FloatTy
);
668 DIEEntry
PITy(*PITyDIE
);
669 auto PI
= DIE::get(Alloc
, dwarf::DW_TAG_member
);
670 DIEString PIStr
= getString("PI");
672 PI
->addValue(Alloc
, dwarf::DW_AT_name
, dwarf::DW_FORM_strp
, PIStr
);
673 PI
->addValue(Alloc
, dwarf::DW_AT_decl_file
, dwarf::DW_FORM_data1
, One
);
674 PI
->addValue(Alloc
, dwarf::DW_AT_decl_line
, dwarf::DW_FORM_data1
, Two
);
675 PI
->addValue(Alloc
, dwarf::DW_AT_type
, dwarf::DW_FORM_ref4
, PITy
);
676 PI
->addValue(Alloc
, dwarf::DW_AT_external
, dwarf::DW_FORM_flag_present
, One
);
677 PI
->addValue(Alloc
, dwarf::DW_AT_declaration
, dwarf::DW_FORM_flag_present
,
681 DIEInteger
Blk1(0xc3);
682 DIEInteger
Blk2(0xf5);
683 DIEInteger
Blk3(0x48);
684 DIEInteger
Blk4(0x40);
686 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk1
);
687 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk2
);
688 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk3
);
689 PIBlock
.addValue(Alloc
, (dwarf::Attribute
)0, dwarf::DW_FORM_data1
, Blk4
);
691 PI
->addValue(Alloc
, dwarf::DW_AT_const_value
, dwarf::DW_FORM_block1
,
694 A
.addChild(std::move(PI
));
696 uint64_t MD5Res
= DIEHash().computeTypeSignature(A
);
697 ASSERT_EQ(0x493af53ad3d3f651ULL
, MD5Res
);