To declare global variables, using a mixture of I6 Globals and array entries.
void I6TargetVariables::create_generator(code_generator *gtr) { METHOD_ADD(gtr, DECLARE_VARIABLES_MTID, I6TargetVariables::declare_variables); METHOD_ADD(gtr, EVALUATE_VARIABLE_MTID, I6TargetVariables::evaluate_variable); }
§2. In an ideal world we would implement all Inter global variables using Global, thus making them I6 global variables as well. But when I6 compiles to the Z-machine VM, there's an absolute limit of 240 globals, so we do not live in an ideal world. As a compromise, we make all the kit-declared variables use Global (for speed) and have all of the rest use entries in an array called Global_Vars, at the cost of a lookup whenever we read or write them.
void I6TargetVariables::declare_variables(code_generator *gtr, code_generation *gen, linked_list *L) { int k = 1; inter_symbol *var_name; LOOP_OVER_LINKED_LIST(var_name, inter_symbol, L) { inter_tree_node *P = var_name->definition; inter_pair val = VariableInstruction::value(P); if (SymbolAnnotation::get_b(var_name, ASSIMILATED_IANN) == FALSE) { if (k == 1) Begin the array2.1; Variables created by Inform 7 source text all go into the array2.2; } else { Variables created by kits all become Globals in I62.4; } } if (k > 1) End the array2.3; }
segmentation_pos saved = CodeGen::select(gen, global_variables_array_I7CGS); text_stream *OUT = CodeGen::current(gen); WRITE("Array Global_Vars --> 0\n"); CodeGen::deselect(gen, saved);
- This code is used in §2.
§2.2. Variables created by Inform 7 source text all go into the array2.2 =
SymbolAnnotation::set_i(var_name, I6_GLOBAL_OFFSET_IANN, (inter_ti) k); segmentation_pos saved = CodeGen::select(gen, global_variables_array_I7CGS); text_stream *OUT = CodeGen::current(gen); WRITE(" ("); CodeGen::pair(gen, P, val); WRITE(") ! -->%d = %S (%S)\n", k, InterSymbol::trans(var_name), InterSymbol::identifier(var_name)); CodeGen::deselect(gen, saved); k++;
- This code is used in §2.
segmentation_pos saved = CodeGen::select(gen, global_variables_array_I7CGS); text_stream *OUT = CodeGen::current(gen); WRITE(";\n"); CodeGen::deselect(gen, saved);
- This code is used in §2.
§2.4. Variables created by kits all become Globals in I62.4 =
segmentation_pos saved = CodeGen::select(gen, global_variables_I7CGS); text_stream *OUT = CodeGen::current(gen); WRITE("Global %S = ", InterSymbol::trans(var_name)); CodeGen::pair(gen, P, val); WRITE(";\n"); CodeGen::deselect(gen, saved);
- This code is used in §2.
§3. And the following is called when we want to compile an lvalue or rvalue for the variable (lvalue in the case of as_reference being set).
void I6TargetVariables::evaluate_variable(code_generator *gtr, code_generation *gen, inter_symbol *var_name, int as_reference) { text_stream *OUT = CodeGen::current(gen); int k = SymbolAnnotation::get_i(var_name, I6_GLOBAL_OFFSET_IANN); if (k > 0) WRITE("(Global_Vars-->%d)", k); else WRITE("%S", InterSymbol::trans(var_name)); }