Continuing the work discussed in the RFC, this is the next patch for implementing variadic debug values. This patch adds a new instruction that can represent variadic debug values, DBG_VALUE_VAR. This patch alone covers the addition of the instruction and a set of basic code changes in MachineInstr and a few adjacent areas, but does not correctly handle variadic debug values outside of these areas, nor does it generate them at any point; these will be introduced in later patches.
The new instruction is similar to the existing DBG_VALUE instruction, with the following differences:
- The operands are in a different order; DBG_VALUE’s operands are Value, Offset, Variable, Expression. DBG_VALUE_VAR’s operands are Variable, Expression[, Values]*
- Any number of values may be used in the instruction following the Variable and Expression operands. These are referred to in code as “debug operands”, and are indexed from 0 so that getDebugOperand(X) == getOperand(X+2).
- The Expression in a DBG_VALUE_VAR must use the DW_OP_LLVM_arg operator, also added in this patch, to pass arguments into the expression: none of the values in the instruction are pushed onto the expression stack by default.
The new DW_OP_LLVM_arg operator is only valid in expressions appearing in a DBG_VALUE_VAR; it takes a single argument and pushes the debug operand at the index given by the argument onto the Expression stack. For example, in the instruction below:
DBG_VALUE_VAR !”a”, ! DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_minus), %0, %1
DW_OP_LLVM_arg, 0 has the meaning “Push the 0th debug operand (%0) onto the stack.” The whole expression thus evaluates to %0 - %1.
There are two main motivations for introducing this as a separate instruction rather than simply changing the old instruction:
- Smaller change to MIR: by creating a new instruction we avoid invalidating old MIR, and will not cause produced MIR to be different in any cases apart from where the new instruction is needed. This simplifies the process of getting this change integrated, without preventing us from eventually removing the old instruction if desired.
- Conciseness: DBG_VALUE_VAR instructions are more verbose than the existing instruction, which neatly covers simple direct and indirect values. By using DBG_VALUE_VAR for only the complex cases where it is needed, we avoid making debug information any more incomprehensible. This also simplifies (in my opinion) the question of whether or not to automatically push debug operands onto the expression stack (as was discussed in the original RFC).