1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
After simplification the structures are as follows:
The top-most scope contains of a double-linked list of declarations.
Declarations
------------
Each declaration declares one of the following:
* a struct, union, enum
The `identifier' field of the declaration struct is NULL in this
case. The `type_name' field contains the struct, union, enum
definition.
The `storage', `mod_inline' fields don't contain any info.
* a type
The `identifier' field of the declaration struct contains the
name of the new type. The `type_name' field contains the
type definitions.
The `storage' field contains STORAGE_TYPEDEF.
* a variable
The `identifier' contains the name of the variable.
`type_name' is the type of the variable.
If `storage' is STORAGE_EXTERN this is only an extern declaration.
In case of STORAGE_STATIC it is a local variable. Otherwise
(STORAGE_NONE) it is a global variable.
STORAGE_AUTO and STORAGE_REGISTER define function local
variables. Parameters are marked STORAGE_PARAM.
If `initializer' field contains the initializer expressions if
it isn't NULL.
* a function
The `identifier' contains the name of the function.
`type_name' is the type of the function. The type contains
the parameter list.
If `storage' is STORAGE_EXTERN this is only an extern declaration.
It also is only a forward declaration if the `stmt' field is NULL.
In case of STORAGE_STATIC it is a local function. Otherwise
(STORAGE_NONE) it is a global function.
`stmt' contains the code.
The `mod_inline' marks functions to be inlined.
Inlining is done during simplification. After simplification
no inline function remain.
`attr_noreturn' is true if the function doesn't return
(like the exit/abort functions).
`nbits' is an expression only valid in struct/union scopes. It is not
used, yet.
`clone' is used during inlining only.
`assign_expr', `acount', `wcount' and `rcount' are used during optimization
only.
`live_noreg', `move_first', `move_last', `storage_class',
`choices', `storage_register', `spills' `degree',
`conflict_first', `conflict_last',
`conflict_save_first', `conflict_save_last' are used during
register allocation only.
Code
----
The `stmt' field of a declaration contains the code and the variables
of a function. The `stmt' points to a stmt struct of type STMT_BLOCK.
STMT_BLOCKs have a `scope' field pointing to a scope (containing a double
linked list of declarations; see above) and `stmt_first' and `stmt_last'
fields being the head/tail of a double linked list of stmt structs.
Each stmt struct is one of the following:
* a label
In this case the `identifier' field contains a pointer to the
name of the label. The `stmt0' field always contains a pointer
to a null-statement (type = STMT_NULL).
* an expression statement
The expression is an assignment or a function-call expression.
* an if statement
The `expr0' field contains a pointer to an expression of type
EXPR_EQUAL, EXPR_NOT_EQUAL, EXPR_LESS, EXPR_LESS_EQUAL,
EXPR_GREATER, EXPR_GREATER_EQUAL.
The `stmt0' pointer always points to a goto-statement.
* a switch statement
The `expr0' field contains a pointer to an expression.
The expression is always of type EXPR_IDENTIFIER.
The `stmt0' pointer points to a block. The block (in a
stmt struct) doesn't contain any declarations but only
case and default statements. The case statements `expr0' fields
always point to an expression of type EXPR_INTEGER.
Case and default statements both always have `stmt0' pointers
pointing to a goto statement. Switch statements always have
a default statement.
* a goto statement
All goto statements only have a valid `identifier' member
containing a pointer to the name of the label to go to.
* a return statement
Each function have one and only one return statement as the
last statement in the statement list.
In case the function is no `void' function the `expr0' member
points to the return expression. The return expression is
of type EXPR_IDENTIFIER or a constant (EXPR_INTEGER,
EXPR_REAL, EXPR_AMPHERSAND).
* an asm statement
The `code' member points to the string containing the asm
statements.
The `output', `input' and `change' fields (if non-NULL)
contain a double linked list of constraints. Each constraint
has a `string' field with the register/memory definition
and an `expr' field with the expression to pass from/to
the code.
* a va_start/va_end statement
The `expr0' field containts the `args' parameter. The second
parameter of the va_start call is stored in `expr1'.
No other types of statements are valid after simplification.
Optimization will stay with this constraints.
Expressions
-----------
All expressions are as follows:
* assignment expressions
The `expr0' pointer points to the lhs of the assignment.
The `expr1' field contains the pointer of the rhs.
* function/procedure calls
The `expr0' is the name of the function to be called or
a pointer to such a function.
`expr1' is a pointer to an EXPR_LIST element which has
the `first' and `last' fields used. `first' and `last'
form a double linked list of `expr' objects. Each
such expression holds one parameter for the function
call. If no parameters are present, `first' and `last'
are both NULL. All parameters are simple expressions.
Simple expressions are:
* an identifier
`type' is EXPR_IDENTIFIER. `declaration' points to the
declaration of the identifier. The declaration contains
the name, type, storage type, etc. of the identifier.
* a constant
`type' is EXPR_INTEGER, EXPR_REAL. `type_name' contains
the type of the constant (int8, uint8, ..., uint64,
float32, float64, float80). `integer' or `real' contain
the constant.
* an address
`type' is EXPR_TYPE_CONVERSION, `expr0' is EXPR_AMPHERSAND
and `expr0->expr0' is EXPR_IDENTIFIER in this case.
`expr0' might be EXPR_IDENTIFIER if the identifier is
an array.
Examples are expressions like "(int) &var" or "(int) array".
Unary expressions are:
* a star expression
`type' is EXPR_STAR. `expr0' is a type conversion and
`expr0->expr0' is an expression containing an address.
An example expression is "*(int *) var".
* a type conversion
`type' is EXPR_TYPE_CONVERSION. `type_name' contains the
type be converted to. `expr0' is the expression to be converted.
* a NEG or INV expression
`type' is EXPR_NEG or EXPR_INV. `expr0' containts the pointer
to the expression to be negated/inverted.
Binary expressions are:
`type' might contain: EXPR_ADD, EXPR_SUB, EXPR_MUL, EXPR_DIV,
EXPR_MOD for the standard arithmetic operations, EXPR_LEFT,
EXPR_RIGHT for shift operations, EXPR_EQUAL, EXPR_NOT_EQUAL,
EXPR_LESS, EXPR_LESS_EQUAL, EXPR_GREATER, EXPR_GREATER_EQUAL
for comparisons. `expr0' and `expr1' contain the two
operands.
No other expressions remain after simplification/optimization steps
are performed.
|