Even though the base instruction
class does not contain any
source operand fields, it does provide several methods to access the
source operands in derived classes. First, the num_srcs
method
returns the number of source operands in a particular instruction. Once
you know the number of sources, you can access them by number. This is
frequently useful when you need to visit all of the source operands
without concern for how they are used in the instruction. The
src_op
and set_src_op
methods provide this access. The
operands are numbered beginning from zero (like arrays in C).
Specifying an operand number that does not exist will cause an error.
Do not use these methods to access a particular operand field in an
instruction; the operand numbering used here is implementation-defined
and subject to change.
The src_map
method provides an alternate way to visit all of the
source operands. It applies a function that you specify to all of the
source operands. This can be used to implement recursive descents of
expression trees by making the mapped function call src_map
if
the operand is an instruction. This is similar to what the
instr_map
method in the tree_instr
class does.
See section Instruction Nodes. The mapped function must match the
src_map_f
type which has three parameters: a pointer to the
instruction, a pointer to a copy of the operand, and a void*
value used to pass any other information needed by the function. If the
function returns TRUE
, the copy of the operand will be assigned
to the actual operand field within the instruction. If it returns
FALSE
, the source operand field is not modified.
The SUIF library requires that instruction pointers in operands be
consistent. That is, a source operand may only point to an instruction
if the destination of that instruction points back to where the result
value is used. Because of this, you cannot simply overwrite a source
operand that contains an instruction pointer. Doing so would leave the
other instruction with an inconsistent destination operand. Instead,
you must first use the source operand's remove
method. This
clears the instruction pointers in both the source and destination
operands. If the source instruction was part of an expression tree
(i.e. it didn't have its own parent tree_instr
node),
remove
also clears its parent
pointer by calling the
parent's remove_instr
method (see section Instruction Nodes). If the
source operand is not an instruction, the remove
method does
nothing so it is always safe to use it. The instruction
class
also has a remove
method which does the same thing.
As an example, the following code clears all of the source operands in an instruction:
for (int n = 0; n < i->num_srcs(); n++) { i->src_op(n).remove(); i->set_src_op(n, operand()); }