Home | History | Annotate | Download | only in CodeGen
      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 "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:
     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