I’ve been working on improving the DWARF output of an LLVM-based Ada compiler. I’ve landed a few relatively straightforward patches so far, but the next set of problems requires bigger changes, so I thought I would post here.
The main issue is that Ada is more dynamic than C or C++. My focus in this post is that, in Ada, the size of a given type can vary, as can the offsets of fields.
This means that these fields in DIType
:
uint64_t SizeInBits;
uint64_t OffsetInBits;
… will need to be expressions in the general case. I still haven’t worked out all of the details of how to make this change.
One extra difficulty is that a packed record can have a field that is at a dynamic bit offset. I posted about this recently on dwarf-discuss:
https://lists.dwarfstd.org/pipermail/dwarf-discuss/2025-April/002666.html
The gist is that there is no way to represent this in DWARF 5.
The one response on the dwarf-discuss thread suggested using a DWARF extension: have the compiler allow an expression for DW_AT_data_bit_offset
. This would be fine by me, but I wonder whether LLVM would accept it.
Now, GNAT doesn’t seem to need the full generality here. In particular, from what I can tell, the byte offset of a field may be non-constant, but the bit offset within that byte will always be constant.
Taking advantage of this observation, GCC emits a DWARF 3 construct to work around this problem. That is, it emits an expression for DW_AT_data_member_location
, plus a constant DW_AT_bit_offset
. (This approach was obsoleted in DWARF 4 and removed entirely from DWARF 5.)
So one idea would be to replicate this behavior for LLVM. It’s somewhat ugly, though, because in addition to the deprecation, two attributes would be needed where, ideally, just one would do.
It may be worth noting that, in Ada, not every type can have a variable size – I think just arrays and records. So, maybe there’s some possible refactoring where a constant size is available in many cases.
I’ve gone back and forth a few times, but my current plan is to go with the “DWARF 3” approach: for the offset, add an optional “dynamic offset in bytes” to DIType
and, when this is set, generate the deprecated DWARF.
For the size, I suppose I will try changing the SizeInBits
to allow an expression. One wrinkle here is that an expression here would necessarily compute the size in bytes. So, the API may be a little inconsistent.
I’d appreciate any thoughts you may have.