A recent version of the Rust compiler (using LLVM 6) can generate DWARF like this for an enum: <2><2c92>: Abbrev Number: 10 (DW_TAG_union_type) <2c93> DW_AT_name : (indirect string, offset: 0x28bf): MoreComplicated <2c97> DW_AT_byte_size : 24 <2c98> DW_AT_alignment : 8 <3><2c99>: Abbrev Number: 18 (DW_TAG_member) <2c9a> DW_AT_type : <0x2cc8> <2c9e> DW_AT_byte_size : 24 <2c9f> DW_AT_bit_size : 8 <2ca0> DW_AT_bit_offset : 56 <2ca1> DW_AT_data_member_location: 0x1ffffffffffffff0 [...] First, and most importantly, the data member location is wrong. Second, I don't believe it is valid to emit both a byte size and a bit size. DWARF documents these as exclusive. The data member location comes from the code starting here: https://github.com/llvm-mirror/llvm/blob/master/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L1505 In particular what I believe is going wrong is that here: https://github.com/llvm-mirror/llvm/blob/master/lib/CodeGen/AsmPrinter/DwarfUnit.cpp#L1500-L1501 we have Size==8 and FieldSize==192. However, the alignment computation (which per the comment already seems suspect): // We can't use DT->getAlignInBits() here: AlignInBits for member type // is non-zero if and only if alignment was forced (e.g. _Alignas()), // which can't be done with bitfields. Thus we use FieldSize here. uint32_t AlignInBits = FieldSize; uint32_t AlignMask = ~(AlignInBits - 1); ... only works properly when the field size is a power of 2. One option for this code might be to tighten the definition of "bitfield" to only encompass things that actually require sub-byte resolution. If negative data member locations are desirable (Rust doesn't need them but maybe something does) then the code that gets the byte offset from the field offset probably has to be done using a signed type.
> Second, I don't believe it is valid to emit both a byte size and a bit size. > DWARF documents these as exclusive. It's not for DWARF v4 and later, but it is for earlier versions. I think the default is DWARF v2 compatibility, which seems to match your output. From http://www.dwarfstd.org/doc/dwarf-2.0.0.pdf: > If the member entry describes a bit field, then that entry has the following attributes: > 1. A DW_AT_byte_size attribute whose constant value is the number of bytes that contain an instance of the bit field and any padding bits. The byte size attribute may be omitted if the size of the object containing the bit field can be inferred from the type attribute of the data member containing the bit field. > 2. A DW_AT_bit_offset attribute whose constant value is the number of bits to the left of the leftmost (most significant) bit of the bit field value. > 3. A DW_AT_bit_size attribute whose constant value is the number of bits occupied by the bit field value. So for your example, the field is 192 bits (24 bytes) wide, the value takes up 8 bits (1 byte) and we have 184 bits of padding (23 bytes). Does that sound right?
(In reply to Jonas Devlieghere from comment #1) > > Second, I don't believe it is valid to emit both a byte size and a bit size. > > DWARF documents these as exclusive. > > It's not for DWARF v4 and later, but it is for earlier versions. I think the > default is DWARF v2 compatibility, which seems to match your output. The CU header says version 4. > So for your example, the field is 192 bits (24 bytes) wide, the value takes > up 8 bits (1 byte) and we have 184 bits of padding (23 bytes). Does that > sound right? Yes, I think so. @vadimcn found a workaround for the rust compiler: https://github.com/rust-lang/rust/issues/32920#issuecomment-412296203 Something like this will be landing in rustc soon.