[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