mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
DWARF type hashing: pointers to members
Includes a test case/FIXME demonstrating a bug/limitation in pointer to member hashing. To be honest I'm not sure why we don't just always use summary hashing for referenced types... but perhaps I'm missing something. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193175 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
51ec77d880
commit
f196208900
@ -192,6 +192,7 @@ void DIEHash::collectAttributes(DIE *Die, DIEAttrs &Attrs) {
|
||||
void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
|
||||
const DIEValue *Value = Attr.Val;
|
||||
const DIEAbbrevData *Desc = Attr.Desc;
|
||||
dwarf::Attribute Attribute = Desc->getAttribute();
|
||||
|
||||
// 7.27 Step 3
|
||||
// ... An attribute that refers to another type entry T is processed as
|
||||
@ -200,14 +201,16 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
|
||||
DIE *Entry = EntryAttr->getEntry();
|
||||
|
||||
// Step 5
|
||||
// If the tag in Step 3 is one of ...
|
||||
if (Tag == dwarf::DW_TAG_pointer_type ||
|
||||
Tag == dwarf::DW_TAG_reference_type ||
|
||||
Tag == dwarf::DW_TAG_rvalue_reference_type) {
|
||||
// ... and the referenced type (via the DW_AT_type or DW_AT_friend
|
||||
// attribute) ...
|
||||
assert(Desc->getAttribute() == dwarf::DW_AT_type ||
|
||||
Desc->getAttribute() == dwarf::DW_AT_friend);
|
||||
// If the tag in Step 3 is one of [the below tags]
|
||||
if ((Tag == dwarf::DW_TAG_pointer_type ||
|
||||
Tag == dwarf::DW_TAG_reference_type ||
|
||||
Tag == dwarf::DW_TAG_rvalue_reference_type ||
|
||||
Tag == dwarf::DW_TAG_ptr_to_member_type) &&
|
||||
// and the referenced type (via the [below attributes])
|
||||
// FIXME: This seems overly restrictive, and causes hash mismatches
|
||||
// there's a decl/def difference in the containing type of a
|
||||
// ptr_to_member_type.
|
||||
Attribute == dwarf::DW_AT_type) {
|
||||
// [FIXME] ... has a DW_AT_name attribute,
|
||||
// append the letter 'N'
|
||||
addULEB128('N');
|
||||
@ -238,7 +241,7 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
|
||||
// 'R' as the marker
|
||||
addULEB128('R');
|
||||
|
||||
addULEB128(Desc->getAttribute());
|
||||
addULEB128(Attribute);
|
||||
|
||||
// and use the unsigned LEB128 encoding of [the index of T in the
|
||||
// list] as the attribute value;
|
||||
@ -249,7 +252,7 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
|
||||
// otherwise, b) use the letter 'T' as a the marker, ...
|
||||
addULEB128('T');
|
||||
|
||||
addULEB128(Desc->getAttribute());
|
||||
addULEB128(Attribute);
|
||||
|
||||
// ... process the type T recursively by performing Steps 2 through 7, and
|
||||
// use the result as the attribute value.
|
||||
@ -261,7 +264,7 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
|
||||
// Other attribute values use the letter 'A' as the marker, ...
|
||||
addULEB128('A');
|
||||
|
||||
addULEB128(Desc->getAttribute());
|
||||
addULEB128(Attribute);
|
||||
|
||||
// ... and the value consists of the form code (encoded as an unsigned LEB128
|
||||
// value) followed by the encoding of the value according to the form code. To
|
||||
|
@ -264,4 +264,182 @@ TEST(DIEHashTest, RValueReference) {
|
||||
|
||||
ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
|
||||
}
|
||||
|
||||
// struct foo { foo foo::*mem; };
|
||||
TEST(DIEHashTest, PtrToMember) {
|
||||
DIE Foo(dwarf::DW_TAG_structure_type);
|
||||
DIEInteger Eight(8);
|
||||
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
|
||||
DIEString FooStr(&Eight, "foo");
|
||||
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
|
||||
|
||||
DIE *Mem = new DIE(dwarf::DW_TAG_member);
|
||||
DIEString MemStr(&Eight, "mem");
|
||||
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
|
||||
DIEInteger Zero(0);
|
||||
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
|
||||
|
||||
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
|
||||
DIEEntry FooEntry(&Foo);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry);
|
||||
|
||||
DIEEntry PtrToFooMemRef(&PtrToFooMem);
|
||||
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
|
||||
|
||||
Foo.addChild(Mem);
|
||||
|
||||
uint64_t MD5Res = DIEHash().computeTypeSignature(&Foo);
|
||||
|
||||
ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
|
||||
}
|
||||
|
||||
// Check that the hash for a pointer-to-member matches regardless of whether the
|
||||
// pointed-to type is a declaration or a definition.
|
||||
//
|
||||
// struct bar; // { };
|
||||
// struct foo { bar foo::*mem; };
|
||||
TEST(DIEHashTest, PtrToMemberDeclDefMatch) {
|
||||
DIEInteger Zero(0);
|
||||
DIEInteger One(1);
|
||||
DIEInteger Eight(8);
|
||||
DIEString FooStr(&Eight, "foo");
|
||||
DIEString BarStr(&Eight, "bar");
|
||||
DIEString MemStr(&Eight, "mem");
|
||||
uint64_t MD5ResDecl;
|
||||
{
|
||||
DIE Bar(dwarf::DW_TAG_structure_type);
|
||||
Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
|
||||
Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
|
||||
|
||||
DIE Foo(dwarf::DW_TAG_structure_type);
|
||||
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
|
||||
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
|
||||
|
||||
DIE *Mem = new DIE(dwarf::DW_TAG_member);
|
||||
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
|
||||
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
|
||||
&Zero);
|
||||
|
||||
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
|
||||
DIEEntry BarEntry(&Bar);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
|
||||
DIEEntry FooEntry(&Foo);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
||||
&FooEntry);
|
||||
|
||||
DIEEntry PtrToFooMemRef(&PtrToFooMem);
|
||||
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
|
||||
|
||||
Foo.addChild(Mem);
|
||||
|
||||
MD5ResDecl = DIEHash().computeTypeSignature(&Foo);
|
||||
}
|
||||
uint64_t MD5ResDef;
|
||||
{
|
||||
DIE Bar(dwarf::DW_TAG_structure_type);
|
||||
Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
|
||||
Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
|
||||
|
||||
DIE Foo(dwarf::DW_TAG_structure_type);
|
||||
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
|
||||
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
|
||||
|
||||
DIE *Mem = new DIE(dwarf::DW_TAG_member);
|
||||
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
|
||||
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
|
||||
&Zero);
|
||||
|
||||
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
|
||||
DIEEntry BarEntry(&Bar);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
|
||||
DIEEntry FooEntry(&Foo);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
||||
&FooEntry);
|
||||
|
||||
DIEEntry PtrToFooMemRef(&PtrToFooMem);
|
||||
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
|
||||
|
||||
Foo.addChild(Mem);
|
||||
|
||||
MD5ResDef = DIEHash().computeTypeSignature(&Foo);
|
||||
}
|
||||
ASSERT_EQ(MD5ResDef, MD5ResDecl);
|
||||
}
|
||||
|
||||
// Check that the hash for a pointer-to-member matches regardless of whether the
|
||||
// pointed-to type is a declaration or a definition.
|
||||
//
|
||||
// struct bar; // { };
|
||||
// struct foo { bar bar::*mem; };
|
||||
TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) {
|
||||
DIEInteger Zero(0);
|
||||
DIEInteger One(1);
|
||||
DIEInteger Eight(8);
|
||||
DIEString FooStr(&Eight, "foo");
|
||||
DIEString BarStr(&Eight, "bar");
|
||||
DIEString MemStr(&Eight, "mem");
|
||||
uint64_t MD5ResDecl;
|
||||
{
|
||||
DIE Bar(dwarf::DW_TAG_structure_type);
|
||||
Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
|
||||
Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
|
||||
|
||||
DIE Foo(dwarf::DW_TAG_structure_type);
|
||||
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
|
||||
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
|
||||
|
||||
DIE *Mem = new DIE(dwarf::DW_TAG_member);
|
||||
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
|
||||
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
|
||||
&Zero);
|
||||
|
||||
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
|
||||
DIEEntry BarEntry(&Bar);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
||||
&BarEntry);
|
||||
|
||||
DIEEntry PtrToFooMemRef(&PtrToFooMem);
|
||||
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
|
||||
|
||||
Foo.addChild(Mem);
|
||||
|
||||
MD5ResDecl = DIEHash().computeTypeSignature(&Foo);
|
||||
}
|
||||
uint64_t MD5ResDef;
|
||||
{
|
||||
DIE Bar(dwarf::DW_TAG_structure_type);
|
||||
Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
|
||||
Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
|
||||
|
||||
DIE Foo(dwarf::DW_TAG_structure_type);
|
||||
Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
|
||||
Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
|
||||
|
||||
DIE *Mem = new DIE(dwarf::DW_TAG_member);
|
||||
Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
|
||||
Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
|
||||
&Zero);
|
||||
|
||||
DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
|
||||
DIEEntry BarEntry(&Bar);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
|
||||
PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
|
||||
&BarEntry);
|
||||
|
||||
DIEEntry PtrToFooMemRef(&PtrToFooMem);
|
||||
Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
|
||||
|
||||
Foo.addChild(Mem);
|
||||
|
||||
MD5ResDef = DIEHash().computeTypeSignature(&Foo);
|
||||
}
|
||||
// FIXME: This seems to be a bug in the DWARF type hashing specification that
|
||||
// only uses the brief name hashing for types referenced via DW_AT_type. In
|
||||
// this case the type is referenced via DW_AT_containing_type and full hashing
|
||||
// causes a hash to differ when the containing type is a declaration in one TU
|
||||
// and a definition in another.
|
||||
ASSERT_NE(MD5ResDef, MD5ResDecl);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user