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 "llvm/CodeGen/DIE.h"
11 #include "../lib/CodeGen/AsmPrinter/DIEHash.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Dwarf.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