Mlaskal compiler support classes
Assignment 6

Assignment 4 describes the basics of the symbol tables. Assignment 5 describes the principles of code generation for expressions.

Control flow

Assignment 6 deals with control-flow structures, i.e. conditional statements, loops, and go-to statements. All these structures are represented in the intermediate code using the same means: Conditionial jumps [JT,JF], unconditional jumps [JMP] and IC labels.

IC labels (not to be confused with Mlaskal labels) are "magic numbers" used to connect jump instructions to their target positions in intermediate code. Unique magic numbers are generated by the function mlc::symbol_tables::new_label and they are represented by the type mlc::ic_label.

Each magic number may be associated with one position in the intermediate code: the function add_label associates a previously generated magic number with the position after the last instruction in a code fragment.

Each magic number may be used in any number of jump instructions, using the function append_with_target.

The jumps may be generated before or after associating the magic number with a position; they may also be added into different code fragments - they will be physically linked together as soon as the fragments are merged together. It is an error if an IC block contains two positions associated with the same magic number (on the contrary, more than one magic number may be associated with the same position). It is also an error if a code block passed to mlc::symbol_tables::set_subprogram_code or mlc::symbol_tables::set_main_code contains a jump instruction whose magic number was not associated with a position.

Labels and goto statements

Mlaskal labels are explicitly declared using label declarations - within Assignment 4, the corresponding magic number were already generated and stored in the label entry in the symbol tables.

When a goto statement or a labeled statement is encountered, the label (i.e. an integer constant) shall be searched in the symbol tables using mlc::symbol_tables::find_label. (If not found, the mlc::DUERR_NOTLABEL message shall be reported.) If found, the returned pointer allows to invoke the label function which returns the stored magic number.

The magic number shall then be passed to add_label or append_instruction_with_target, respectively.

In addition, symbol table function mlc::label_symbol::goto_found or mlc::label_symbol::label_found shall be called when a goto statement or a labeled statement is encountered. Based on this calls, the symbol tables will generate corresponding messages for unused, undefined, or doubly defined labels.

Conditionals and loops

Control-flow structures shall be handled by insertion of appropriate jump instructions between the code fragments of conditions and statements. These jumps are linked to the appropriate places in the code using magic numbers generated beforehand, as shown in the following example covering a (complete) conditional statement:

{
mlc::ic_label l1 = ctx->tab->new_label();
mlc::ic_label l2 = ctx->tab->new_label();
mlc::icblock_pointer ib = condition;
ib->append_with_target< ai::JF>(l1);
ib = mlc::icblock_merge_and_kill(ib,statement1);
ib->append_with_target< ai::JMP>(l2);
ib->add_label(l1);
ib = mlc::icblock_merge_and_kill(ib,statement2);
ib->add_label(l2);
return ib;
}

The function assumes that condition is a code fragment which leaves a Boolean value on the stack; statement1 and statement2 are the "then" and "else" blocks.

When implementing for-loops, several arithmetic operations shall be generated by the compiler. The function mlc::symbol_tables::one may be useful for this purpose.