mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
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
This commit is contained in:
parent
7a46345c15
commit
ae61e8a345
@ -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;
|
||||
|
56
test/DebugInfo/ARM/big-endian-bitfield.ll
Normal file
56
test/DebugInfo/ARM/big-endian-bitfield.ll
Normal file
@ -0,0 +1,56 @@
|
||||
; RUN: llc -O0 -filetype=obj -mtriple=armeb-none-linux %s -o - \
|
||||
; RUN: | llvm-dwarfdump --debug-dump=info - | FileCheck %s
|
||||
; Generated from:
|
||||
; struct S {
|
||||
; int j:5;
|
||||
; int k:6;
|
||||
; int m:5;
|
||||
; int n:8;
|
||||
; } s;
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
|
||||
|
||||
%struct.S = type { i24 }
|
||||
|
||||
@s = common global %struct.S zeroinitializer, align 4
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!12, !13, !14}
|
||||
!llvm.ident = !{!15}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
|
||||
!1 = !DIFile(filename: "bitfield.c", directory: "/Volumes/Data/llvm")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = distinct !DIGlobalVariable(name: "s", scope: !0, file: !1, line: 6, type: !5, isLocal: false, isDefinition: true, variable: %struct.S* @s)
|
||||
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, line: 1, size: 32, align: 32, elements: !6)
|
||||
!6 = !{!7, !9, !10, !11}
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"j"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x00)
|
||||
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!7 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !5, file: !1, line: 2, baseType: !8, size: 5, align: 32)
|
||||
!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"k"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x05)
|
||||
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!9 = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: !5, file: !1, line: 3, baseType: !8, size: 6, align: 32, offset: 5)
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"m"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x0b)
|
||||
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!10 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !5, file: !1, line: 4, baseType: !8, size: 5, align: 32, offset: 11)
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"n"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x10)
|
||||
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!11 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !5, file: !1, line: 5, baseType: !8, size: 8, align: 32, offset: 16)
|
||||
!12 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!13 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!14 = !{i32 1, !"PIC Level", i32 2}
|
||||
!15 = !{!"clang version 3.9.0 (trunk 267633)"}
|
68
test/DebugInfo/X86/bitfields-dwarf4.ll
Normal file
68
test/DebugInfo/X86/bitfields-dwarf4.ll
Normal file
@ -0,0 +1,68 @@
|
||||
; RUN: llc -mtriple x86_64-apple-macosx -O0 -filetype=obj -o - %s \
|
||||
; RUN: | llvm-dwarfdump -debug-dump=info - | FileCheck %s
|
||||
;
|
||||
; Generated from:
|
||||
; #include <stdint.h>
|
||||
; #pragma pack(1)
|
||||
; struct PackedBits
|
||||
; {
|
||||
; char a;
|
||||
; uint32_t b : 5,
|
||||
; c : 27
|
||||
; } s;
|
||||
; #pragma pack()
|
||||
|
||||
source_filename = "bitfield.c"
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx"
|
||||
|
||||
%struct.PackedBits = type <{ i8, i32 }>
|
||||
|
||||
@s = common global %struct.PackedBits zeroinitializer, align 1
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!14, !15, !16}
|
||||
!llvm.ident = !{!17}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
|
||||
!1 = !DIFile(filename: "bitfield.c", directory: "/Volumes/Data/llvm")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = distinct !DIGlobalVariable(name: "s", scope: !0, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, variable: %struct.PackedBits* @s)
|
||||
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "PackedBits", file: !1, line: 3, size: 40, align: 8, elements: !6)
|
||||
!6 = !{!7, !9, !13}
|
||||
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"a"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK-NOT: DW_AT_bit_offset
|
||||
; CHECK-NOT: DW_AT_data_bit_offset
|
||||
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!7 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !5, file: !1, line: 5, baseType: !8, size: 8, align: 8)
|
||||
|
||||
!8 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
|
||||
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"b"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK-NOT: DW_AT_bit_offset
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x08)
|
||||
; CHECK-NEXT: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!9 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !5, file: !1, line: 6, baseType: !10, size: 5, align: 32, offset: 8)
|
||||
|
||||
!10 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !11, line: 183, baseType: !12)
|
||||
!11 = !DIFile(filename: "/Volumes/Data/llvm/_build.ninja.release/bin/../lib/clang/3.9.0/include/stdint.h", directory: "/Volumes/Data/llvm")
|
||||
!12 = !DIBasicType(name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned)
|
||||
|
||||
; CHECK: DW_TAG_member
|
||||
; CHECK-NEXT: DW_AT_name{{.*}}"c"
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK-NOT: DW_AT_bit_offset
|
||||
; CHECK: DW_AT_data_bit_offset [DW_FORM_data1] (0x0d)
|
||||
; CHECK-NEXT: DW_AT_data_member_location [DW_FORM_data1] (0x00)
|
||||
!13 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !5, file: !1, line: 7, baseType: !10, size: 27, align: 32, offset: 13)
|
||||
|
||||
!14 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!15 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!16 = !{i32 1, !"PIC Level", i32 2}
|
||||
!17 = !{!"clang version 3.9.0 (trunk 267633)"}
|
Loading…
Reference in New Issue
Block a user