Implementation of Instruction, Code Generation In Compiler
This article will emphasize each and every step mention in the working in order to show how the code is generated in regular terms;
Supporting Functions:
Before generating some code, we need to set up a few supporting functions to keep track of a few details. To hold intermediate values between operators, we would require some scratch registers to generate expressions. An example is mentioned below in the form of three functions with the following interface.
Generating Expressions:
The basic approach to generating assembly code for an expression is to perform a post-order traversal of the AST or DAG and emit one or more instructions for each node. Consider the following scratch functions;
- The nodes will be visited in post-order traversal in the below-mentioned order;
- The node is visited and to allocate a new register (0) and save that on a node in that register scratch allocation is called and the instruction MOVQ a, R0 to load the value into register zero is emitted.
- Visit the 3 nodes. Call scratch allocation to allocate a new register (1) and emit the instruction MOVQ $3, R1.
- Visit the IADD node. We can see that node values are stored in registers R0 and R1 by examining their child nodes, so we emit an instruction that adds them together: ADDQ R0, R1. The two address instruction which leaves the result in R1. R0 is no longer needed so a scratch-free function is called.
- Visit the b node. Call scratch allocation to allocate a new register (0) and emit MOVQ b, R0.
- Visit the ISUB node. Emit SUBQ R0, R1, leaving the result in R1, and freeing register R0.
- Visit the c node, but don’t emit anything, because it is the target of the assignment.
- Visit the ASSIGN node and emit MOVQ R1, c.
Generating Statements:
Now that we have encapsulated expression generation into a single function, we can begin to build up larger code structures that rely upon expressions. The statement will create code for all control flow statements.
Constants:
When an intermediate-language instruction uses a constant; the code generator must check if it fits into the constant field (if any) of the equivalent machine-code instruction and if it does fit; then a single machine-code instruction is generated by code generator and if the instruction does not fit; then a sequence of instructions that builds the constant in a register, followed by an instruction that uses this register in place of the constant are generated by the code generator as in the table below;
Control flow statements:
Are more interesting. It is better and more beneficial to first consider how the output assembly language should look like and then work backward to get the code for generating it. The table below will show the generated code template for the if statement.
Iterative Statements:
A similar approach can be used to generate loops. Here is the source template of a for-loop as mentioned in the table;