# Expression Operator For Constants

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 stack. - 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 "pieces".) (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. -cary ----------------------- 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. -cary