# Code Generation 2 ## Stack Machine Consider two instructions * `push i` * `add i` It is not efficient because all stack is considered as memory (which is slower than register). ### Utilizing Register Files Keep the top of the stack in a register, so `add` requires only a single memory access. * `acc <- i` * `push acc` * `pop` * `add` ### Code Generation From Stack Machine Assume that stack grows towards lower addresses. ## MIPS 32 regs `$sp`, `$a0`, `$t1` * `lw` * `add` * `sw` * `addi` * `li` * `mv` Converting Stack to MIPS ISA * `acc <- i` * `li $a0 i` ### Optimizing no ## Branch `beq $1 $2 lbl` `b lbl` ## Function At Caller Side: 1. saves the `$fp` to the stack 2. saves the actual params in reverse order 3. saves the return address to `$ra` At Callee Side: 1. set `$fp` to `$sp` 2. the callee saves the return address 3. ... ## Temp Var Many various intermediate vars should be stored in the AR. But compiler can statically know how many temporary variables there are. Let $NT(e)$ is defined recursively by: $$NT(e1 + e2) = \max (NT(e1), NT(e2) + 1)$$ for example: ### CG using NT add new args to the `cgen(e, nt)` reduce number of decrease `$sp` (`addi $sp $sp -4`) ## Intermediate Representation (IR) Before: Each Languages need respective, different Optimizer. Now: Common IR optimizer. IR is language-independent and machine-independent optimization. ### High-Level Assembly It uses unlimited number of registers. It uses assembly-like control structures (jmp and lbl). opcodes but some are higher level igen(e, t)