Go to the previous, next section.
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
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.
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,
There are also methods provided to access all the variables that are
sub-variables of a given variable. The
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
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
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.