LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 36654 - DwarfUnit::constructMemberDIE computes incorrect member location
Summary: DwarfUnit::constructMemberDIE computes incorrect member location
Status: NEW
Alias: None
Product: libraries
Classification: Unclassified
Component: DebugInfo (show other bugs)
Version: trunk
Hardware: PC Linux
: P enhancement
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-03-08 13:05 PST by Tom Tromey
Modified: 2018-09-18 05:06 PDT (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Tromey 2018-03-08 13:05:48 PST
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.
Comment 1 Jonas Devlieghere 2018-09-18 04:39:04 PDT
> 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?
Comment 2 Tom Tromey 2018-09-18 05:06:07 PDT
(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.