diff options
author | Adrian Prantl <aprantl@apple.com> | 2015-06-27 20:12:43 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2015-06-27 20:12:43 +0000 |
commit | 57c7a62b973e909c29a7da46bae11051b16a5de8 (patch) | |
tree | 192653cde79baf5e387cb4a6de43a133abf3f64a /llvm/lib/CodeGen | |
parent | 43899d44c2f47e2fbd29e8d3745f1f68e29ba306 (diff) | |
download | bcm5719-llvm-57c7a62b973e909c29a7da46bae11051b16a5de8.tar.gz bcm5719-llvm-57c7a62b973e909c29a7da46bae11051b16a5de8.zip |
Debug Info: One more bitfield bugfix. While yesterday's r240853 fixed
the DW_AT_bit_offset computation, the byte offset is in fact also
endian-dependent as it needs to point to the storage unit containing the
most-significant bit of the the bitfield.
I'm so looking forward to emitting the endian-agnostic DWARF 3 version
instead.
llvm-svn: 240890
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 44de3407369..ca9951eda42 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1346,9 +1346,9 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8); addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size); // - // The DWARF 2 DW_AT_bit_offset is counting the bits between - // the high end of the aligned storage unit containing the bit - // field to the high end of the bit field. + // The DWARF 2 DW_AT_bit_offset is counting the bits between the most + // significant bit of the aligned storage unit containing the bit field to + // the most significan bit of the bit field. // // FIXME: DWARF 4 states that DW_AT_data_bit_offset (which // counts from the beginning, regardless of endianness) should @@ -1361,24 +1361,29 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { // | ... |b1|b2|b3|b4| // +-----------+-----*-----+-----*-----+-- // | | |<-- Size ->| | - // |<---- Offset --->| |<--->| - // | | | \_ DW_AT_bit_offset (little endian) - // | |<--->| - // |<--------->| \_ StartBitOffset = DW_AT_bit_offset (big endian) - // \ = DW_AT_data_bit_offset (biendian) - // \_ OffsetInBytes + // |<---- Offset --->| | |<--->| + // | | | | \_ DW_AT_bit_offset (little endian) + // | |<--->| | + // |<--big-e.->| \_ StartBitOffset = DW_AT_bit_offset (big endian) + // | ^ | = DW_AT_data_bit_offset (biendian) + // | OffsetInBytes | + // | v | + // |<----little-endian---->| uint64_t Offset = DT->getOffsetInBits(); uint64_t Align = DT->getAlignInBits() ? DT->getAlignInBits() : FieldSize; uint64_t AlignMask = ~(Align - 1); // The bits from the start of the storage unit to the start of the field. uint64_t StartBitOffset = Offset - (Offset & AlignMask); - // The endian-dependent DWARF 2 offset. - uint64_t DwarfBitOffset = Asm->getDataLayout().isLittleEndian() - ? OffsetToAlignment(Offset + Size, Align) - : StartBitOffset; - - // The byte offset of the field's aligned storage unit inside the struct. - OffsetInBytes = (Offset - StartBitOffset) / 8; + // OffsetInBytes is the byte offset of the field's aligned storage unit + // inside the struct. + uint64_t DwarfBitOffset; + if (Asm->getDataLayout().isLittleEndian()) { + DwarfBitOffset = OffsetToAlignment(Offset + Size, Align); + OffsetInBytes = ((Offset + Size) & AlignMask) / 8; + } else { + DwarfBitOffset = StartBitOffset; + OffsetInBytes = (Offset - StartBitOffset) / 8; + } addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, DwarfBitOffset); } else // This is not a bitfield. |