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
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 91c490f..08800f4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1395,41 +1395,43 @@
       // 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;