[Dwarf-Discuss] PROPOSAL: Constant expressions in location lists
Alexandre Oliva
aoliva@redhat.com
Sun Jan 6 10:03:15 GMT 2008
On Jan 6, 2008, Roland McGrath <roland at redhat.com> wrote:
>> When you say "rematerialized for debugging purposes", do you mean that
>> the value is a constant known at build time, or do you mean that it
>> can be computed from the current state of the program, even though the
>> variable has no location allocated to it at the moment?
> I believe he was referring to the general case, i.e. the latter.
Yep, I talked to him about this just before he posted his e-mail.
Also, on Dec 27, not knowing you'd already started discussing this
here, I submitted an extension proposal at
http://dwarfstd.org/Comment.php, that Michael Eager has already
acknowledged but hasn't added to the Open Issues page yet.
In that proposal, I use DW_OP_value as the operator name.
Frank suggested an alternate representation, that might be less
intrusive and more backward-compatible. Something along the lines of
DW_AT_value, that could hold a loclistptr, but in which the
expressions would represent values, rather than locations. (We can't
just reuse DW_AT_const_value, because adding loclistptr to its
available classes would change the meaning of DW_FORM_data[48] :-(
When both DW_AT_value and DW_AT_location are present, they would add,
rather than override each other, just like overlapping ranges in
DW_AT_location add up. So, at the same PC, one could have multiple
locations for a piece of a variable, and multiple value expressions as
well. The effect would be equivalent to that of adding a deref to
each piece of each DW_AT_location location expression that mentions a
memory address, except that DW_AT_location locations are assumed to be
modifiable (and thus exclusively assigned to the mentioned variable),
whereas a dereferenced address or a register in a DW_AT_value is
expected to be non-modifiable or shared.
This reminds me of one doubt I have. Consider a variable that
represents a struct-typed object. If the compiler scalarizes it, and
each member becomes an independent implementation variable, must the
compiler emit a separate location list entry for the entire source
variable every time any of the members change location, or can it use
separate entries with DW_OP_nop for all but one of the pieces, and
rely on overlapping ranges for the debugger to put it all together?
I.e., consider
struct { int x, y; };
Could a representation such as:
[L0,L1) [nop] DW_OP_piece 4 DW_OP_reg1 DW_OP_piece 4
[L1,L2) DW_OP_reg0 DW_OP_piece 4 DW_OP_reg1 DW_OP_piece 4
[L2,L3) DW_OP_reg0 DW_OP_piece 4 [nop] DW_OP_piece 4
be shortened to:
[L0,L2) [nop] DW_OP_piece 4 DW_OP_reg1 DW_OP_piece 4
[L1,L3) DW_OP_reg0 DW_OP_piece 4 [nop] DW_OP_piece 4
this becomes even more important if any of the pieces is
simultaneously available in more than one location (say, its stack
slot and a register it is live in throughout a loop).
BTW, It might have been useful to have accepted negative operands to
DW_OP_piece to cover these cases, as in:
DW_OP_reg0 DW_OP_piece 4 DW_OP_piece -4 DW_OP_fbreg -60 DW_OP_piece 4
or perhaps we could introduce DW_OP_both:
DW_OP_reg0 DW_OP_fbreg -60 DW_OP_both DW_OP_piece 4
but this doesn't work all that well with say a bit field partially
scalarized into registers that retains memory backstore, and it
doesn't work at all for DW_OP_bit_piece, should the second operand of
DW_OP_bit_piece have to vary for each component (e.g. if we were to
represent various portions of the memory backstore as bit-fields
themselves)
So perhaps something like DW_OP_overlap, with a bit-count, would be
best:
DW_OP_reg0 DW_OP_piece 4 DW_OP_overlap 32 DW_OP_fbreg -60 DW_OP_piece 4
DW_OP_overlap might accept negative values, mainly for bit-padding,
avoiding the need for DW_OP_bit_piece's useless second operand, both
in backtracking and in advancing the bit position, as in:
DW_OP_reg0 DW_OP_bit_piece 15 0 \
DW_OP_overlap 15 \
DW_OP_fbreg -52 DW_OP_bit_piece 15 0 \
DW_OP_reg1 DW_OP_bit_piece 15 0 \
DW_OP_overlap 15 \
DW_OP_fbreg -52 DW_OP_bit_piece 15 15 \
DW_OP_overlap -2 \
...
which would be better represented as
DW_OP_reg0 DW_OP_bit_piece 15 0 \
DW_OP_reg1 DW_OP_bit_piece 15 0 \
DW_OP_overlap 30 \
DW_OP_fbreg -52 DW_OP_piece 4 \
...
But I'm not sure about the wisdom of introducing such explicit
backward-incompatible overlap mechanisms, if empty DW_OP_pieces can be
taken from overlapping ranges. It can be more compact, for sure, but
it amounts to a lot of complexity and redundancy as well.
> Frank referred to my proposal in http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2007-May/000478.html
> This handles the general case by computing values (or values of pieces)
> with arbitrary DWARF expressions. Compile-time constants are a degenerate
> case where those expressions use only const*/lit* ops.
http://dwarfstd.org/ShowIssue.php?issue=070512.1&type=closed appears
to indicate that DW_OP_implicit_value, that you mentioned in your
e-mail, was actually accepted in a far more limited way, that only
supports literal constant values.
Unfortunately, there's an error in
http://dwarfstd.org/Issues.php?type=closed because, just before the
070512.1 issue, there are two issues numbered 070426.2, and the second
of them, that appears to be the one that introduced
DW_OP_implicit_value, is not trivially accessible.
Its correct number is 070426.1, and it should link to
http://dwarfstd.org/ShowIssue.php?issue=070426.1&type=closed
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member http://www.fsfla.org/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}
More information about the Dwarf-discuss
mailing list