[MemProf] Templatize CallStackRadixTreeBuilder (NFC) (#117014)
[llvm-project.git] / llvm / unittests / CodeGen / DIEHashTest.cpp
blobb9e5f53155bd84feb5a0961a027871611e6b7f78
1 //===- llvm/unittest/CodeGen/DIEHashTest.cpp ------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "../lib/CodeGen/AsmPrinter/DIEHash.h"
10 #include "TestAsmPrinter.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 "llvm/TargetParser/Host.h"
18 #include "llvm/Testing/Support/Error.h"
19 #include "gtest/gtest.h"
21 using namespace llvm;
23 namespace {
25 // Test fixture
26 class DIEHashTest : public testing::Test {
27 public:
28 BumpPtrAllocator Alloc;
30 private:
31 StringMap<DwarfStringPoolEntry> Pool;
32 std::unique_ptr<TestAsmPrinter> TestPrinter;
34 void setupTestPrinter() {
35 auto ExpectedTestPrinter = TestAsmPrinter::create(
36 sys::getDefaultTargetTriple(), /*DwarfVersion=*/4, dwarf::DWARF32);
37 ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded());
38 TestPrinter = std::move(ExpectedTestPrinter.get());
41 public:
42 DIEString getString(StringRef S) {
43 DwarfStringPoolEntry Entry = {nullptr, 1, 1};
44 return DIEString(
45 DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S, Entry)).first));
48 AsmPrinter *getAsmPrinter() {
49 if (!TestPrinter)
50 setupTestPrinter();
51 return TestPrinter ? TestPrinter->getAP() : nullptr;
55 TEST_F(DIEHashTest, Data1) {
56 DIEHash Hash;
57 DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
58 DIEInteger Size(4);
59 Die.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Size);
60 uint64_t MD5Res = Hash.computeTypeSignature(Die);
61 ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
64 // struct {};
65 TEST_F(DIEHashTest, TrivialType) {
66 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
67 DIEInteger One(1);
68 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
70 // Line and file number are ignored.
71 Unnamed.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
72 Unnamed.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
73 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
75 // The exact same hash GCC produces for this DIE.
76 ASSERT_EQ(0x715305CE6CFD9AD1ULL, MD5Res);
79 // struct foo { };
80 TEST_F(DIEHashTest, NamedType) {
81 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
82 DIEInteger One(1);
83 DIEString FooStr = getString("foo");
84 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
85 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
87 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
89 // The exact same hash GCC produces for this DIE.
90 ASSERT_EQ(0xD566DBD2CA5265FFULL, MD5Res);
93 // namespace space { struct foo { }; }
94 TEST_F(DIEHashTest, NamespacedType) {
95 DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit);
97 auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace);
98 DIEInteger One(1);
99 DIEString SpaceStr = getString("space");
100 Space->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, SpaceStr);
101 // DW_AT_declaration is ignored.
102 Space->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
103 One);
104 // sibling?
106 auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
107 DIEString FooStr = getString("foo");
108 Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
109 Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
111 DIE &N = *Foo;
112 Space->addChild(std::move(Foo));
113 CU.addChild(std::move(Space));
115 uint64_t MD5Res = DIEHash().computeTypeSignature(N);
117 // The exact same hash GCC produces for this DIE.
118 ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
121 // struct { int member; };
122 TEST_F(DIEHashTest, TypeWithMember) {
123 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
124 DIEInteger Four(4);
125 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
127 DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
128 DIEString IntStr = getString("int");
129 Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
130 Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
131 DIEInteger Five(5);
132 Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
134 DIEEntry IntRef(Int);
136 auto Member = DIE::get(Alloc, dwarf::DW_TAG_member);
137 DIEString MemberStr = getString("member");
138 Member->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemberStr);
139 DIEInteger Zero(0);
140 Member->addValue(Alloc, dwarf::DW_AT_data_member_location,
141 dwarf::DW_FORM_data1, Zero);
142 Member->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
144 Unnamed.addChild(std::move(Member));
146 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
148 ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
151 // struct foo { int mem1, mem2; };
152 TEST_F(DIEHashTest, ReusedType) {
153 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
154 DIEInteger Eight(8);
155 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
157 DIEInteger Four(4);
158 DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
159 DIEString IntStr = getString("int");
160 Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
161 Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
162 DIEInteger Five(5);
163 Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
165 DIEEntry IntRef(Int);
167 auto Mem1 = DIE::get(Alloc, dwarf::DW_TAG_member);
168 DIEString Mem1Str = getString("mem1");
169 Mem1->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem1Str);
170 DIEInteger Zero(0);
171 Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
172 Zero);
173 Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
175 Unnamed.addChild(std::move(Mem1));
177 auto Mem2 = DIE::get(Alloc, dwarf::DW_TAG_member);
178 DIEString Mem2Str = getString("mem2");
179 Mem2->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem2Str);
180 Mem2->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
181 Four);
182 Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
184 Unnamed.addChild(std::move(Mem2));
186 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
188 ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
191 // struct foo { static foo f; };
192 TEST_F(DIEHashTest, RecursiveType) {
193 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
194 DIEInteger One(1);
195 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
196 DIEString FooStr = getString("foo");
197 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
199 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
200 DIEString MemStr = getString("mem");
201 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
202 DIEEntry FooRef(Foo);
203 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
204 // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
206 Foo.addChild(std::move(Mem));
208 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
210 ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
213 // struct foo { foo *mem; };
214 TEST_F(DIEHashTest, Pointer) {
215 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
216 DIEInteger Eight(8);
217 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
218 DIEString FooStr = getString("foo");
219 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
221 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
222 DIEString MemStr = getString("mem");
223 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
224 DIEInteger Zero(0);
225 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
226 Zero);
228 DIE &FooPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
229 FooPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
230 DIEEntry FooRef(Foo);
231 FooPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
233 DIEEntry FooPtrRef(FooPtr);
234 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef);
236 Foo.addChild(std::move(Mem));
238 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
240 ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
243 // struct foo { foo &mem; };
244 TEST_F(DIEHashTest, Reference) {
245 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
246 DIEInteger Eight(8);
247 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
248 DIEString FooStr = getString("foo");
249 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
251 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
252 DIEString MemStr = getString("mem");
253 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
254 DIEInteger Zero(0);
255 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
256 Zero);
258 DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_reference_type);
259 FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
260 DIEEntry FooEntry(Foo);
261 FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
263 DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
264 DIEEntry FooRefRef(FooRef);
265 FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
266 FooRefRef);
268 DIEEntry FooRefConstRef(FooRefConst);
269 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
271 Foo.addChild(std::move(Mem));
273 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
275 ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
278 // struct foo { foo &&mem; };
279 TEST_F(DIEHashTest, RValueReference) {
280 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
281 DIEInteger Eight(8);
282 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
283 DIEString FooStr = getString("foo");
284 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
286 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
287 DIEString MemStr = getString("mem");
288 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
289 DIEInteger Zero(0);
290 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
291 Zero);
293 DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_rvalue_reference_type);
294 FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
295 DIEEntry FooEntry(Foo);
296 FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
298 DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
299 DIEEntry FooRefRef(FooRef);
300 FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
301 FooRefRef);
303 DIEEntry FooRefConstRef(FooRefConst);
304 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
306 Foo.addChild(std::move(Mem));
308 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
310 ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
313 // struct foo { foo foo::*mem; };
314 TEST_F(DIEHashTest, PtrToMember) {
315 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
316 DIEInteger Eight(8);
317 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
318 DIEString FooStr = getString("foo");
319 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
321 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
322 DIEString MemStr = getString("mem");
323 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
324 DIEInteger Zero(0);
325 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
326 Zero);
328 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
329 DIEEntry FooEntry(Foo);
330 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
331 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
332 FooEntry);
334 DIEEntry PtrToFooMemRef(PtrToFooMem);
335 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef);
337 Foo.addChild(std::move(Mem));
339 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
341 ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
344 // Check that the hash for a pointer-to-member matches regardless of whether the
345 // pointed-to type is a declaration or a definition.
347 // struct bar; // { };
348 // struct foo { bar foo::*mem; };
349 TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) {
350 DIEInteger Zero(0);
351 DIEInteger One(1);
352 DIEInteger Eight(8);
353 DIEString FooStr = getString("foo");
354 DIEString BarStr = getString("bar");
355 DIEString MemStr = getString("mem");
356 uint64_t MD5ResDecl;
358 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
359 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
360 Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
361 One);
363 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
364 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
365 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
367 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
368 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
369 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
370 dwarf::DW_FORM_data1, Zero);
372 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
373 DIEEntry BarEntry(Bar);
374 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
375 BarEntry);
376 DIEEntry FooEntry(Foo);
377 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
378 dwarf::DW_FORM_ref4, FooEntry);
380 DIEEntry PtrToFooMemRef(PtrToFooMem);
381 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
382 PtrToFooMemRef);
384 Foo.addChild(std::move(Mem));
386 MD5ResDecl = DIEHash().computeTypeSignature(Foo);
388 uint64_t MD5ResDef;
390 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
391 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
392 Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
394 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
395 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
396 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
398 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
399 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
400 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
401 dwarf::DW_FORM_data1, Zero);
403 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
404 DIEEntry BarEntry(Bar);
405 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
406 BarEntry);
407 DIEEntry FooEntry(Foo);
408 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
409 dwarf::DW_FORM_ref4, FooEntry);
411 DIEEntry PtrToFooMemRef(PtrToFooMem);
412 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
413 PtrToFooMemRef);
415 Foo.addChild(std::move(Mem));
417 MD5ResDef = DIEHash().computeTypeSignature(Foo);
419 ASSERT_EQ(MD5ResDef, MD5ResDecl);
422 // Check that the hash for a pointer-to-member matches regardless of whether the
423 // pointed-to type is a declaration or a definition.
425 // struct bar; // { };
426 // struct foo { bar bar::*mem; };
427 TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) {
428 DIEInteger Zero(0);
429 DIEInteger One(1);
430 DIEInteger Eight(8);
431 DIEString FooStr = getString("foo");
432 DIEString BarStr = getString("bar");
433 DIEString MemStr = getString("mem");
434 uint64_t MD5ResDecl;
436 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
437 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
438 Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
439 One);
441 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
442 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
443 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
445 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
446 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
447 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
448 dwarf::DW_FORM_data1, Zero);
450 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
451 DIEEntry BarEntry(Bar);
452 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
453 BarEntry);
454 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
455 dwarf::DW_FORM_ref4, BarEntry);
457 DIEEntry PtrToFooMemRef(PtrToFooMem);
458 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
459 PtrToFooMemRef);
461 Foo.addChild(std::move(Mem));
463 MD5ResDecl = DIEHash().computeTypeSignature(Foo);
465 uint64_t MD5ResDef;
467 DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
468 Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
469 Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
471 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
472 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
473 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
475 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
476 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
477 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
478 dwarf::DW_FORM_data1, Zero);
480 DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
481 DIEEntry BarEntry(Bar);
482 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
483 BarEntry);
484 PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
485 dwarf::DW_FORM_ref4, BarEntry);
487 DIEEntry PtrToFooMemRef(PtrToFooMem);
488 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
489 PtrToFooMemRef);
491 Foo.addChild(std::move(Mem));
493 MD5ResDef = DIEHash().computeTypeSignature(Foo);
495 // FIXME: This seems to be a bug in the DWARF type hashing specification that
496 // only uses the brief name hashing for types referenced via DW_AT_type. In
497 // this case the type is referenced via DW_AT_containing_type and full hashing
498 // causes a hash to differ when the containing type is a declaration in one TU
499 // and a definition in another.
500 ASSERT_NE(MD5ResDef, MD5ResDecl);
503 // struct { } a;
504 // struct foo { decltype(a) mem; };
505 TEST_F(DIEHashTest, RefUnnamedType) {
506 DIEInteger Zero(0);
507 DIEInteger One(1);
508 DIEInteger Eight(8);
509 DIEString FooStr = getString("foo");
510 DIEString MemStr = getString("mem");
512 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
513 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
515 DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
516 Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
517 Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
519 auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
520 Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
521 Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
522 Zero);
524 DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
525 UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
526 Eight);
527 DIEEntry UnnamedRef(Unnamed);
528 UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
529 UnnamedRef);
531 DIEEntry UnnamedPtrRef(UnnamedPtr);
532 Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef);
534 Foo.addChild(std::move(Mem));
536 uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
538 ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
541 // struct { struct foo { }; };
542 TEST_F(DIEHashTest, NestedType) {
543 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
544 DIEInteger One(1);
545 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
547 auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
548 DIEString FooStr = getString("foo");
549 Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
550 Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
552 Unnamed.addChild(std::move(Foo));
554 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
556 // The exact same hash GCC produces for this DIE.
557 ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
560 // struct { static void func(); };
561 TEST_F(DIEHashTest, MemberFunc) {
562 DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
563 DIEInteger One(1);
564 Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
566 auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
567 DIEString FuncStr = getString("func");
568 Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
570 Unnamed.addChild(std::move(Func));
572 uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
574 // The exact same hash GCC produces for this DIE.
575 ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
578 // struct A {
579 // static void func();
580 // };
581 TEST_F(DIEHashTest, MemberFuncFlag) {
582 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
583 DIEInteger One(1);
584 DIEString AStr = getString("A");
585 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
586 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
587 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
588 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
590 auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
591 DIEString FuncStr = getString("func");
592 DIEString FuncLinkage = getString("_ZN1A4funcEv");
593 DIEInteger Two(2);
594 Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
595 One);
596 Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
597 Func->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
598 Func->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
599 Func->addValue(Alloc, dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
600 FuncLinkage);
601 Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
602 One);
604 A.addChild(std::move(Func));
606 uint64_t MD5Res = DIEHash().computeTypeSignature(A);
608 // The exact same hash GCC produces for this DIE.
609 ASSERT_EQ(0x8F78211DDCE3DF10ULL, MD5Res);
612 // Derived from:
613 // struct A {
614 // const static int PI = -3;
615 // };
616 // A a;
617 TEST_F(DIEHashTest, MemberSdata) {
618 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
619 DIEInteger One(1);
620 DIEString AStr = getString("A");
621 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
622 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
623 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
624 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
626 DIEInteger Four(4);
627 DIEInteger Five(5);
628 DIEString FStr = getString("int");
629 DIE &IntTyDIE = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
630 IntTyDIE.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
631 IntTyDIE.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
632 IntTyDIE.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
634 DIEEntry IntTy(IntTyDIE);
635 auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
636 PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntTy);
638 DIEEntry PITy(*PITyDIE);
639 auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
640 DIEString PIStr = getString("PI");
641 DIEInteger Two(2);
642 DIEInteger NegThree(-3);
643 PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
644 PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
645 PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
646 PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
647 PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
648 PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
649 One);
650 PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree);
652 A.addChild(std::move(PI));
654 uint64_t MD5Res = DIEHash().computeTypeSignature(A);
655 ASSERT_EQ(0x9A216000DD3788A7ULL, MD5Res);
658 // Derived from:
659 // struct A {
660 // const static float PI = 3.14;
661 // };
662 // A a;
663 TEST_F(DIEHashTest, MemberBlock) {
664 if (!this->getAsmPrinter())
665 GTEST_SKIP();
667 DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
668 DIEInteger One(1);
669 DIEString AStr = getString("A");
670 A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
671 A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
672 A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
673 A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
675 DIEInteger Four(4);
676 DIEString FStr = getString("float");
677 auto FloatTyDIE = DIE::get(Alloc, dwarf::DW_TAG_base_type);
678 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
679 Four);
680 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
681 Four);
682 FloatTyDIE->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
683 DIEEntry FloatTy(*FloatTyDIE);
684 auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
685 PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FloatTy);
687 DIEEntry PITy(*PITyDIE);
688 auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
689 DIEString PIStr = getString("PI");
690 DIEInteger Two(2);
691 PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
692 PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
693 PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
694 PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
695 PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
696 PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
697 One);
699 DIEBlock PIBlock;
700 DIEInteger Blk1(0xc3);
701 DIEInteger Blk2(0xf5);
702 DIEInteger Blk3(0x48);
703 DIEInteger Blk4(0x40);
705 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk1);
706 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk2);
707 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk3);
708 PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk4);
710 PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1,
711 &PIBlock);
713 A.addChild(std::move(PI));
715 uint64_t MD5Res = DIEHash(this->getAsmPrinter()).computeTypeSignature(A);
716 ASSERT_EQ(0x493AF53AD3D3F651ULL, MD5Res);