The type of a variable can be accessed via the type
and
set_type
methods. The type must be visible in the scope where
the variable is defined. Since the type specifies the amount of storage
occupied by the variable, the size of the type must not be zero. This
means that function types, void types, incomplete structure and union
types, and array types with unknown bounds cannot be used for variables
(4). Pointers to those types are acceptable, of course.
Sub-variables may have any type so long as the size of that type and
the sub-variable's offset allow it to remain within the parent
variable.
Variable symbols may also be allocated to machine registers. A flag is
used to indicate variables that are contained in registers; the
is_reg
method returns the value of this flag and the
set_reg
and reset_reg
methods change its value. The
reg_num
annotation can be attached to a register variable to
specify the corresponding machine register number (see section Miscellaneous Annotations). Variables cannot be registers if they have variable
definitions. Whether a sub-variable is a register or not is slaved to
this property in its parent.
Symbols for variables that are not allocated on the stack must have
separate variable definitions (see section Variable Definitions) or else
they are merely declarations of external symbols. The
has_var_def
method checks if a variable symbol has a separate
definition, and the definition
method returns a pointer to the
definition. It is an error to call definition
for a variable
that does not have a definition, so be sure to check first.
Sub-variables are never allowed to have their own definitions.
The var_sym
class includes several methods to check various
attributes and flags for variables. The is_auto
method checks if
a variable is in the automatic storage class, i.e. if it will be
allocated on the stack. Global variables and static local variables
(those with variable definitions) are not automatic and is_auto
returns FALSE
for them; other variables are automatic. The
is_static
method is the opposite of is_auto
, except that
register variables are not considered to be static.
The formal parameters of a procedure are represented by variables that
have a special flag set. The is_param
method returns the value
of this flag, and the set_param
and reset_param
methods
change its value. Identifying the formals with flags does not allow
their order to be specified, so the procedure symbol table maintains a
list of the formals (see section Procedure Symbol Tables). All of the
variables for which is_param
returns TRUE
should be on the
list of parameters, and conversely, all variables on the parameter list
should have the flag set. Sub-variables are not allowed to be
parameters; sub-variables of parameters are allowed, but these are not
considered parameters themselves.
Because many compiler optimizations are only applicable to variables
that are not aliased, it is important to identify such variables. Each
variable symbol includes a flag to indicate whether the variable has its
address taken, and thus whether it could be aliased. The
is_addr_taken
method returns the value of this flag. The
front-end should set these flags, but they may also need to be updated
as the code is transformed. The set_addr_taken
and
reset_addr_taken
methods can be used to change the flag for a
particular variable symbol. For sub-variables, this property is
slaved to this property in the parent variable.
Besides requiring that variables not be aliased, most optimizations also
do not apply to aggregate data structures. The is_scalar
method
checks the type of a variable symbol and returns TRUE
if it is
not an aggregate type. Arrays, structures, and unions are considered to
be aggregates.
In general, most optimizations target scalar variables that are
guaranteed not to be aliased. Since it is difficult to guarantee that
global variables with external linkage are not addressed, those
variables may be aliased even if their flags indicate that they are not
addressed. Rather than checking these conditions separately, the
library provides one method to check them all. The is_spilled
method returns TRUE
for variables that are static, addressed, or
aggregates. Variables that are not spilled can then be targeted for
optimization.