Go to the previous, next section.

Sub-Variables

The data objects represented by variable symbols are allowed to overlap, but only in a carefully controlled way. The mechanism that allows this is the existence of sub-variables. One variable symbol is allowed to be a sub-variable of another, occupying a portion of the parent variable symbol specified by an offset and the types of the two variables. This allows arbitrary hierarchies of variable symbols and the relations among them are known at all times.

For any hierarchy, there will always be one root ancestor in terms of which everything else can be specified. If neither of two variables is a sub-variable of anything else, the two variables are guaranteed to be completely independent objects.

Use of sub-variables is optional. Anything that can be represented with the sub-variable can be represented in terms of its parent by loading from the parent's address plus the offset and with the type of the child variable.

Sub-variable names are independent of their parent variable symbols. Whether or not they have the userdef flag set is also independent of the parent. There is nothing inconsistent in having a parent which is user-defined and a sub-variable which is not (if some stage of the compiler decides a particular piece of a larger user-defined object has some special property and wants a handle on it), and neither is there anything inconsistent in a sub-variable that is user-defined in a parent which is not (user-defined variables that are equivalenced cause the system to create a new aggregate object).

Among the properties general to the sym_node class that may be changed by the user, the only one for which sub-variables have any special restriction is the symbol table in which they reside. A sub-variable should be in the same symbol table as its parent. They may be temporarily in different symbol tables while being moved around, so the library doesn't enforce the restriction that they always be in the same symbol table at all times. The library does enforce the restrictions that they must be in the same table when a symbol is first linked in as a sub-variable by the var_sym::add_child method and when the owning symbol table of the parent or child variable is written out.

Among properties specific to variable symbols that the user has control over, some may be set independently in sub-variables, and some are kept consistent between sub-variables and their parents. For the properties that are kept consistent, the value of the property in the sub-variable is slaved to that in the parent. In that case, either setting or getting the property from the sub-variable has exactly the same effect as getting or setting it from the parent variable. If and when the sub-variable is removed from being a sub-variable by the var_sym::remove_child method, the current values of those properties in the sub-variable are set to the values of the parent at the time of separation and can be changed independently from then on.

Sub-variables are attached to parent variables by the add_child method. The user tells the parent which variable symbol is to be the sub-variable and at what offset it begins and the library makes it a sub-variable. If it is ever necessary to remove a sub-variable, the remove_child method may be used. It undoes what add_child did making the sub-variable into a fully independent variable. The argument of remove_child must already be a sub-variable of the given variable. This method should be called before a sub-variable is deleted, or else there will be dangling pointers from the parent.

Two methods, parent_var and offset, provide a way to see whether a variable is a sub-variable, and if so what variable it is a sub-variable of and where it is in that variable. If a variable is not a sub-variable, parent_var will return NULL. If it is a sub-variable, this method will return the variable symbol for the variable of which it is a sub-variable. If it is a sub-variable, the offset method will return the offset in bits of the beginning of the sub-variable from the beginning of the parent variable. If called on a variable that is not a sub-variable, offset will return zero.

There are also methods provided to access all the variables that are sub-variables of a given variable. The num_children method will return the number of sub-variables for a given variable symbol. Given a non-negative number less than the number of children, the child_var method will return one of the sub-variables. The ordering of the sub-variables is the order in which they were added, starting with zero for the oldest remaining sub-variable. For example, child_var(2) will return the sub-variable that was the third added of those that are still sub-variables. Hence calling this method for each integer from zero through the number of children minus one will give all the sub-variables. It is an error to call child_var with an argument greater than or equal to the number of sub-variables or less than zero.

Given a variable that may or may not be a sub-variable, the root_ancestor will return the unique ancestor of a sub-variable that is not itself a sub-variable, or the variable itself if it is not a sub-variable. The root_offset method will return the offset of the variable within that root ancestor, which will be the sum of all the offsets along the path up. The overlaps method is provided to determine whether any two variables overlap to any extent. If the result is TRUE, then they definitely overlap, at least in part; otherwise, the result is FALSE, and the variables do not overlap at all.

It is often useful to know whether a given portion of a variable treated as a given type has a corresponding sub-variable. The find_child method will answer that question. If such a sub-variable exists, it will return a pointer to it, otherwise it will return NULL.

As an alternative to attaching an existing variable symbol as a sub-variable to another variable, the build_child method is provided. Given a location and type within a variable and a name, it creates an sub-variable, installs it in the proper symbol table if the parent variable was in a symbol table, and adds it as a sub-variable, all at once.

Go to the previous, next section.