diff options
author | Adrian Prantl <aprantl@apple.com> | 2016-04-28 15:37:48 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2016-04-28 15:37:48 +0000 |
commit | f393d313ece93b7ab10bbbc0776bf10e4617cfda (patch) | |
tree | b53c3ff4fe5d2dfcdb932aebc5369a1d50b97b44 /llvm/lib/CodeGen/AsmPrinter | |
parent | bcdce3fd85dfb3942c8996430e429824667a6ed1 (diff) | |
download | bcm5719-llvm-f393d313ece93b7ab10bbbc0776bf10e4617cfda.tar.gz bcm5719-llvm-f393d313ece93b7ab10bbbc0776bf10e4617cfda.zip |
Debug info: Support DWARF4 bitfields via DW_AT_data_bit_offset.
The DWARF2 specification of DW_AT_bit_offset was written from the perspective of
a big-endian machine with unclear semantics for other systems. DWARF4
deprecated DW_AT_bit_offset and introduced a new attribute DW_AT_data_bit_offset
that simply counts the number of bits from the beginning of the containing
entity regardless of endianness.
After this patch LLVM emits DW_AT_bit_offset for DWARF 2 or 3 and
DW_AT_data_bit_offset when DWARF 4 or later is requested.
llvm-svn: 267895
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 91c490f0e9d..08800f415a4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1395,41 +1395,43 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { // Handle bitfield, assume bytes are 8 bits. 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 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 - // be used instead. - // - // - // Struct Align Align Align - // v v v v - // +-----------+-----*-----+-----*-----+-- - // | ... |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 + 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; - addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, DwarfBitOffset); + + if (DD->getDwarfVersion() >= 4) + addUInt(MemberDie, dwarf::DW_AT_data_bit_offset, None, Offset); + else { + // + // 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. + // + // Struct Align Align Align + // v v v v + // +-----------+-----*-----+-----*-----+-- + // | ... |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 + // The endian-dependent DWARF 2 offset. + uint64_t DwarfBitOffset = Asm->getDataLayout().isLittleEndian() + ? OffsetToAlignment(Offset + Size, Align) + : StartBitOffset; + + addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, DwarfBitOffset); + } } else // This is not a bitfield. OffsetInBytes = DT->getOffsetInBits() / 8; |