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 | //===----------------------------------------------------------------------===// |
8 | |
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" |
20 | |
21 | using namespace llvm; |
22 | |
23 | namespace { |
24 | |
25 | // Test fixture |
26 | class DIEHashTest : public testing::Test { |
27 | public: |
28 | BumpPtrAllocator Alloc; |
29 | |
30 | private: |
31 | StringMap<DwarfStringPoolEntry> Pool; |
32 | std::unique_ptr<TestAsmPrinter> TestPrinter; |
33 | |
34 | void setupTestPrinter() { |
35 | auto ExpectedTestPrinter = TestAsmPrinter::create( |
36 | TripleStr: sys::getDefaultTargetTriple(), /*DwarfVersion=*/4, DwarfFormat: dwarf::DWARF32); |
37 | ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded()); |
38 | TestPrinter = std::move(ExpectedTestPrinter.get()); |
39 | } |
40 | |
41 | public: |
42 | DIEString getString(StringRef S) { |
43 | DwarfStringPoolEntry Entry = {.Symbol: nullptr, .Offset: 1, .Index: 1}; |
44 | return DIEString( |
45 | DwarfStringPoolEntryRef(*Pool.insert(KV: std::make_pair(x&: S, y&: Entry)).first)); |
46 | } |
47 | |
48 | AsmPrinter *getAsmPrinter() { |
49 | if (!TestPrinter) |
50 | setupTestPrinter(); |
51 | return TestPrinter ? TestPrinter->getAP() : nullptr; |
52 | } |
53 | }; |
54 | |
55 | TEST_F(DIEHashTest, Data1) { |
56 | DIEHash Hash; |
57 | DIE &Die = *DIE::get(Alloc, Tag: dwarf::DW_TAG_base_type); |
58 | DIEInteger Size(4); |
59 | Die.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Size); |
60 | uint64_t MD5Res = Hash.computeTypeSignature(Die); |
61 | ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res); |
62 | } |
63 | |
64 | // struct {}; |
65 | TEST_F(DIEHashTest, TrivialType) { |
66 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
67 | DIEInteger One(1); |
68 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
69 | |
70 | // Line and file number are ignored. |
71 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
72 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: One); |
73 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Unnamed); |
74 | |
75 | // The exact same hash GCC produces for this DIE. |
76 | ASSERT_EQ(0x715305CE6CFD9AD1ULL, MD5Res); |
77 | } |
78 | |
79 | // struct foo { }; |
80 | TEST_F(DIEHashTest, NamedType) { |
81 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
82 | DIEInteger One(1); |
83 | DIEString FooStr = getString(S: "foo" ); |
84 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
85 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
86 | |
87 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
88 | |
89 | // The exact same hash GCC produces for this DIE. |
90 | ASSERT_EQ(0xD566DBD2CA5265FFULL, MD5Res); |
91 | } |
92 | |
93 | // namespace space { struct foo { }; } |
94 | TEST_F(DIEHashTest, NamespacedType) { |
95 | DIE &CU = *DIE::get(Alloc, Tag: dwarf::DW_TAG_compile_unit); |
96 | |
97 | auto Space = DIE::get(Alloc, Tag: dwarf::DW_TAG_namespace); |
98 | DIEInteger One(1); |
99 | DIEString SpaceStr = getString(S: "space" ); |
100 | Space->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: SpaceStr); |
101 | // DW_AT_declaration is ignored. |
102 | Space->addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
103 | Value&: One); |
104 | // sibling? |
105 | |
106 | auto Foo = DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
107 | DIEString FooStr = getString(S: "foo" ); |
108 | Foo->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
109 | Foo->addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
110 | |
111 | DIE &N = *Foo; |
112 | Space->addChild(Child: std::move(Foo)); |
113 | CU.addChild(Child: std::move(Space)); |
114 | |
115 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: N); |
116 | |
117 | // The exact same hash GCC produces for this DIE. |
118 | ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res); |
119 | } |
120 | |
121 | // struct { int member; }; |
122 | TEST_F(DIEHashTest, TypeWithMember) { |
123 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
124 | DIEInteger Four(4); |
125 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Four); |
126 | |
127 | DIE &Int = *DIE::get(Alloc, Tag: dwarf::DW_TAG_base_type); |
128 | DIEString IntStr = getString(S: "int" ); |
129 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: IntStr); |
130 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Four); |
131 | DIEInteger Five(5); |
132 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_encoding, Form: dwarf::DW_FORM_data1, Value&: Five); |
133 | |
134 | DIEEntry IntRef(Int); |
135 | |
136 | auto Member = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
137 | DIEString MemberStr = getString(S: "member" ); |
138 | Member->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemberStr); |
139 | DIEInteger Zero(0); |
140 | Member->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, |
141 | Form: dwarf::DW_FORM_data1, Value&: Zero); |
142 | Member->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: IntRef); |
143 | |
144 | Unnamed.addChild(Child: std::move(Member)); |
145 | |
146 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Unnamed); |
147 | |
148 | ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res); |
149 | } |
150 | |
151 | // struct foo { int mem1, mem2; }; |
152 | TEST_F(DIEHashTest, ReusedType) { |
153 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
154 | DIEInteger Eight(8); |
155 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
156 | |
157 | DIEInteger Four(4); |
158 | DIE &Int = *DIE::get(Alloc, Tag: dwarf::DW_TAG_base_type); |
159 | DIEString IntStr = getString(S: "int" ); |
160 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: IntStr); |
161 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Four); |
162 | DIEInteger Five(5); |
163 | Int.addValue(Alloc, Attribute: dwarf::DW_AT_encoding, Form: dwarf::DW_FORM_data1, Value&: Five); |
164 | |
165 | DIEEntry IntRef(Int); |
166 | |
167 | auto Mem1 = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
168 | DIEString Mem1Str = getString(S: "mem1" ); |
169 | Mem1->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: Mem1Str); |
170 | DIEInteger Zero(0); |
171 | Mem1->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
172 | Value&: Zero); |
173 | Mem1->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: IntRef); |
174 | |
175 | Unnamed.addChild(Child: std::move(Mem1)); |
176 | |
177 | auto Mem2 = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
178 | DIEString Mem2Str = getString(S: "mem2" ); |
179 | Mem2->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: Mem2Str); |
180 | Mem2->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
181 | Value&: Four); |
182 | Mem2->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: IntRef); |
183 | |
184 | Unnamed.addChild(Child: std::move(Mem2)); |
185 | |
186 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Unnamed); |
187 | |
188 | ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res); |
189 | } |
190 | |
191 | // struct foo { static foo f; }; |
192 | TEST_F(DIEHashTest, RecursiveType) { |
193 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
194 | DIEInteger One(1); |
195 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
196 | DIEString FooStr = getString(S: "foo" ); |
197 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
198 | |
199 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
200 | DIEString MemStr = getString(S: "mem" ); |
201 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
202 | DIEEntry FooRef(Foo); |
203 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooRef); |
204 | // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them. |
205 | |
206 | Foo.addChild(Child: std::move(Mem)); |
207 | |
208 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
209 | |
210 | ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res); |
211 | } |
212 | |
213 | // struct foo { foo *mem; }; |
214 | TEST_F(DIEHashTest, Pointer) { |
215 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
216 | DIEInteger Eight(8); |
217 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
218 | DIEString FooStr = getString(S: "foo" ); |
219 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
220 | |
221 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
222 | DIEString MemStr = getString(S: "mem" ); |
223 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
224 | DIEInteger Zero(0); |
225 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
226 | Value&: Zero); |
227 | |
228 | DIE &FooPtr = *DIE::get(Alloc, Tag: dwarf::DW_TAG_pointer_type); |
229 | FooPtr.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
230 | DIEEntry FooRef(Foo); |
231 | FooPtr.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooRef); |
232 | |
233 | DIEEntry FooPtrRef(FooPtr); |
234 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooPtrRef); |
235 | |
236 | Foo.addChild(Child: std::move(Mem)); |
237 | |
238 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
239 | |
240 | ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res); |
241 | } |
242 | |
243 | // struct foo { foo &mem; }; |
244 | TEST_F(DIEHashTest, Reference) { |
245 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
246 | DIEInteger Eight(8); |
247 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
248 | DIEString FooStr = getString(S: "foo" ); |
249 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
250 | |
251 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
252 | DIEString MemStr = getString(S: "mem" ); |
253 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
254 | DIEInteger Zero(0); |
255 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
256 | Value&: Zero); |
257 | |
258 | DIE &FooRef = *DIE::get(Alloc, Tag: dwarf::DW_TAG_reference_type); |
259 | FooRef.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
260 | DIEEntry FooEntry(Foo); |
261 | FooRef.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooEntry); |
262 | |
263 | DIE &FooRefConst = *DIE::get(Alloc, Tag: dwarf::DW_TAG_const_type); |
264 | DIEEntry FooRefRef(FooRef); |
265 | FooRefConst.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
266 | Value&: FooRefRef); |
267 | |
268 | DIEEntry FooRefConstRef(FooRefConst); |
269 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooRefConstRef); |
270 | |
271 | Foo.addChild(Child: std::move(Mem)); |
272 | |
273 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
274 | |
275 | ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res); |
276 | } |
277 | |
278 | // struct foo { foo &&mem; }; |
279 | TEST_F(DIEHashTest, RValueReference) { |
280 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
281 | DIEInteger Eight(8); |
282 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
283 | DIEString FooStr = getString(S: "foo" ); |
284 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
285 | |
286 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
287 | DIEString MemStr = getString(S: "mem" ); |
288 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
289 | DIEInteger Zero(0); |
290 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
291 | Value&: Zero); |
292 | |
293 | DIE &FooRef = *DIE::get(Alloc, Tag: dwarf::DW_TAG_rvalue_reference_type); |
294 | FooRef.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
295 | DIEEntry FooEntry(Foo); |
296 | FooRef.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooEntry); |
297 | |
298 | DIE &FooRefConst = *DIE::get(Alloc, Tag: dwarf::DW_TAG_const_type); |
299 | DIEEntry FooRefRef(FooRef); |
300 | FooRefConst.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
301 | Value&: FooRefRef); |
302 | |
303 | DIEEntry FooRefConstRef(FooRefConst); |
304 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooRefConstRef); |
305 | |
306 | Foo.addChild(Child: std::move(Mem)); |
307 | |
308 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
309 | |
310 | ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res); |
311 | } |
312 | |
313 | // struct foo { foo foo::*mem; }; |
314 | TEST_F(DIEHashTest, PtrToMember) { |
315 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
316 | DIEInteger Eight(8); |
317 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
318 | DIEString FooStr = getString(S: "foo" ); |
319 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
320 | |
321 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
322 | DIEString MemStr = getString(S: "mem" ); |
323 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
324 | DIEInteger Zero(0); |
325 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
326 | Value&: Zero); |
327 | |
328 | DIE &PtrToFooMem = *DIE::get(Alloc, Tag: dwarf::DW_TAG_ptr_to_member_type); |
329 | DIEEntry FooEntry(Foo); |
330 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FooEntry); |
331 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_containing_type, Form: dwarf::DW_FORM_ref4, |
332 | Value&: FooEntry); |
333 | |
334 | DIEEntry PtrToFooMemRef(PtrToFooMem); |
335 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: PtrToFooMemRef); |
336 | |
337 | Foo.addChild(Child: std::move(Mem)); |
338 | |
339 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
340 | |
341 | ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res); |
342 | } |
343 | |
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. |
346 | // |
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(S: "foo" ); |
354 | DIEString BarStr = getString(S: "bar" ); |
355 | DIEString MemStr = getString(S: "mem" ); |
356 | uint64_t MD5ResDecl; |
357 | { |
358 | DIE &Bar = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
359 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: BarStr); |
360 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
361 | Value&: One); |
362 | |
363 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
364 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
365 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
366 | |
367 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
368 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
369 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, |
370 | Form: dwarf::DW_FORM_data1, Value&: Zero); |
371 | |
372 | DIE &PtrToFooMem = *DIE::get(Alloc, Tag: dwarf::DW_TAG_ptr_to_member_type); |
373 | DIEEntry BarEntry(Bar); |
374 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
375 | Value&: BarEntry); |
376 | DIEEntry FooEntry(Foo); |
377 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_containing_type, |
378 | Form: dwarf::DW_FORM_ref4, Value&: FooEntry); |
379 | |
380 | DIEEntry PtrToFooMemRef(PtrToFooMem); |
381 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
382 | Value&: PtrToFooMemRef); |
383 | |
384 | Foo.addChild(Child: std::move(Mem)); |
385 | |
386 | MD5ResDecl = DIEHash().computeTypeSignature(Die: Foo); |
387 | } |
388 | uint64_t MD5ResDef; |
389 | { |
390 | DIE &Bar = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
391 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: BarStr); |
392 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
393 | |
394 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
395 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
396 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
397 | |
398 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
399 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
400 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, |
401 | Form: dwarf::DW_FORM_data1, Value&: Zero); |
402 | |
403 | DIE &PtrToFooMem = *DIE::get(Alloc, Tag: dwarf::DW_TAG_ptr_to_member_type); |
404 | DIEEntry BarEntry(Bar); |
405 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
406 | Value&: BarEntry); |
407 | DIEEntry FooEntry(Foo); |
408 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_containing_type, |
409 | Form: dwarf::DW_FORM_ref4, Value&: FooEntry); |
410 | |
411 | DIEEntry PtrToFooMemRef(PtrToFooMem); |
412 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
413 | Value&: PtrToFooMemRef); |
414 | |
415 | Foo.addChild(Child: std::move(Mem)); |
416 | |
417 | MD5ResDef = DIEHash().computeTypeSignature(Die: Foo); |
418 | } |
419 | ASSERT_EQ(MD5ResDef, MD5ResDecl); |
420 | } |
421 | |
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. |
424 | // |
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(S: "foo" ); |
432 | DIEString BarStr = getString(S: "bar" ); |
433 | DIEString MemStr = getString(S: "mem" ); |
434 | uint64_t MD5ResDecl; |
435 | { |
436 | DIE &Bar = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
437 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: BarStr); |
438 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
439 | Value&: One); |
440 | |
441 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
442 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
443 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
444 | |
445 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
446 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
447 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, |
448 | Form: dwarf::DW_FORM_data1, Value&: Zero); |
449 | |
450 | DIE &PtrToFooMem = *DIE::get(Alloc, Tag: dwarf::DW_TAG_ptr_to_member_type); |
451 | DIEEntry BarEntry(Bar); |
452 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
453 | Value&: BarEntry); |
454 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_containing_type, |
455 | Form: dwarf::DW_FORM_ref4, Value&: BarEntry); |
456 | |
457 | DIEEntry PtrToFooMemRef(PtrToFooMem); |
458 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
459 | Value&: PtrToFooMemRef); |
460 | |
461 | Foo.addChild(Child: std::move(Mem)); |
462 | |
463 | MD5ResDecl = DIEHash().computeTypeSignature(Die: Foo); |
464 | } |
465 | uint64_t MD5ResDef; |
466 | { |
467 | DIE &Bar = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
468 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: BarStr); |
469 | Bar.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
470 | |
471 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
472 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
473 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
474 | |
475 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
476 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
477 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, |
478 | Form: dwarf::DW_FORM_data1, Value&: Zero); |
479 | |
480 | DIE &PtrToFooMem = *DIE::get(Alloc, Tag: dwarf::DW_TAG_ptr_to_member_type); |
481 | DIEEntry BarEntry(Bar); |
482 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
483 | Value&: BarEntry); |
484 | PtrToFooMem.addValue(Alloc, Attribute: dwarf::DW_AT_containing_type, |
485 | Form: dwarf::DW_FORM_ref4, Value&: BarEntry); |
486 | |
487 | DIEEntry PtrToFooMemRef(PtrToFooMem); |
488 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
489 | Value&: PtrToFooMemRef); |
490 | |
491 | Foo.addChild(Child: std::move(Mem)); |
492 | |
493 | MD5ResDef = DIEHash().computeTypeSignature(Die: Foo); |
494 | } |
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); |
501 | } |
502 | |
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(S: "foo" ); |
510 | DIEString MemStr = getString(S: "mem" ); |
511 | |
512 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
513 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
514 | |
515 | DIE &Foo = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
516 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Eight); |
517 | Foo.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
518 | |
519 | auto Mem = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
520 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: MemStr); |
521 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_data_member_location, Form: dwarf::DW_FORM_data1, |
522 | Value&: Zero); |
523 | |
524 | DIE &UnnamedPtr = *DIE::get(Alloc, Tag: dwarf::DW_TAG_pointer_type); |
525 | UnnamedPtr.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, |
526 | Value&: Eight); |
527 | DIEEntry UnnamedRef(Unnamed); |
528 | UnnamedPtr.addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, |
529 | Value&: UnnamedRef); |
530 | |
531 | DIEEntry UnnamedPtrRef(UnnamedPtr); |
532 | Mem->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: UnnamedPtrRef); |
533 | |
534 | Foo.addChild(Child: std::move(Mem)); |
535 | |
536 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Foo); |
537 | |
538 | ASSERT_EQ(0x954e026f01c02529ULL, MD5Res); |
539 | } |
540 | |
541 | // struct { struct foo { }; }; |
542 | TEST_F(DIEHashTest, NestedType) { |
543 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
544 | DIEInteger One(1); |
545 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
546 | |
547 | auto Foo = DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
548 | DIEString FooStr = getString(S: "foo" ); |
549 | Foo->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FooStr); |
550 | Foo->addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
551 | |
552 | Unnamed.addChild(Child: std::move(Foo)); |
553 | |
554 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Unnamed); |
555 | |
556 | // The exact same hash GCC produces for this DIE. |
557 | ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res); |
558 | } |
559 | |
560 | // struct { static void func(); }; |
561 | TEST_F(DIEHashTest, MemberFunc) { |
562 | DIE &Unnamed = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
563 | DIEInteger One(1); |
564 | Unnamed.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
565 | |
566 | auto Func = DIE::get(Alloc, Tag: dwarf::DW_TAG_subprogram); |
567 | DIEString FuncStr = getString(S: "func" ); |
568 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FuncStr); |
569 | |
570 | Unnamed.addChild(Child: std::move(Func)); |
571 | |
572 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: Unnamed); |
573 | |
574 | // The exact same hash GCC produces for this DIE. |
575 | ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res); |
576 | } |
577 | |
578 | // struct A { |
579 | // static void func(); |
580 | // }; |
581 | TEST_F(DIEHashTest, MemberFuncFlag) { |
582 | DIE &A = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
583 | DIEInteger One(1); |
584 | DIEString AStr = getString(S: "A" ); |
585 | A.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: AStr); |
586 | A.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
587 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
588 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: One); |
589 | |
590 | auto Func = DIE::get(Alloc, Tag: dwarf::DW_TAG_subprogram); |
591 | DIEString FuncStr = getString(S: "func" ); |
592 | DIEString FuncLinkage = getString(S: "_ZN1A4funcEv" ); |
593 | DIEInteger Two(2); |
594 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_external, Form: dwarf::DW_FORM_flag_present, |
595 | Value&: One); |
596 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FuncStr); |
597 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
598 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: Two); |
599 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_linkage_name, Form: dwarf::DW_FORM_strp, |
600 | Value&: FuncLinkage); |
601 | Func->addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
602 | Value&: One); |
603 | |
604 | A.addChild(Child: std::move(Func)); |
605 | |
606 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: A); |
607 | |
608 | // The exact same hash GCC produces for this DIE. |
609 | ASSERT_EQ(0x8F78211DDCE3DF10ULL, MD5Res); |
610 | } |
611 | |
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, Tag: dwarf::DW_TAG_structure_type); |
619 | DIEInteger One(1); |
620 | DIEString AStr = getString(S: "A" ); |
621 | A.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: AStr); |
622 | A.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
623 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
624 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: One); |
625 | |
626 | DIEInteger Four(4); |
627 | DIEInteger Five(5); |
628 | DIEString FStr = getString(S: "int" ); |
629 | DIE &IntTyDIE = *DIE::get(Alloc, Tag: dwarf::DW_TAG_base_type); |
630 | IntTyDIE.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: Four); |
631 | IntTyDIE.addValue(Alloc, Attribute: dwarf::DW_AT_encoding, Form: dwarf::DW_FORM_data1, Value&: Five); |
632 | IntTyDIE.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FStr); |
633 | |
634 | DIEEntry IntTy(IntTyDIE); |
635 | auto PITyDIE = DIE::get(Alloc, Tag: dwarf::DW_TAG_const_type); |
636 | PITyDIE->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: IntTy); |
637 | |
638 | DIEEntry PITy(*PITyDIE); |
639 | auto PI = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
640 | DIEString PIStr = getString(S: "PI" ); |
641 | DIEInteger Two(2); |
642 | DIEInteger NegThree(-3); |
643 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: PIStr); |
644 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
645 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: Two); |
646 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: PITy); |
647 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_external, Form: dwarf::DW_FORM_flag_present, Value&: One); |
648 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
649 | Value&: One); |
650 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_const_value, Form: dwarf::DW_FORM_sdata, Value&: NegThree); |
651 | |
652 | A.addChild(Child: std::move(PI)); |
653 | |
654 | uint64_t MD5Res = DIEHash().computeTypeSignature(Die: A); |
655 | ASSERT_EQ(0x9A216000DD3788A7ULL, MD5Res); |
656 | } |
657 | |
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(); |
666 | |
667 | DIE &A = *DIE::get(Alloc, Tag: dwarf::DW_TAG_structure_type); |
668 | DIEInteger One(1); |
669 | DIEString AStr = getString(S: "A" ); |
670 | A.addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: AStr); |
671 | A.addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, Value&: One); |
672 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
673 | A.addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: One); |
674 | |
675 | DIEInteger Four(4); |
676 | DIEString FStr = getString(S: "float" ); |
677 | auto FloatTyDIE = DIE::get(Alloc, Tag: dwarf::DW_TAG_base_type); |
678 | FloatTyDIE->addValue(Alloc, Attribute: dwarf::DW_AT_byte_size, Form: dwarf::DW_FORM_data1, |
679 | Value&: Four); |
680 | FloatTyDIE->addValue(Alloc, Attribute: dwarf::DW_AT_encoding, Form: dwarf::DW_FORM_data1, |
681 | Value&: Four); |
682 | FloatTyDIE->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: FStr); |
683 | DIEEntry FloatTy(*FloatTyDIE); |
684 | auto PITyDIE = DIE::get(Alloc, Tag: dwarf::DW_TAG_const_type); |
685 | PITyDIE->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: FloatTy); |
686 | |
687 | DIEEntry PITy(*PITyDIE); |
688 | auto PI = DIE::get(Alloc, Tag: dwarf::DW_TAG_member); |
689 | DIEString PIStr = getString(S: "PI" ); |
690 | DIEInteger Two(2); |
691 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_name, Form: dwarf::DW_FORM_strp, Value&: PIStr); |
692 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_decl_file, Form: dwarf::DW_FORM_data1, Value&: One); |
693 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_decl_line, Form: dwarf::DW_FORM_data1, Value&: Two); |
694 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_type, Form: dwarf::DW_FORM_ref4, Value&: PITy); |
695 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_external, Form: dwarf::DW_FORM_flag_present, Value&: One); |
696 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_declaration, Form: dwarf::DW_FORM_flag_present, |
697 | Value&: One); |
698 | |
699 | DIEBlock PIBlock; |
700 | DIEInteger Blk1(0xc3); |
701 | DIEInteger Blk2(0xf5); |
702 | DIEInteger Blk3(0x48); |
703 | DIEInteger Blk4(0x40); |
704 | |
705 | PIBlock.addValue(Alloc, Attribute: (dwarf::Attribute)0, Form: dwarf::DW_FORM_data1, Value&: Blk1); |
706 | PIBlock.addValue(Alloc, Attribute: (dwarf::Attribute)0, Form: dwarf::DW_FORM_data1, Value&: Blk2); |
707 | PIBlock.addValue(Alloc, Attribute: (dwarf::Attribute)0, Form: dwarf::DW_FORM_data1, Value&: Blk3); |
708 | PIBlock.addValue(Alloc, Attribute: (dwarf::Attribute)0, Form: dwarf::DW_FORM_data1, Value&: Blk4); |
709 | |
710 | PI->addValue(Alloc, Attribute: dwarf::DW_AT_const_value, Form: dwarf::DW_FORM_block1, |
711 | Value: &PIBlock); |
712 | |
713 | A.addChild(Child: std::move(PI)); |
714 | |
715 | uint64_t MD5Res = DIEHash(this->getAsmPrinter()).computeTypeSignature(Die: A); |
716 | ASSERT_EQ(0x493AF53AD3D3F651ULL, MD5Res); |
717 | } |
718 | } |
719 | |