Go to the previous, next section.

Basic Features of Variables

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.

Go to the previous, next section.