From 57c7a62b973e909c29a7da46bae11051b16a5de8 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Sat, 27 Jun 2015 20:12:43 +0000 Subject: [PATCH] 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 --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 37 ++++++++++++++++++------------- llvm/test/DebugInfo/ARM/bitfield.ll | 2 +- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 44de340..ca9951e 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. diff --git a/llvm/test/DebugInfo/ARM/bitfield.ll b/llvm/test/DebugInfo/ARM/bitfield.ll index 9b41e4e..8f9d95d3 100644 --- a/llvm/test/DebugInfo/ARM/bitfield.ll +++ b/llvm/test/DebugInfo/ARM/bitfield.ll @@ -14,7 +14,7 @@ ; CHECK: DW_AT_byte_size {{.*}} (0x04) ; CHECK: DW_AT_bit_size {{.*}} (0x1c) ; CHECK: DW_AT_bit_offset {{.*}} (0x18) -; CHECK: DW_AT_data_member_location {{.*}}00 +; CHECK: DW_AT_data_member_location {{.*}}04 target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" target triple = "thumbv7-apple-ios" -- 2.7.4