06.intermediate Code Generation
06.intermediate Code Generation
Parser
Static
Checker
Intermediate
Code
Generator
Intermediate
Code
Code
Generator
Intermediate Languages
Syntax trees, Postfix notation,
Three-address code (x := y op z)
Example:
a := b * -c + b * -c
assign
Syntax
tree:
assign
*
b
uniminus
DAG:
uniminus
uniminus
Three-Address Code
Sequence of statements:
x := y op z
x+y*z
=>
Example:
t1 := y * z
t2 := x + t1
a := b * -c + b * -c
t1 := - c
t2 := b *t1
t3 := - c
t4 := b * t3
t5 := t2 + t4
a := t5
Linearized representation
of a syntax tree
t1
t2
t5
a
:=
:=
:=
:=
- c
b *t1
t2 + t2
t5
Linearized representation
of a syntax DAG
Assignment statements:
Indexed assignments:
Pointer assignments:
Copy statements:
Unconditional jumps:
Conditional jumps:
Function calls:
p(x1,..., xn) =>
x := y op z and x := op y
x := y[ i ] and x[ i ] := y
x := & y, x := * y, * x := y
x := y
goto L
if x relop y goto L
param x, call p, n, and return y
param x1
. . .
param xn
call p, n
E E1 + E2
e.g.
=> t := E1 + E2,
t5 := t2 + t4
a := t5
Syntax-directed Translation
To produce three-address code for assignments
Production
S id := E
Semantic Rule
S.code := E.code || gen( id.place := E.place )
E E 1 + E2 E.place := newtemp();
E.code := E1.code || E2.code || gen( E.place := E1.place + E2.place )
E E1 * E2
E.place := newtemp();
E.code := E1.code || E2.code || gen( E.place := E1.place * E2 .place )
E - E1
E.place := newtemp();
E.code := E1.code || gen( E.place := uminus E1.place )
E ( E1 )
E.place := E1.place
E.code := E.code
E id
E.place := id.place
E .code :=
Flow-of-control Statements
While statements
Production
S while E do S1
S.begin :
Semantic Rule
S.begin := newlabel()
S.after := newlabel()
S.code := gen( S.begin : ) ||
E.code ||
gen ( if E.place = 0 goto S.after ) ||
S1.code ||
gen ( goto S.begin) ||
gen( S.after : )
E.code
...
if E.place = 0 goto S.after
S1.code
...
goto S.begin
S.after :
...
Flow-of-control Statements
Example
Source program
fragment
Three-address
code sequence
i := 2 * n + k
while i do
i := i - k
t1 := 2
t2 := t1 * n
t3 := t2 + k
i := t3
L1: if i = 0 goto L2
t4 := i - k
i := t4
goto L1
L2:
Implementation (1)
Quadruples, triples, and idirect triples
:=
:=
:=
:=
:=
:=
- c
b *t1
- c
b * t3
t2 + t4
t5
Three-address code
op
arg 1
arg 2
result
(0)
uniminus
(1)
(2)
uniminus
(3)
t3
t4
(4)
t2
t4
t5
(5)
:=
t5
t1
t1
t2
t3
Quads (quadruples)
Pro: easy to rearrange code for global optimization
Cons: lots of temporaries
Implementation (2)
Quadruples, triples, and idirect triples
:=
:=
:=
:=
:=
:=
- c
b *t1
- c
b * t3
t2 + t4
t5
Three-address code
op
arg 1
arg 2
(0)
uniminus
(1)
(2)
uniminus
(3)
(2)
(4)
(1)
(3)
(5)
:=
(4)
(0)
Triples
Pro: temporaries are implicit
Cons: difficult to rearrange code
Implementation (3)
Quadruples, triples, and idirect triples
:=
:=
:=
:=
:=
:=
- c
b *t1
- c
b * t3
t2 + t4
t5
Three-address code
statement
op
arg 1
arg 2
(0)
(14)
(14) uniminus
(1)
(15)
(15)
(2)
(16)
(16) uniminus
(3)
(17)
(17)
(16)
(4)
(18)
(18)
(15)
(17)
(5)
(19)
(19)
:=
(18)
Implicit Triples
c
b
c
Triple Container
(14)
Declarations in a Procedure
PMD
M
{ offset := 0 }
DD;D
D id : T
T integer
{ T.type := integer;
T.width := 4 }
T real
{ T.type := real;
T.width := 8 }
T array [ num ] of T1
T ^ T1
in table
addwidth( table, width ): accumulates the total width
Processing Declarations
Nested Procedures
PMD
{ t := mktable( nil );
push( t, tblptr ); push( 0, offset ) }
D D1 ; D2
D proc id ; N D1 ; S
{ t := top( tblptr );
addwidth( t, top( offset ) );
pop( tblptr ); pop( offset );
enterproc( top( tblptr ), id.name, t ) }
D id : T
Assignment Statements
A Translation Scheme
S id := E
{ p := lookup( id.name );
if p <> nil then
emit( p := E.place )
else error }
E E1 + E2
{ E.place := newtemp;
emit( E.place := E1.place + E2.place ) }
E E1 * E2
{ E.place := newtemp;
emit( E.place := E1.place * E2.place ) }
E - E1
{ E.place := newtemp;
emit( E.place := uniminus E1.place )}
E ( E1 )
{ E.place := E1.place }
E id
{ p := lookup( id.name );
if p <> nil then
E.place := p
else error }
Value of c
0
$0 := a * b
$1 := c * d
$0 := $0 + $1
$1 := e * f
$0 := $0 - $1
:= $0
base + (i low) x W
base = A[low], W = sizeof( type )
t1
t2
t3
:=
:=
:=
:=
c
i * W
t1[t2]
t3
i x W + ( base low x W )
c = base low x W is stored in symbol-table entry for A
A[i] = i x W + c
A[1,1]
A[1,1]
A[1,2]
A[2,1]
A[1,3]
A[1,2]
A[2,1]
A[2,2]
A[2,2]
A[1,3]
A[2,3]
A[2,3]
Row-major
Column-major
First
Column
:=
:=
:=
:=
:=
:=
i * 3
t1 + j
c
t1 * 4
t2[t3]
t4
Synthesized Attributes:
E.place
Elist.array
Elist.place
Elist.ndim
L.place
L.offset
null
E E1 + E2
{ E.place := newtemp;
emit( E.place := E1.place + E2.place ) }
E ( E1 )
{ E.place := E1.place }
EL
L id
{ L.place := id.place;
L.offset := null }
Elist Elist 1, E
Elist id [ E
{ Elist.array := id.place;
Elist.place := E.place;
Elist.ndim := 1 }
t1 := not c
t2 := b and t1
t3 := a or t2
if a
t :=
goto
t :=
{ E.place := newtemp;
emit( E.place := E1.place or E2.place ) }
E E1 and E2
{ E.place := newtemp;
emit( E.place := E1.place and E2.place ) }
E not E1
{ E.place := newtemp;
emit( E.place := not E1.place ) }
E ( E1 )
{ E.place := E1.place }
{ E.place := newtemp;
emit( if id1.place relop.op id2.place goto nextstat + 3 );
emit( E.place := 0 );
emit( goto nextstat + 2 );
emit( E.place := 1 ) }
E true
{ E.place := newtemp;
emit( E.place := 1 ) }
E false
{ E.place := newtemp;
emit( E.place := 0 ) }
Backpatching
Code generation problem:
Labels (addresses) that control must go to may not be
known at the time the jump statements are generated
A solution - backpatching:
Generate branching statements with empty jumps
Put the statements in a goto list
Fill the labels of these statements when the proper label
is determined
Backpatching
Quadruples in a quadruple array
Labels are indexes into the array
Backpatching
Grammar for boolean expressions
E E1 or M E2
| E1 and M E2
| not E1
| ( E1 )
| id1 relop id2
| true
| false
M
Synthesized Attributes:
E.code
E.truelist
E.falselist
M.quad
three-address code
backpatch list for jumps on true
backpatch list for jumps on false
location of current three-address
quad
Backpatching
A Translation Scheme... (1)
E E1 or M E2
E E1 and M E2
E not E1
{ E.truelist := E1.falselist;
E.falselist := E1.truelist }
E ( E1 )
{ E.truelist := E1.truelist;
E.falselist := E1.falselist }
Backpatching
A Translation Scheme... (2)
E id1 relop id2
E true
E false
{ M.quad := nextquad }
Backpatching
Example: a<b or c<d and e<f
E id1 relop id2
E E1 or M E2
(M.quad := 102)
E E1 and M E2
(M.quad := 104)
100:
101:
102:
103:
104:
105:
if a < b goto_
goto_
if c < d goto_
goto_
if e < f goto_
goto_
backpatch( {102}, 104 )
if a
goto
if c
goto
if e
goto
Flow-of-control Statements
Grammar
Synthesized Attributes:
S if E then S
| if E then S else S
| while E do S
| begin L end
| A
LL;S
| S
E.code
E.truelist
E.falselist
M.quad
S.nextlist
L.nextlist
three-address code
backpatch list for jumps on true
backpatch list for jumps on false
location of current three-address
quad
backpatch list for jumps to the
next statement after S (or nil)
backpatch list for jumps to the
next statement after L (or nil)
Flow-of-Control Statements
A Translation Scheme using backpatching... (1)
S if E then M1 S1 N
else M2 S2
{ M.quad := nextquad }
S if E then M S1
S wihle M1 E do
M2 S1
Flow-of-Control Statements
A Translation Scheme using backpatching... (2)
S begin L end
{ S.nextlist := L.nextlist }
SA
{ S.nextlist := nil }
L L1 ; M S
LS
{ L.nextlist := S.nextlist }