1.2k likes | 1.24k Views
Understand recursive and iterative interpretation, self-identifying data representation, and code generation in compilers, with sample instructions and optimal techniques explained.
E N D
Compilers 7. Code Generation Chih-Hung Wang References 1. C. N. Fischer, R. K. Cytron and R. J. LeBlanc. Crafting a Compiler. Pearson Education Inc., 2010. 2. D. Grune, H. Bal, C. Jacobs, and K. Langendoen. Modern Compiler Design. John Wiley & Sons, 2000. 3. Alfred V. Aho, Ravi Sethi, and Jeffrey D. Ullman. Compilers: Principles, Techniques, and Tools. Addison-Wesley, 1986. (2nd Ed. 2006)
Interpretation • An interpreter is a program that consider the nodes of the AST in the correct order and performs the actions prescribed for those nodes by the semantics of the language. • Two varieties • Recursive • Iterative
Interpretation • Recursive interpretation • operates directly on the AST [attribute grammar] • simple to write • thorough error checks • very slow: 1000x speed of compiled code • Iterative interpretation • operates on intermediate code • good error checking • slow: 100x speed of compiled code
Self-identifying data • must handle user-defined data types • value = pointer to type descriptor + array of subvalues • example: complex number 3.0 re: 4.0 im:
IF condition THEN ELSE FI Iterative interpretation • Operates on threaded AST • Active node pointer • Flat loop over a case statement
Code Generation • Compilation produces object code from the intermediate code tree through a process called code generation • Tree rewriting • Replace nodes and subtrees of the AST by target code segments • Produce a linear sequence of instructions from the rewritten AST
Example of code generation a:=(b[4*c+d]*2)+9;
Machine instructions • Load_Addr M[Ri], C, Rd • Loads the address of the Ri-th element of the array at M into Rd, where the size of the elements of M is C bytes • Load_Byte (M+Ro)[Ri], C, Rd • Loads the byte contents of the Ri-th element of the array at M plus offset Ro into Rd, where the other parameters have the same meanings as above
Code generation Main issues: • Code selection – which template? • Register allocation – too few! • Instruction ordering Optimal code generation is NP-complete • Consider small parts of the AST • Simplify target machine • Use conventions
Object code sequence Load_Byte (b+Rd)[Rc], 4, Rt Load_Addr 9[Rt], 2, Ra
frame Simple code generation • Consider one AST node at a time • Two simplistic target machines • Pure register machine • Pure stack machine stack SP vars BP
Pure stack machine • Instructions
Example of p:=p+5 Push_Local #p Push_Const 5 Add_Top2 Store_Local #p
Pure register machine • Instructions
Example of p:=p+5 Load_Mem p, R1 Load_Const 5, R2 Add_Reg R2, R1 Store_Reg R1, p
Simple code generation for a stack machine • The AST for b*b – 4 *(a*c)
Simple code generationfor a stack machine (demo) • example: b*b – 4*a*c • threaded AST - * * b b 4 * a c
Simple code generationfor a stack machine (demo) • example: b*b – 4*a*c • threaded AST Sub_Top2 - Mul_Top2 Mul_Top2 * * Push_Local #b b Push_Local #b b Push_Const 4 4 Mul_Top2 * Push_Local #a a Push_Local #c c
Sub_Top2 - Mul_Top2 Mul_Top2 * * Push_Local #b b Push_Local #b b Push_Const 4 4 Mul_Top2 * Push_Local #a a Push_Local #c c Simple code generationfor a stack machine (demo) Push_Local #b Push_Local #b Mul_Top2 Push_Const 4 Push_Local #a Push_Local #c Mul_Top2 Mul_Top2 Sub_Top2 • example: b*b – 4*a*c • rewritten AST
Simple code generation for a register machine • The ASTs for the register machine instructions
Weighted register allocation • It is advantageous to generate the code for the child that requires the most registers first • Weight: • The number of registers required by a node
Example Parameter number N 2 3 1 Stored weight 4 2 1 Registers occupied when 0 1 2 starting parameter N Maximum per parameter 4 3 3 Overall maximum 4
- * * T1 1 b b 4 * a c Register spilling Too few registers? • Spill registers in memory, to be retrieved later • Heuristic: select subtree that uses all registers, and replace it by a temporary example: • b*b – 4*a*c • 2 registers 3 2 2 2 2 1 1 1 1 1
- 3 2 T1 * * 2 2 1 b b 4 * 2 1 1 1 a c 1 1 Register spilling Load_Mem b, R1 Load_Mem b, R2 Mul_Reg R2, R1 Store_Mem R1, T1 Load_Mem a, R1 Load_Mem c, R2 Mul_Reg R2, R1 Load_Const 4, R2 Mul_Reg R1, R2 Load_Mem T1, R1 Sub_Reg R2, R1
- * * T1 1 b b 4 * a c Another example 3 2 2 2 2 1 1 1
Machines with register-memory operations • An instruction: • Add_Mem X, R1 • Adding the contents of memory location X to R1