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: 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 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 {}; 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 { }; 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 { }; } 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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; }; 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 { }; }; 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(); }; 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 // }; 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; 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; 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