xref: /llvm-project/llvm/unittests/CodeGen/DIEHashTest.cpp (revision f5ec3a02db27ef4500a67041d50e08edd57cc6c2)
1 //===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "../lib/CodeGen/AsmPrinter/DIE.h"
11 #include "../lib/CodeGen/AsmPrinter/DIEHash.h"
12 #include "llvm/Support/Debug.h"
13 #include "llvm/Support/Dwarf.h"
14 #include "llvm/Support/Format.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 
19 namespace {
20 TEST(DIEHashTest, Data1) {
21   DIEHash Hash;
22   DIE Die(dwarf::DW_TAG_base_type);
23   DIEInteger Size(4);
24   Die.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Size);
25   uint64_t MD5Res = Hash.computeTypeSignature(Die);
26   ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
27 }
28 
29 // struct {};
30 TEST(DIEHashTest, TrivialType) {
31   DIE Unnamed(dwarf::DW_TAG_structure_type);
32   DIEInteger One(1);
33   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
34 
35   // Line and file number are ignored.
36   Unnamed.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
37   Unnamed.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
38   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
39 
40   // The exact same hash GCC produces for this DIE.
41   ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
42 }
43 
44 // struct foo { };
45 TEST(DIEHashTest, NamedType) {
46   DIE Foo(dwarf::DW_TAG_structure_type);
47   DIEInteger One(1);
48   DIEString FooStr(&One, "foo");
49   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
50   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
51 
52   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
53 
54   // The exact same hash GCC produces for this DIE.
55   ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
56 }
57 
58 // namespace space { struct foo { }; }
59 TEST(DIEHashTest, NamespacedType) {
60   DIE CU(dwarf::DW_TAG_compile_unit);
61 
62   DIE *Space = new DIE(dwarf::DW_TAG_namespace);
63   DIEInteger One(1);
64   DIEString SpaceStr(&One, "space");
65   Space->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &SpaceStr);
66   // DW_AT_declaration is ignored.
67   Space->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
68   // sibling?
69 
70   DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
71   DIEString FooStr(&One, "foo");
72   Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
73   Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
74 
75   Space->addChild(Foo);
76   CU.addChild(Space);
77 
78   uint64_t MD5Res = DIEHash().computeTypeSignature(*Foo);
79 
80   // The exact same hash GCC produces for this DIE.
81   ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
82 }
83 
84 // struct { int member; };
85 TEST(DIEHashTest, TypeWithMember) {
86   DIE Unnamed(dwarf::DW_TAG_structure_type);
87   DIEInteger Four(4);
88   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
89 
90   DIE *Member = new DIE(dwarf::DW_TAG_member);
91   DIEString MemberStr(&Four, "member");
92   Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr);
93   DIEInteger Zero(0);
94   Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
95                    &Zero);
96 
97   Unnamed.addChild(Member);
98 
99   DIE Int(dwarf::DW_TAG_base_type);
100   DIEString IntStr(&Four, "int");
101   Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
102   Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
103   DIEInteger Five(5);
104   Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
105 
106   DIEEntry IntRef(&Int);
107   Member->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
108 
109   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
110 
111   ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
112 }
113 
114 // struct foo { int mem1, mem2; };
115 TEST(DIEHashTest, ReusedType) {
116   DIE Unnamed(dwarf::DW_TAG_structure_type);
117   DIEInteger Eight(8);
118   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
119 
120   DIE *Mem1 = new DIE(dwarf::DW_TAG_member);
121   DIEInteger Four(4);
122   DIEString Mem1Str(&Four, "mem1");
123   Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str);
124   DIEInteger Zero(0);
125   Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
126                  &Zero);
127 
128   Unnamed.addChild(Mem1);
129 
130   DIE *Mem2 = new DIE(dwarf::DW_TAG_member);
131   DIEString Mem2Str(&Four, "mem2");
132   Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str);
133   Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
134                  &Four);
135 
136   Unnamed.addChild(Mem2);
137 
138   DIE Int(dwarf::DW_TAG_base_type);
139   DIEString IntStr(&Four, "int");
140   Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
141   Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
142   DIEInteger Five(5);
143   Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
144 
145   DIEEntry IntRef(&Int);
146   Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
147   Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
148 
149   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
150 
151   ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
152 }
153 
154 // struct foo { static foo f; };
155 TEST(DIEHashTest, RecursiveType) {
156   DIE Foo(dwarf::DW_TAG_structure_type);
157   DIEInteger One(1);
158   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
159   DIEString FooStr(&One, "foo");
160   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
161 
162   DIE *Mem = new DIE(dwarf::DW_TAG_member);
163   DIEString MemStr(&One, "mem");
164   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
165   DIEEntry FooRef(&Foo);
166   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
167   // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
168 
169   Foo.addChild(Mem);
170 
171   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
172 
173   ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
174 }
175 
176 // struct foo { foo *mem; };
177 TEST(DIEHashTest, Pointer) {
178   DIE Foo(dwarf::DW_TAG_structure_type);
179   DIEInteger Eight(8);
180   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
181   DIEString FooStr(&Eight, "foo");
182   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
183 
184   DIE *Mem = new DIE(dwarf::DW_TAG_member);
185   DIEString MemStr(&Eight, "mem");
186   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
187   DIEInteger Zero(0);
188   Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
189 
190   DIE FooPtr(dwarf::DW_TAG_pointer_type);
191   FooPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
192   DIEEntry FooRef(&Foo);
193   FooPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
194 
195   DIEEntry FooPtrRef(&FooPtr);
196   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooPtrRef);
197 
198   Foo.addChild(Mem);
199 
200   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
201 
202   ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
203 }
204 
205 // struct foo { foo &mem; };
206 TEST(DIEHashTest, Reference) {
207   DIE Foo(dwarf::DW_TAG_structure_type);
208   DIEInteger Eight(8);
209   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
210   DIEString FooStr(&Eight, "foo");
211   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
212 
213   DIE *Mem = new DIE(dwarf::DW_TAG_member);
214   DIEString MemStr(&Eight, "mem");
215   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
216   DIEInteger Zero(0);
217   Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
218 
219   DIE FooRef(dwarf::DW_TAG_reference_type);
220   FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
221   DIEEntry FooEntry(&Foo);
222   FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
223 
224   DIE FooRefConst(dwarf::DW_TAG_const_type);
225   DIEEntry FooRefRef(&FooRef);
226   FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
227 
228   DIEEntry FooRefConstRef(&FooRefConst);
229   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
230 
231   Foo.addChild(Mem);
232 
233   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
234 
235   ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
236 }
237 
238 // struct foo { foo &&mem; };
239 TEST(DIEHashTest, RValueReference) {
240   DIE Foo(dwarf::DW_TAG_structure_type);
241   DIEInteger Eight(8);
242   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
243   DIEString FooStr(&Eight, "foo");
244   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
245 
246   DIE *Mem = new DIE(dwarf::DW_TAG_member);
247   DIEString MemStr(&Eight, "mem");
248   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
249   DIEInteger Zero(0);
250   Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
251 
252   DIE FooRef(dwarf::DW_TAG_rvalue_reference_type);
253   FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
254   DIEEntry FooEntry(&Foo);
255   FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
256 
257   DIE FooRefConst(dwarf::DW_TAG_const_type);
258   DIEEntry FooRefRef(&FooRef);
259   FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
260 
261   DIEEntry FooRefConstRef(&FooRefConst);
262   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
263 
264   Foo.addChild(Mem);
265 
266   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
267 
268   ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
269 }
270 
271 // struct foo { foo foo::*mem; };
272 TEST(DIEHashTest, PtrToMember) {
273   DIE Foo(dwarf::DW_TAG_structure_type);
274   DIEInteger Eight(8);
275   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
276   DIEString FooStr(&Eight, "foo");
277   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
278 
279   DIE *Mem = new DIE(dwarf::DW_TAG_member);
280   DIEString MemStr(&Eight, "mem");
281   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
282   DIEInteger Zero(0);
283   Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
284 
285   DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
286   DIEEntry FooEntry(&Foo);
287   PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
288   PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
289                        &FooEntry);
290 
291   DIEEntry PtrToFooMemRef(&PtrToFooMem);
292   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
293 
294   Foo.addChild(Mem);
295 
296   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
297 
298   ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
299 }
300 
301 // Check that the hash for a pointer-to-member matches regardless of whether the
302 // pointed-to type is a declaration or a definition.
303 //
304 //   struct bar; // { };
305 //   struct foo { bar foo::*mem; };
306 TEST(DIEHashTest, PtrToMemberDeclDefMatch) {
307   DIEInteger Zero(0);
308   DIEInteger One(1);
309   DIEInteger Eight(8);
310   DIEString FooStr(&Eight, "foo");
311   DIEString BarStr(&Eight, "bar");
312   DIEString MemStr(&Eight, "mem");
313   uint64_t MD5ResDecl;
314   {
315     DIE Bar(dwarf::DW_TAG_structure_type);
316     Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
317     Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
318 
319     DIE Foo(dwarf::DW_TAG_structure_type);
320     Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
321     Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
322 
323     DIE *Mem = new DIE(dwarf::DW_TAG_member);
324     Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
325     Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
326                   &Zero);
327 
328     DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
329     DIEEntry BarEntry(&Bar);
330     PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
331     DIEEntry FooEntry(&Foo);
332     PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
333                          &FooEntry);
334 
335     DIEEntry PtrToFooMemRef(&PtrToFooMem);
336     Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
337 
338     Foo.addChild(Mem);
339 
340     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
341   }
342   uint64_t MD5ResDef;
343   {
344     DIE Bar(dwarf::DW_TAG_structure_type);
345     Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
346     Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
347 
348     DIE Foo(dwarf::DW_TAG_structure_type);
349     Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
350     Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
351 
352     DIE *Mem = new DIE(dwarf::DW_TAG_member);
353     Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
354     Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
355                   &Zero);
356 
357     DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
358     DIEEntry BarEntry(&Bar);
359     PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
360     DIEEntry FooEntry(&Foo);
361     PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
362                          &FooEntry);
363 
364     DIEEntry PtrToFooMemRef(&PtrToFooMem);
365     Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
366 
367     Foo.addChild(Mem);
368 
369     MD5ResDef = DIEHash().computeTypeSignature(Foo);
370   }
371   ASSERT_EQ(MD5ResDef, MD5ResDecl);
372 }
373 
374 // Check that the hash for a pointer-to-member matches regardless of whether the
375 // pointed-to type is a declaration or a definition.
376 //
377 //   struct bar; // { };
378 //   struct foo { bar bar::*mem; };
379 TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) {
380   DIEInteger Zero(0);
381   DIEInteger One(1);
382   DIEInteger Eight(8);
383   DIEString FooStr(&Eight, "foo");
384   DIEString BarStr(&Eight, "bar");
385   DIEString MemStr(&Eight, "mem");
386   uint64_t MD5ResDecl;
387   {
388     DIE Bar(dwarf::DW_TAG_structure_type);
389     Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
390     Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
391 
392     DIE Foo(dwarf::DW_TAG_structure_type);
393     Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
394     Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
395 
396     DIE *Mem = new DIE(dwarf::DW_TAG_member);
397     Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
398     Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
399                   &Zero);
400 
401     DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
402     DIEEntry BarEntry(&Bar);
403     PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
404     PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
405                          &BarEntry);
406 
407     DIEEntry PtrToFooMemRef(&PtrToFooMem);
408     Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
409 
410     Foo.addChild(Mem);
411 
412     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
413   }
414   uint64_t MD5ResDef;
415   {
416     DIE Bar(dwarf::DW_TAG_structure_type);
417     Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
418     Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
419 
420     DIE Foo(dwarf::DW_TAG_structure_type);
421     Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
422     Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
423 
424     DIE *Mem = new DIE(dwarf::DW_TAG_member);
425     Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
426     Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
427                   &Zero);
428 
429     DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
430     DIEEntry BarEntry(&Bar);
431     PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
432     PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
433                          &BarEntry);
434 
435     DIEEntry PtrToFooMemRef(&PtrToFooMem);
436     Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
437 
438     Foo.addChild(Mem);
439 
440     MD5ResDef = DIEHash().computeTypeSignature(Foo);
441   }
442   // FIXME: This seems to be a bug in the DWARF type hashing specification that
443   // only uses the brief name hashing for types referenced via DW_AT_type. In
444   // this case the type is referenced via DW_AT_containing_type and full hashing
445   // causes a hash to differ when the containing type is a declaration in one TU
446   // and a definition in another.
447   ASSERT_NE(MD5ResDef, MD5ResDecl);
448 }
449 
450 // struct { } a;
451 // struct foo { decltype(a) mem; };
452 TEST(DIEHashTest, RefUnnamedType) {
453   DIEInteger Zero(0);
454   DIEInteger One(1);
455   DIEInteger Eight(8);
456   DIEString FooStr(&Zero, "foo");
457   DIEString MemStr(&Zero, "mem");
458 
459   DIE Unnamed(dwarf::DW_TAG_structure_type);
460   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
461 
462   DIE Foo(dwarf::DW_TAG_structure_type);
463   Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
464   Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
465 
466   DIE *Mem = new DIE(dwarf::DW_TAG_member);
467   Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
468   Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
469 
470   DIE UnnamedPtr(dwarf::DW_TAG_pointer_type);
471   UnnamedPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
472   DIEEntry UnnamedRef(&Unnamed);
473   UnnamedPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedRef);
474 
475   DIEEntry UnnamedPtrRef(&UnnamedPtr);
476   Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedPtrRef);
477 
478   Foo.addChild(Mem);
479 
480   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
481 
482   ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
483 }
484 
485 // struct { struct foo { }; };
486 TEST(DIEHashTest, NestedType) {
487   DIE Unnamed(dwarf::DW_TAG_structure_type);
488   DIEInteger One(1);
489   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
490 
491   DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
492   DIEString FooStr(&One, "foo");
493   Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
494   Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
495 
496   Unnamed.addChild(Foo);
497 
498   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
499 
500   // The exact same hash GCC produces for this DIE.
501   ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
502 }
503 
504 // struct { static void func(); };
505 TEST(DIEHashTest, MemberFunc) {
506   DIE Unnamed(dwarf::DW_TAG_structure_type);
507   DIEInteger One(1);
508   Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
509 
510   DIE *Func = new DIE(dwarf::DW_TAG_subprogram);
511   DIEString FuncStr(&One, "func");
512   Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr);
513 
514   Unnamed.addChild(Func);
515 
516   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
517 
518   // The exact same hash GCC produces for this DIE.
519   ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
520 }
521 
522 // struct A {
523 //   static void func();
524 // };
525 TEST(DIEHashTest, MemberFuncFlag) {
526   DIE A(dwarf::DW_TAG_structure_type);
527   DIEInteger One(1);
528   DIEString AStr(&One, "A");
529   A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr);
530   A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
531   A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
532   A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
533 
534   DIE *Func = new DIE(dwarf::DW_TAG_subprogram);
535   DIEString FuncStr(&One, "func");
536   DIEString FuncLinkage(&One, "_ZN1A4funcEv");
537   DIEInteger Two(2);
538   Func->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One);
539   Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr);
540   Func->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
541   Func->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two);
542   Func->addValue(dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, &FuncLinkage);
543   Func->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
544 
545   A.addChild(Func);
546 
547   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
548 
549   // The exact same hash GCC produces for this DIE.
550   ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res);
551 }
552 
553 // Derived from:
554 // struct A {
555 //   const static int PI = -3;
556 // };
557 // A a;
558 TEST(DIEHashTest, MemberBlock) {
559   DIE A(dwarf::DW_TAG_structure_type);
560   DIEInteger One(1);
561   DIEString AStr(&One, "A");
562   A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr);
563   A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
564   A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
565   A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
566 
567   DIEInteger Four(4);
568   DIEInteger Five(5);
569   DIEString FStr(&One, "int");
570   DIE *IntTyDIE = new DIE(dwarf::DW_TAG_base_type);
571   IntTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
572   IntTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
573   IntTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr);
574 
575   DIEEntry IntTy(IntTyDIE);
576   DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type);
577   PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntTy);
578 
579   DIEEntry PITy(PITyDIE);
580   DIE *PI = new DIE(dwarf::DW_TAG_member);
581   DIEString PIStr(&One, "PI");
582   DIEInteger Two(2);
583   DIEInteger NegThree(-3);
584   PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr);
585   PI->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
586   PI->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two);
587   PI->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PITy);
588   PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One);
589   PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
590   PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, &NegThree);
591 
592   A.addChild(PI);
593 
594   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
595   ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
596 }
597 }
598