diff --git a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp index 13238f37b34c..aa54db004613 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -196,22 +196,30 @@ void DIEHash::hashAttribute(AttrEntry Attr) { // 7.27s3 // ... An attribute that refers to another type entry T is processed as // follows: - // a) If T is in the list of [previously hashed types], use the letter 'R' as - // the marker and use the unsigned LEB128 encoding of [the index of T in the - // list] as the attribute value; otherwise, - - // [TODO: implement clause (a)] - if (const DIEEntry *EntryAttr = dyn_cast(Value)) { DIE *Entry = EntryAttr->getEntry(); + unsigned &DieNumber = Numbering[Entry]; + if (DieNumber) { + // a) If T is in the list of [previously hashed types], use the letter + // 'R' as the marker + addULEB128('R'); - // b) use the letter 'T' as a the marker, ... + addULEB128(Desc->getAttribute()); + + // and use the unsigned LEB128 encoding of [the index of T in the + // list] as the attribute value; + addULEB128(DieNumber); + return; + } + + // otherwise, b) use the letter 'T' as a the marker, ... addULEB128('T'); addULEB128(Desc->getAttribute()); // ... process the type T recursively by performing Steps 2 through 7, and // use the result as the attribute value. + DieNumber = Numbering.size(); computeHash(Entry); return; } @@ -321,7 +329,6 @@ void DIEHash::addAttributes(DIE *Die) { // given in section 7.27 of the DWARF4 standard. It is the md5 hash of a // flattened description of the DIE. void DIEHash::computeHash(DIE *Die) { - // Append the letter 'D', followed by the DWARF tag of the DIE. addULEB128('D'); addULEB128(Die->getTag()); @@ -377,6 +384,8 @@ uint64_t DIEHash::computeDIEODRSignature(DIE *Die) { /// with the inclusion of the full CU and all top level CU entities. // TODO: Initialize the type chain at 0 instead of 1 for CU signatures. uint64_t DIEHash::computeCUSignature(DIE *Die) { + Numbering.clear(); + Numbering[Die] = 1; // Hash the DIE. computeHash(Die); @@ -396,6 +405,8 @@ uint64_t DIEHash::computeCUSignature(DIE *Die) { /// with the inclusion of additional forms not specifically called out in the /// standard. uint64_t DIEHash::computeTypeSignature(DIE *Die) { + Numbering.clear(); + Numbering[Die] = 1; if (DIE *Parent = Die->getParent()) addParentContext(Parent); diff --git a/llvm/lib/CodeGen/AsmPrinter/DIEHash.h b/llvm/lib/CodeGen/AsmPrinter/DIEHash.h index ee753fea99c2..f6650cc93e7a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIEHash.h +++ b/llvm/lib/CodeGen/AsmPrinter/DIEHash.h @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/MD5.h" namespace llvm { @@ -125,5 +126,6 @@ private: private: MD5 Hash; + DenseMap Numbering; }; } diff --git a/llvm/unittests/CodeGen/DIEHashTest.cpp b/llvm/unittests/CodeGen/DIEHashTest.cpp index 834a16a2ce11..6da1fd7b2401 100644 --- a/llvm/unittests/CodeGen/DIEHashTest.cpp +++ b/llvm/unittests/CodeGen/DIEHashTest.cpp @@ -92,7 +92,6 @@ TEST(TypeWithMember, DIEHash) { DIE *Member = new DIE(dwarf::DW_TAG_member); DIEString MemberStr(&Four, "member"); Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); - // type DIEInteger Zero(0); Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); @@ -112,4 +111,62 @@ TEST(TypeWithMember, DIEHash) { ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res); } + +TEST(ReusedType, DIEHash) { + DIE Unnamed(dwarf::DW_TAG_structure_type); + DIEInteger Eight(8); + Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); + + DIE *Mem1 = new DIE(dwarf::DW_TAG_member); + DIEInteger Four(4); + DIEString Mem1Str(&Four, "mem1"); + Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str); + DIEInteger Zero(0); + Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); + + Unnamed.addChild(Mem1); + + DIE *Mem2 = new DIE(dwarf::DW_TAG_member); + DIEString Mem2Str(&Four, "mem2"); + Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str); + Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Four); + + Unnamed.addChild(Mem2); + + DIE Int(dwarf::DW_TAG_base_type); + DIEString IntStr(&Four, "int"); + Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); + Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + DIEInteger Five(5); + Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); + + DIEEntry IntRef(&Int); + Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + + uint64_t MD5Res = DIEHash().computeTypeSignature(&Unnamed); + + ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res); +} + +TEST(RecursiveType, DIEHash) { + DIE Foo(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + DIEString FooStr(&One, "foo"); + Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); + + DIE *Mem = new DIE(dwarf::DW_TAG_member); + DIEString MemStr(&One, "mem"); + Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); + DIEEntry FooRef(&Foo); + Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef); + // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them. + + Foo.addChild(Mem); + + uint64_t MD5Res = DIEHash().computeTypeSignature(&Foo); + + ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res); +} }