The Main Idea of Today’s Lecture Code Generation We can emit stack-machine-style code for expressions via recursion (We will use MIPS assembly as our target language) 2 Compiler Design I (2011) Lecture Outline Stack Machines • What are stack-machines? • A simple evaluation model • The MIPS assembly language • No variables or registers • A simple source language ( “Mini Bar” ) • A stack of values for intermediate results • A stack-machine implementation of the simple • Each instruction: language – Takes its operands from the top of the stack – Removes those operands from the stack – Computes the required operation on them – Pushes the result onto the stack 3 4 Compiler Design I (2011) Compiler Design I (2011)
Example of Stack Machine Operation Example of a Stack Machine Program The addition operation on a stack machine • Consider two instructions - place the integer i on top of the stack – push i - pop topmost two elements, add them – add and put the result back onto the stack 5 ⊕ 7 5 • A program to compute 7 + 5: 12 7 push 7 9 9 9 push 5 … … … add pop add push 5 6 Compiler Design I (2011) Compiler Design I (2011) Why Use a Stack Machine? Why Use a Stack Machine? • Each operation takes operands from the same • Location of the operands is implicit place and puts results in the same place – Always on the top of the stack • No need to specify operands explicitly • This means a uniform compilation scheme • No need to specify the location of the result • Instruction is “ add ” as opposed to “ add r 1 ” , r 2 • And therefore a simpler compiler ⇒ Smaller encoding of instructions ⇒ More compact programs • This is one of the reasons why Java Bytecode uses a stack evaluation model 7 8 Compiler Design I (2011) Compiler Design I (2011)
Optimizing the Stack Machine Stack Machine with Accumulator • The add instruction does 3 memory operations Invariants – Two reads and one write to the stack • The result of computing an expression is – The top of the stack is frequently accessed always placed in the accumulator • Idea: keep the top of the stack in a dedicated • For an operation op(e 1 ,…,e n ) compute each e i register (called the “accumulator”) and then push the accumulator (= the result of evaluating e i ) onto the stack – Register accesses are faster (why?) • The “ add ” instruction is now • After the operation pop n-1 values acc ← acc + top_of_stack • After computing an expression the stack is as – Only one memory operation! before 9 10 Compiler Design I (2011) Compiler Design I (2011) Stack Machine with Accumulator: Example A Bigger Example: 3 + (7 + 5) Compute 7 + 5 using an accumulator Code Acc Stack acc ← 3 3 <init> acc 3 3, <init> push acc ← 7 7 3, <init> 7 5 12 acc ⊕ acc 7 7, 3, <init> push acc ← 5 5 7, 3, <init> 7 7 acc ← acc + top_of_stack 12 7, 3, <init> stack … … … … 12 3, <init> pop acc ← acc + top_of_stack 15 3, <init> acc ← acc + top_of_stack acc ← 7 acc ← 5 pop 15 <init> push acc pop 11 12 Compiler Design I (2011) Compiler Design I (2011)
Notes From Stack Machines to MIPS • It is very important that the stack is • The compiler generates code for a stack preserved across the evaluation of a machine with accumulator subexpression • We want to run the resulting code on the – Stack before the evaluation of 7 + 5 is 3, <init> MIPS processor (or simulator) – Stack after the evaluation of 7 + 5 is 3, <init> – The first operand is on top of the stack • We simulate the stack machine instructions using MIPS instructions and registers 13 14 Compiler Design I (2011) Compiler Design I (2011) Simulating a Stack Machine on the MIPS… MIPS Assembly • The accumulator is kept in MIPS register $a0 MIPS architecture • The stack is kept in memory – Prototypical Reduced Instruction Set Computer (RISC) architecture • The stack grows towards lower addresses – Arithmetic operations use registers for operands – Standard convention on the MIPS architecture and results • The address of the next location on the stack – Must use load and store instructions to use is kept in MIPS register $sp operands and store results in memory – Guess: what does “sp” stand for? – 32 general purpose registers (32 bits each) – The top of the stack is at address $sp + 4 • We will use $sp, $a0 and $t1 (a temporary register) Read the SPIM documentation for more details 15 16 Compiler Design I (2011) Compiler Design I (2011)
A Sample of MIPS Instructions MIPS Assembly: Example • The stack-machine code for 7 + 5 in MIPS: “load word” – lw reg 1 offset(reg 2 ) • Load 32-bit word from address reg 2 into reg 1 + offset – add reg 1 reg 2 reg 3 acc ← 7 li $a0 7 • reg 1 reg 2 + reg 3 ← acc push sw $a0 0($sp) “store word” – sw reg 1 offset(reg 2 ) addiu $sp $sp -4 • Store 32-bit word in reg 1 at address reg 2 + offset acc ← 5 li $a0 5 “add immediate” – addiu reg 1 reg 2 imm acc ← acc + top_of_stack lw $t1 4($sp) ← • reg 1 reg 2 + imm add $a0 $a0 $t1 • “u” means overflow is not checked “load immediate” pop addiu $sp $sp 4 – li reg imm ← • reg imm • We now generalize this to a simple language… 17 18 Compiler Design I (2011) Compiler Design I (2011) A Small Language A Small Language (Cont.) • A language with only integers and integer • The first function definition f is the “main” operations (“ Mini Bar ”) routine • Running the program on input i means computing f(i) P → F P | F • Program for computing the Fibonacci numbers: F → id(ARGS) begin E end fib(x) ARGS → id, ARGS | id begin E → int | id | if E 1 = E 2 then E 3 else E 4 if x = 1 then 0 else | E 1 + E 2 | E 1 – E 2 | id(E 1 ,…,E n ) if x = 2 then 1 else fib(x - 1) + fib(x – 2) end 19 20 Compiler Design I (2011) Compiler Design I (2011)
Code Generation Strategy Code Generation for Constants • For each expression e we generate MIPS code • The code to evaluate an integer constant that: simply copies it into the accumulator: – Computes the value of e in $a0 – Preserves $sp and the contents of the stack cgen(int) = li int $a0 • We define a code generation function cgen(e) • Note that this also preserves the stack, as whose result is the code generated for e required – cgen(e) will be recursive 21 22 Compiler Design I (2011) Compiler Design I (2011) Code Generation for Add Code Generation for Add: Wrong Attempt! cgen(e 1 + e 2 ) = Optimization: Put the result of e 1 directly in $t1 ? cgen(e 1 ) ; $a0 ← value of e 1 cgen(e 1 + e 2 ) = ; push that value sw $a0 0($sp) cgen(e 1 ) ; $a0 ← value of e 1 ; onto the stack addiu $sp $sp –4 ; save that value in $t1 move $t1 $a0 cgen(e 2 ) ; $a0 ← value of e 2 cgen(e 2 ) ; $a0 ← value of e 2 ; grab value of e 1 lw $t1 4($sp) ; may clobber $t1 ; do the addition add $a0 $t1 $a0 ; perform the addition add $a0 $t1 $a0 ; pop the stack addiu $sp $sp 4 Try to generate code for : 3 + (7 + 5) • Possible optimization: Put the result of e 1 directly in register $t1 ? 23 24 Compiler Design I (2011) Compiler Design I (2011)
Code Generation Notes Code Generation for Sub and Constants • The code for e 1 + e 2 is a template with “holes” New instruction: sub reg 1 for code for evaluating e 1 and e 2 reg 2 reg 3 Implements • Stack machine code generation is recursive ← reg 1 reg 2 - reg 3 cgen(e 1 - e 2 ) = • Code for e 1 + e 2 consists of code for e 1 and e 2 cgen(e 1 ) ; $a0 ← value of e 1 glued together ; push that value sw $a0 0($sp) • Code generation can be written as a recursive- ; onto the stack addiu $sp $sp –4 descent of the AST cgen(e 2 ) ; $a0 ← value of e 2 – At least for (arithmetic) expressions ; grab value of e 1 lw $t1 4($sp) ; do the subtraction sub $a0 $t1 $a0 ; pop the stack addiu $sp $sp 4 25 26 Compiler Design I (2011) Compiler Design I (2011) Code Generation for Conditional Code Generation for If (Cont.) • We need flow control instructions cgen(if e 1 = e 2 then e 3 else e 4 ) = cgen(e 1 ) sw $a0 0($sp) • New MIPS instruction: beq reg 1 reg 2 label false_branch: addiu $sp $sp -4 – Branch to label if reg 1 cgen(e 4 ) = reg 2 cgen(e 2 ) b end_if lw $t1 4($sp) true_branch: • New MIPS instruction: b label addiu $sp $sp 4 cgen(e 3 ) – Unconditional jump to label beq $a0 $t1 true_branch end_if: 27 28 Compiler Design I (2011) Compiler Design I (2011)
Recommend
More recommend