1 / 37

Code Generation: Tree Walking and Rules Application

This lecture covers the process of generating target code by walking the AST from top to bottom and applying rules for each node, including basic operations like emitting instructions and handling binary operations. Specific examples and code snippets are provided for better understanding.

maize
Download Presentation

Code Generation: Tree Walking and Rules Application

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture 8 AST Visiting and Code Generation Xiaoyin Wang CS 5363 Programming Languages and Compilers

  2. Code Generation • Tree Walking • Code Generation Rules • Control Flow Graph

  3. Code Generation • After we constructed the AST and decorated it • We finally start working on generating target code • Here we output 3-address code • Still an intermediate representation • Assuming unlimited registers • No machine specifications • Format: op src1 src2 => dest

  4. Code Generation • It is surprisingly simple: • You just need to walk the tree from top to bottom • Apply rules for each AST Node • Then, we are done!

  5. Code Generation • Basic Operations • Emit: write an instruction or a label to the instruction stream • Register.Next(): get the next available register • Label.Next(): get the next available label • For expression AST Nodes, add a register field to save the register that stores its value

  6. Tree walking • Depth-first tree walking • Always visit children left to right

  7. Applying Rules: Binary Operation • Decide what should the code do (semantics) for each AST Node • For example: Consider Add (left, right) • What you want to do is:eval <left> eval <right> add left, right => result

  8. Applying Rules: Binary Operation • So in your code: public void visit (Add add){ add.left.accept(this); Register r1 = add.left.reg; add.right.accept(this); Register r2 = add.right.reg; Register r3 = Register.next(); emit(new instruction(‘add’, r3, r1, r2)); add.reg = r3; }

  9. Applying Rules: Binary Operation • Another example: • expr1 > expr2 eval <expr1> eval <expr2> set1g expr1, expr2 => result

  10. Applying Rules: Binary Operation • Code Example public void visit (Compare comp){ comp.left.accept(this); Register r1 = comp.left.reg; comp.right.accept(this); Register r2 = comp.right.reg; Register r3 = Register.next(); swtich(comp.op){ case ‘>’: emit(new instruction(‘set1g’, r3, r1, r2));break; case ‘>=’: … … } comp.reg = r3; }

  11. Applying Rules: Num Literal • For an immediate number • We just need to assign it to a register, which can be used later • Code: public void visit(NumLiteral num){ Register r1 = Register.next(); num.reg = r1; emit( new Instruction (‘mov’, r1, num.value) ); }

  12. Applying Rules: Identifier • What we should do: • Just find out which register the value is saved in • If no register is found: error, the variable is not initialized public void visit(Identifier ident){ Register r1 = symbolTable.get(ident.name).reg; if (r1 != null) { ident.reg = r1;} else {throw exception … } }

  13. Applying Rules: Assignment • Ident := expr • What we should do • First eval expr • Then find the register of the ident / Or create a new register for the ident • Insert the mov instruction

  14. Applying Rules: Assignment • Ident := expr • What we should do • First eval expr • Then find the register of the ident / Or create a new register for the ident • Insert the mov instruction expr.accept(this); Register r1 = expr.reg; r2 = symbolTable.get(ident.name).reg; if(r2 == null){ r2 = Register.next(); symbolTable.get(ident.name).reg = r2; } emit(new Instruction('mov', r2, r1));

  15. Applying Rules: If statement • Another example: if expr then stmt1 else stmt2; IfElseStmt thenStmt elseStmt cond

  16. Applying Rules: If statement • What we want is: 1. evaluate cond expression 2. if return true: goto then stmt 3. else: goto else stmt 4. goto the end of the stmt on each of the branches

  17. Applying Rules: If statement Eval Cond • Control Flow: Code pattern: <eval condition> JZ reg ELSE <then statements> JMP END ELSE: <else statements> END: True? JZ thenStmt elseStmt JMP end

  18. Applying Rules: If statement • So in your code: public Register visit (IfElseStmtifelse){ ifelse.cond.accept(this); Register r1 = ifelse.cond.reg; Label elseLabel = Label.next(); Label endLabel = Label.next(); emit (new Instruction(‘JZ’, r1, elseLabel)) ifelse.thenStmt.accept(this); emit (new Instruction(‘JMP’, endLabel)) emit (elseLabel); ifelse.elseStmt.accept(this); emit (endLabel) }

  19. Applying Rules: while statement while cond do stmt end WhileStmt stmt cond

  20. Applying Rules: while statement • What we want is: 1. Set a label Start before evaluate cond expression 2. evaluate cond expression 3. if false: goto label End 4. else: go on to execute stmt 5. goto label Start

  21. Applying Rules: while statement • Control Flow: Code pattern: Eval Cond Start: <eval condition> JZ reg END <stmt> JMP Start END: True? JMP JZ stmt end

  22. Applying Rules: while statement • So in your code: public Register visit (WhileStmt while){ Label startLabel = Label.next(); emit(startLabel) while.cond.accept(this); Register r1 = while.cond.reg; Label endLabel = Label.next(); emit (new Instruction(‘JZ’, r1, endLabel)) while.stmt.accept(this); emit (new Instruction(‘JMP’, startLabel)) emit (endLabel) }

  23. Instruction Set The Appendix A of MIPS Assembly Specification On the course website A more brief summary at http://xywang.100871.net/SPIM_instr.pdf

  24. Instruction Set Registers and Memory address Memory instructions Arithmetic instructions Comparison instructions Branch instructions System call related instructions

  25. Registers and Memory address (A-24) $zero: 0 $t0 – $t9: local variables $s0 – $s7: global variables $a0 – $a3: function arguments $v0, v1: function return values $fp: frame pointer (first byte) $sp: stack pointer (last byte)

  26. Memory Instructions (A65) li: Load immediate value Example: li $t0, 2 la: Load address Example: la $t0, str lw: Load value from memory Example: lw $t0, -4($fp) sw: save value to memory Example: sw $t0, -4($fp)

  27. Arithmetic instructions (A51-A57) add / addu / addi Example: addu $t0, $t1, $t2 sub / subu mul / mulo / mulou div / divu rem / remu

  28. Comparison instructions (A57-A59) slt : set 1 if less than Example: slt $t0, $t1, $t2 slti: set 1 if less than immediate Example: slt $t0, $t1, 3 seq: set 1 if equal sgt: set 1 if greater sge, sle, sne

  29. Branch instructions (A59-A63) j/b: jump to label Example: j bbb beqz / bnez: jump to label if equal or not equal to zero Example: beqz $t0 bbb beq, bne, bgt, …

  30. System calls: for read/write int System call code: in $v0 1: print int, parameter in $a0 5: read int, result in $v0 Example: li $v0, 4 la $a0, newline syscall li $v0, 5 syscall add $t0, $v0, $zero

  31. Control Flow Graph • An intermediate presentation of target code • Enables flow-oriented code optimization • Better understanding of the code

  32. Basic Blocks • A block of the code that will be sequentially executed • With no jump instructions and labels for other instructions to jump to • Nodes in the control flow graph

  33. Generate Control Flow Graph with Basic Blocks • In the generated code • Step 1: split the code to a number of basic blocks • Step 2: find the relationship between all basic blocks, for each basic block: • Its predecessors are the basic block directly before it (if no unconditional jump at the end), and all blocks can jump to it • Its successors are the basic block directly after it (if no unconditional jump at the end), and all blocks it jumps to

  34. mov 0 => r_SQRT readint => r_N mov 0 => r_SQRT readint => r_N L1: cmp_LE r1, r_N => r2 jumpeqz r2 -> L2 add r_SQRT, 1 => r4 mov r4 => r_SQRT jump -> L1 L2: sub r_SQRT, r5 => r6 writeInt r_SQRT exit L1: cmp_LE r1, r_N => r2 jumpeqz r2 -> L2 break add r_SQRT, 1 => r4 mov r4 => r_SQRT jump -> L1 L2: sub r_SQRT, r5 => r6 writeInt r_SQRT exit

  35. Block 1: mov 0 => r_SQRT readint => r_N Block 2: L1: cmp_LE r1, r_N => r2 jumpeqz r2 -> L2 Block 3: add r_SQRT, 1 => r4 mov r4 => r_SQRT jump -> L1 Block 4: L2: sub r_SQRT, r5 => r6 writeInt r_SQRT exit

  36. Basic Transformation From 3 address code to MIPS code 3 address code: Assumes unlimited number of registers MIPS code: Only limited number of registers, but memory can be normally viewed as unlimited

  37. Basic Transformation From 3 address code to MIPS code Therefore Any: Op r_x, r_y => r_z Can transform to: lw $t1, -4*x($fp) lw $t2, -4*y($fp) Op $t0, $t1, $t2 sw $t0, -4*z($fp)

More Related