1 //===- llvm/unittest/CodeGen/DIEHashTest.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/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"
18 
19 using namespace llvm;
20 
21 namespace {
22 
23 // Test fixture
24 class DIEHashTest : public testing::Test {
25 public:
26   BumpPtrAllocator Alloc;
27 
28 private:
29   StringMap<DwarfStringPoolEntry> Pool;
30 
31 public:
getString(StringRef S)32   DIEString getString(StringRef S) {
33     DwarfStringPoolEntry Entry = {nullptr, 1, 1};
34     return DIEString(
35         DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S, Entry)).first));
36   }
37 };
38 
TEST_F(DIEHashTest,Data1)39 TEST_F(DIEHashTest, Data1) {
40   DIEHash Hash;
41   DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
42   DIEInteger Size(4);
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);
46 }
47 
48 // struct {};
TEST_F(DIEHashTest,TrivialType)49 TEST_F(DIEHashTest, TrivialType) {
50   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
51   DIEInteger One(1);
52   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
53 
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);
58 
59   // The exact same hash GCC produces for this DIE.
60   ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
61 }
62 
63 // struct foo { };
TEST_F(DIEHashTest,NamedType)64 TEST_F(DIEHashTest, NamedType) {
65   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
66   DIEInteger One(1);
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);
70 
71   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
72 
73   // The exact same hash GCC produces for this DIE.
74   ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
75 }
76 
77 // namespace space { struct foo { }; }
TEST_F(DIEHashTest,NamespacedType)78 TEST_F(DIEHashTest, NamespacedType) {
79   DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit);
80 
81   auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace);
82   DIEInteger One(1);
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,
87                   One);
88   // sibling?
89 
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);
94 
95   DIE &N = *Foo;
96   Space->addChild(std::move(Foo));
97   CU.addChild(std::move(Space));
98 
99   uint64_t MD5Res = DIEHash().computeTypeSignature(N);
100 
101   // The exact same hash GCC produces for this DIE.
102   ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
103 }
104 
105 // struct { int member; };
TEST_F(DIEHashTest,TypeWithMember)106 TEST_F(DIEHashTest, TypeWithMember) {
107   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
108   DIEInteger Four(4);
109   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
110 
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);
115   DIEInteger Five(5);
116   Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
117 
118   DIEEntry IntRef(Int);
119 
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);
123   DIEInteger Zero(0);
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);
127 
128   Unnamed.addChild(std::move(Member));
129 
130   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
131 
132   ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
133 }
134 
135 // struct foo { int mem1, mem2; };
TEST_F(DIEHashTest,ReusedType)136 TEST_F(DIEHashTest, ReusedType) {
137   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
138   DIEInteger Eight(8);
139   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
140 
141   DIEInteger Four(4);
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);
146   DIEInteger Five(5);
147   Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
148 
149   DIEEntry IntRef(Int);
150 
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);
154   DIEInteger Zero(0);
155   Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
156                  Zero);
157   Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
158 
159   Unnamed.addChild(std::move(Mem1));
160 
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,
165                  Four);
166   Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
167 
168   Unnamed.addChild(std::move(Mem2));
169 
170   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
171 
172   ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
173 }
174 
175 // struct foo { static foo f; };
TEST_F(DIEHashTest,RecursiveType)176 TEST_F(DIEHashTest, RecursiveType) {
177   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
178   DIEInteger One(1);
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);
182 
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.
189 
190   Foo.addChild(std::move(Mem));
191 
192   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
193 
194   ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
195 }
196 
197 // struct foo { foo *mem; };
TEST_F(DIEHashTest,Pointer)198 TEST_F(DIEHashTest, Pointer) {
199   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
200   DIEInteger Eight(8);
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);
204 
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);
208   DIEInteger Zero(0);
209   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
210                 Zero);
211 
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);
216 
217   DIEEntry FooPtrRef(FooPtr);
218   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef);
219 
220   Foo.addChild(std::move(Mem));
221 
222   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
223 
224   ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
225 }
226 
227 // struct foo { foo &mem; };
TEST_F(DIEHashTest,Reference)228 TEST_F(DIEHashTest, Reference) {
229   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
230   DIEInteger Eight(8);
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);
234 
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);
238   DIEInteger Zero(0);
239   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
240                 Zero);
241 
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);
246 
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,
250                        FooRefRef);
251 
252   DIEEntry FooRefConstRef(FooRefConst);
253   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
254 
255   Foo.addChild(std::move(Mem));
256 
257   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
258 
259   ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
260 }
261 
262 // struct foo { foo &&mem; };
TEST_F(DIEHashTest,RValueReference)263 TEST_F(DIEHashTest, RValueReference) {
264   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
265   DIEInteger Eight(8);
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);
269 
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);
273   DIEInteger Zero(0);
274   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
275                 Zero);
276 
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);
281 
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,
285                        FooRefRef);
286 
287   DIEEntry FooRefConstRef(FooRefConst);
288   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
289 
290   Foo.addChild(std::move(Mem));
291 
292   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
293 
294   ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
295 }
296 
297 // struct foo { foo foo::*mem; };
TEST_F(DIEHashTest,PtrToMember)298 TEST_F(DIEHashTest, PtrToMember) {
299   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
300   DIEInteger Eight(8);
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);
304 
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);
308   DIEInteger Zero(0);
309   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
310                 Zero);
311 
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,
316                        FooEntry);
317 
318   DIEEntry PtrToFooMemRef(PtrToFooMem);
319   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef);
320 
321   Foo.addChild(std::move(Mem));
322 
323   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
324 
325   ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
326 }
327 
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.
330 //
331 //   struct bar; // { };
332 //   struct foo { bar foo::*mem; };
TEST_F(DIEHashTest,PtrToMemberDeclDefMatch)333 TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) {
334   DIEInteger Zero(0);
335   DIEInteger One(1);
336   DIEInteger Eight(8);
337   DIEString FooStr = getString("foo");
338   DIEString BarStr = getString("bar");
339   DIEString MemStr = getString("mem");
340   uint64_t MD5ResDecl;
341   {
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,
345                  One);
346 
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);
350 
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);
355 
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,
359                          BarEntry);
360     DIEEntry FooEntry(Foo);
361     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
362                          dwarf::DW_FORM_ref4, FooEntry);
363 
364     DIEEntry PtrToFooMemRef(PtrToFooMem);
365     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
366                   PtrToFooMemRef);
367 
368     Foo.addChild(std::move(Mem));
369 
370     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
371   }
372   uint64_t MD5ResDef;
373   {
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);
377 
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);
381 
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);
386 
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,
390                          BarEntry);
391     DIEEntry FooEntry(Foo);
392     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
393                          dwarf::DW_FORM_ref4, FooEntry);
394 
395     DIEEntry PtrToFooMemRef(PtrToFooMem);
396     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
397                   PtrToFooMemRef);
398 
399     Foo.addChild(std::move(Mem));
400 
401     MD5ResDef = DIEHash().computeTypeSignature(Foo);
402   }
403   ASSERT_EQ(MD5ResDef, MD5ResDecl);
404 }
405 
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.
408 //
409 //   struct bar; // { };
410 //   struct foo { bar bar::*mem; };
TEST_F(DIEHashTest,PtrToMemberDeclDefMisMatch)411 TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) {
412   DIEInteger Zero(0);
413   DIEInteger One(1);
414   DIEInteger Eight(8);
415   DIEString FooStr = getString("foo");
416   DIEString BarStr = getString("bar");
417   DIEString MemStr = getString("mem");
418   uint64_t MD5ResDecl;
419   {
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,
423                  One);
424 
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);
428 
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);
433 
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,
437                          BarEntry);
438     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
439                          dwarf::DW_FORM_ref4, BarEntry);
440 
441     DIEEntry PtrToFooMemRef(PtrToFooMem);
442     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
443                   PtrToFooMemRef);
444 
445     Foo.addChild(std::move(Mem));
446 
447     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
448   }
449   uint64_t MD5ResDef;
450   {
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);
454 
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);
458 
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);
463 
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,
467                          BarEntry);
468     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
469                          dwarf::DW_FORM_ref4, BarEntry);
470 
471     DIEEntry PtrToFooMemRef(PtrToFooMem);
472     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
473                   PtrToFooMemRef);
474 
475     Foo.addChild(std::move(Mem));
476 
477     MD5ResDef = DIEHash().computeTypeSignature(Foo);
478   }
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);
485 }
486 
487 // struct { } a;
488 // struct foo { decltype(a) mem; };
TEST_F(DIEHashTest,RefUnnamedType)489 TEST_F(DIEHashTest, RefUnnamedType) {
490   DIEInteger Zero(0);
491   DIEInteger One(1);
492   DIEInteger Eight(8);
493   DIEString FooStr = getString("foo");
494   DIEString MemStr = getString("mem");
495 
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);
498 
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);
502 
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,
506                 Zero);
507 
508   DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
509   UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
510                       Eight);
511   DIEEntry UnnamedRef(Unnamed);
512   UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
513                       UnnamedRef);
514 
515   DIEEntry UnnamedPtrRef(UnnamedPtr);
516   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef);
517 
518   Foo.addChild(std::move(Mem));
519 
520   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
521 
522   ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
523 }
524 
525 // struct { struct foo { }; };
TEST_F(DIEHashTest,NestedType)526 TEST_F(DIEHashTest, NestedType) {
527   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
528   DIEInteger One(1);
529   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
530 
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);
535 
536   Unnamed.addChild(std::move(Foo));
537 
538   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
539 
540   // The exact same hash GCC produces for this DIE.
541   ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
542 }
543 
544 // struct { static void func(); };
TEST_F(DIEHashTest,MemberFunc)545 TEST_F(DIEHashTest, MemberFunc) {
546   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
547   DIEInteger One(1);
548   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
549 
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);
553 
554   Unnamed.addChild(std::move(Func));
555 
556   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
557 
558   // The exact same hash GCC produces for this DIE.
559   ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
560 }
561 
562 // struct A {
563 //   static void func();
564 // };
TEST_F(DIEHashTest,MemberFuncFlag)565 TEST_F(DIEHashTest, MemberFuncFlag) {
566   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
567   DIEInteger One(1);
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);
573 
574   auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
575   DIEString FuncStr = getString("func");
576   DIEString FuncLinkage = getString("_ZN1A4funcEv");
577   DIEInteger Two(2);
578   Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
579                  One);
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,
584                  FuncLinkage);
585   Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
586                  One);
587 
588   A.addChild(std::move(Func));
589 
590   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
591 
592   // The exact same hash GCC produces for this DIE.
593   ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res);
594 }
595 
596 // Derived from:
597 // struct A {
598 //   const static int PI = -3;
599 // };
600 // A a;
TEST_F(DIEHashTest,MemberSdata)601 TEST_F(DIEHashTest, MemberSdata) {
602   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
603   DIEInteger One(1);
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);
609 
610   DIEInteger Four(4);
611   DIEInteger Five(5);
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);
617 
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);
621 
622   DIEEntry PITy(*PITyDIE);
623   auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
624   DIEString PIStr = getString("PI");
625   DIEInteger Two(2);
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,
633                One);
634   PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree);
635 
636   A.addChild(std::move(PI));
637 
638   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
639   ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
640 }
641 
642 // Derived from:
643 // struct A {
644 //   const static float PI = 3.14;
645 // };
646 // A a;
TEST_F(DIEHashTest,MemberBlock)647 TEST_F(DIEHashTest, MemberBlock) {
648   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
649   DIEInteger One(1);
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);
655 
656   DIEInteger Four(4);
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,
660                        Four);
661   FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
662                        Four);
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);
667 
668   DIEEntry PITy(*PITyDIE);
669   auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
670   DIEString PIStr = getString("PI");
671   DIEInteger Two(2);
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,
678                One);
679 
680   DIEBlock PIBlock;
681   DIEInteger Blk1(0xc3);
682   DIEInteger Blk2(0xf5);
683   DIEInteger Blk3(0x48);
684   DIEInteger Blk4(0x40);
685 
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);
690 
691   PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1,
692                &PIBlock);
693 
694   A.addChild(std::move(PI));
695 
696   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
697   ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res);
698 }
699 }
700