Content
- Overview
- AST to Code
- Postfix to Code
- Three-Address Code
1. SDT to TAC 2. Conditional Statements 3. Arrays 4. Procedure Calls 5. Reusing Temp Variables
Overview
- Machine & language independent
- Optional
- Clean separation of front- & back-ends -> machine-independent code optimizations
- e.g. AST, post-fix notation, three-address code, two-address code
AST to Code
- Optimzation: combine common subtrees
Postfix to Code
Original: a := b * -c + b * -c
IR: a b c uminus * b c uminus * +
Code:
iload b
iload c
ineg
imul
...
iadd
istore a
- Easy to generate
- Difficult to optimize
Three-Address Code
- Assignment
- `x := y op z` - `x := op y`
- Indexed assignments
- `x := y[i]` - `x[i] := y`
- Pointer assignments
- `x := &y` - `x := *y` - `*x := y`
- Copy statements
- `x := y`
- Unconditional jumps
- `goto label`
- Conditional jumps
- `if x relop y goto label`
- Function calls
- `param x... call p, n` `return y`
SDT to TAC
- Synthesized attributes
- `S.code`: TAC for S - `S.begin`: label to start of S || nil - `S.after`: label to end of S || nil - `E.place`: name holding value of E - `E.code`: TAC for S
- Functions
- `gen(...)`: code generation
Conditional Statements
- Synthesized attributes
- `E.truelist`: backpatch list for jumps on true - `E.falselist`: backpatch list for jumps on false - `M.quad`: location of current TAC - `S.nextlist`: backpatch list for jumps to next statement after `S` || nil
- Functions
- `makelist(i)`: create new list containing TAC location `i` - `merge(p1,p2)`: concatenate 2 lists - `backpatch(i,p)`: insert label `i` for each statement in `p`
Arrays
- Synthesized attributes
- `E.place`: temp holding value of E - `Elist.array`: array name - `Elist.place`: temp holding index value - `Elist.ndim`: number of array dimensions - `L.place`: lvalue (temp) - `L.offset`: index into array (temp) || null
Procedure Calls
Reusing Temp Variables
- Modify
newtemp()
to keep a stack - Keep a counter
c
, init to0
- Decrement on use of
$i
in a 3-address statement newtemp()
returns$c++