[llvm] r267895 - Debug info: Support DWARF4 bitfields via DW_AT_data_bit_offset.

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 28 08:37:49 PDT 2016


Author: adrian
Date: Thu Apr 28 10:37:48 2016
New Revision: 267895

URL: http://llvm.org/viewvc/llvm-project?rev=267895&view=rev
Log:
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.

Added:
    llvm/trunk/test/DebugInfo/ARM/big-endian-bitfield.ll
    llvm/trunk/test/DebugInfo/X86/bitfields-dwarf4.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=267895&r1=267894&r2=267895&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Thu Apr 28 10:37:48 2016
@@ -1395,41 +1395,43 @@ void DwarfUnit::constructMemberDIE(DIE &
       // 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;

Added: llvm/trunk/test/DebugInfo/ARM/big-endian-bitfield.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/ARM/big-endian-bitfield.ll?rev=267895&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/ARM/big-endian-bitfield.ll (added)
+++ llvm/trunk/test/DebugInfo/ARM/big-endian-bitfield.ll Thu Apr 28 10:37:48 2016
@@ -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 }
+
+ at 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)"}

Added: llvm/trunk/test/DebugInfo/X86/bitfields-dwarf4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/bitfields-dwarf4.ll?rev=267895&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/bitfields-dwarf4.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/bitfields-dwarf4.ll Thu Apr 28 10:37:48 2016
@@ -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 }>
+
+ at 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)"}




More information about the llvm-commits mailing list