Expression Operator For Constants

Revision as of 12:51, 8 March 2007 by >Quenelle (New page: <pre> and Daniel Berlin wrote: > > Why not just a DW_OP_constant_value? Yes, this is probably better. I did consider that approach, but it seemed potentially confusing, given that it...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

and Daniel Berlin wrote:
> > Why not just a DW_OP_constant_value?

Yes, this is probably better.

I did consider that approach, but it seemed potentially confusing,  
given that it would be quite different from the existing DW_OP_const*  
and DW_OP_lit* operators. Nevertheless, Jim's point about large  
values is a good one, and I think it overrides my concern about  
confusion. If this new operator were introduced in Section 2.5.1 (or  
in a new section immediately following), it could be made clear that  
this operator provides a constant value as opposed to a constant to  
be used for address computation. The rules for its use, I think,  
could be exactly the same as those for DW_OP_reg*, and could be used  
as part of a DW_OP_piece construction as well.

> > (The spec really needs a grammar for location expressions; writing out
> > grammar rules in English is clumsy.)

I think what it needs isn't so much a grammar as a type system. The  
grammar for a postfix expression on a simple stack is trivial.  
Consider introducing four types of values that can exist on the  
stack: integers, register names, constant values, and "pieces". Now  
each operator can be described in terms of what types of values it  
can consume from the stack and what type of value it pushes back onto  
the stack (if any):

- The DW_OP_const* and DW_OP_lit* operators push an integer onto the  
- The DW_OP_reg* operators push a register name.
- The DW_OP_constant_value operator pushes a constant value.
- The DW_OP_piece (and DW_OP_bit_piece, if that's in yet) operator  
can consume any one of the other three types, and pushes a "piece"  
back onto the stack.
- Most of the remaining operators consume one or two integers and  
push an integer.

At the end of the expression, we must have a stack that has either  
(a) exactly one value of type integer, register name, or constant  
value; or (b) one or more values of type "piece". (In other words, if  
the stack contains more than one value at the end, they must all be  

(DW_OP_skip and DW_OP_bra may take a little additional descriptive  
effort, but as long as expression validity is defined in terms of  
what kinds of values can be consumed by each operator and what the  
stack has to look like at the end, it should be complete.)

This relates back to an April 2005 discussion on this list about  
DW_OP_piece. That discussion suggested treating DW_OP_piece as  
removing a value from the stack and contributing a piece description  
"somewhere else". I think using separate types makes it conceptually  
clearer, and the allowable expressions are constrained by the types  
that each operator can consume and the requirements for the ending  
contents of the stack.



David Anderson wrote:

> > History note:  We really intended the OP evaluation
> > stack to have simply 'address size integers'
> > and avoid such a 'type' system entirely. Even avoiding signed/ 
> > unsigned issues (as that's not a  problem
> > with twos-complement). Not as an oversight, but as a design decision.
> >
> > Whether that simple address-size-integer
> > value stack  is still sufficient is open to discussion, but
> > any type system introduces all the 'conversion' issues.

Nothing in what I suggested would introduce any conversion issues --  
there are no implicit conversions from, say, integer to constant  
value or register name, and there are no operators that would do any  
conversion. The type system is just there to aid the semantic  
description, and isn't meant to suggest any specific implementation.  
In fact, since I'm not proposing to change the semantics -- just a  
way of describing them -- it shouldn't have any impact at all on  
anyone's implementation. The implementations have to deal with  
register names and piece descriptions today, so they must already  
have something more than just a stack of address-size-integers.