8.
3 Assignment Statements
Computer Science 332
Compiler Construction
Chapter 8: Intermediate Code
Generation
8.3-8.4: Assignment Statements and
Boolean Expressions
In 8.1 we ignored the issue of symbol-table entry and lookup
(just assumed .place attribute worked properly)
Now we show how symbol tables are actually used.
Replace .code attribute and gen function with emit function,
which emits (generates) three-address code directly
From previous section, we assume expressions are evaluated
in context of declarations:
P
M
D
N
8.3 Assignment Statements
S
E1 + E2
{ p := lookup (id.name); // get address: t1, etc.
if p nil then emit (p ':=' E.place)
else error }
{ E.place := newtmp; // returns t1, t2, etc.
- E1
{ E.place := newtmp;
id := E
E
emit(E.place ':= ' E1.place '+' E2.place) }
E
emit(E.place ':= 'uminus' E1.place) }
( E1 )
E
E
id
{ E.place := E1.place; }
{ p := lookup (id.name);
if p nil then E.place := p
else error }
MD
D ; D | id : T | proc id ; D ; S
Reusing Temporary Names
newtmp generates a new temporary variable (t1, t2, t3, ...)
each time it is called
If we put temporaries in the symbol table, it eventually gets
cluttered with them (t1043, t1044, t1045, ...)
But we only need at most three of them, for three-address
code:
E
E1 + E2
evaluate E1 into t1
evaluate E2 into t2
t1 := t1 + t2
Reusing Temporary Names
Solution: keep a count of temporaries, which gets incremented
when a temp is created, and decremented when a temp is used
as an operand (acts like a stack)
E.g., x := a * b + c * d e * f
Statement
t0
t1
t0
t1
t0
x
:=
:=
:=
:=
:=
:=
a * b
c * d
t0 + t1
e * f
t0 - t1
t0
Count
0
1
2
1
2
1
0
8.4 Boolean Expressions
8.4 Boolean Expressions
Recall our grammar from PS7:
expr
comp-expr | cond-expr | bool-expr | ... | boolean
comp-expr
cond-expr
bool-expr
boolean
expr > expr | expr < expr
if expr then expr else expr
expr and expr | expr or expr
true | false
Need a way of translating booleans and control-flow (if-thenelse) into three-address code
Numerical Representation
Two basic approaches
Numerical Representation
true represented as 1
false represented as 0
and, or work like arithmetic expressions
Flow-of-control
Represent value of boolean by position in program
E.g., if first part of or evaluates to true, jump over evaluation of
second part
a or b and not c
t1 := not c
t2 := b and t1
t3 := a or t1
Numerical Representation
Numerical Representation
E
E1 or E2
{ E.place := newtmp;
E1 and E2
{ E.place := newtmp;
not E1
{ E.place := newtmp;
emit(E.place ':= ' E1.place 'or' E2.place) }
if a < b then 1 else 0
100:
101:
102:
103:
104:
if a < b goto 103
t := 0
goto 104
t :=1
...
emit(E.place ':= ' E1.place 'and' E2.place) }
emit(E.place ':= ' 'not' E1.place) }
( E1 )
E
E
E
true
{ E.place := newtmp; emit(E.place ':=
1' )}
false
{ E.place := newtmp; emit(E.place ':=
0' )}
Numerical Representation
E
id1 relop id2
{ E.place := newtmp;
{ E.place := E1.place; }
Flow-of-Control Statements
Consider grammar
S if E then S1 | if E then S1 else S2 | while E do S1
emit( 'if' id1.place relop.op id2.place
'goto' nexstat + 3);
emit(E.place ':= 0');
emit( 'goto' nexstat + 2);
emit(E.place ':= 1');}
where nexstat is address of next statement
Each boolean expression E gets two label attributes
true : where to go when expression evaluates to true
false : where to go when expression evaluates to false
Inherited attribute S.next is address of next instruction after S
Inherited attribute S.begin is address of first instruction of S
Flow-of-Control Statements
E.code
E.true:
E.false:
S1.code
S.begin:
E.code
E.true:
...
if-then
Flow-of-Control Statements
E.true:
S1.code
goto S.next
E.false:
S.next:
E.code
S1.code
goto S.begin
S2.code
E.false:
...
while-do
...
if-then-else
Flow-of-Control Statements
S
if E then S1
E.false := S.next;
S1 .next := S.next;
S.code := E.code || gen (E.true ':' ) S1 .code }
S
Flow-of-Control Statements
{ E.true := newlabel;
if E then S1 else S2 { E.true := newlabel;
E.false := newlabel;
S1 .next := S.next;
S2 .next := S.next;
S.code := E.code ||
gen (E.true ':' ) S1 .code ||
gen ('goto' S.next ) ||
gen (E.false ':' ) S2 .code }
S
while E do S1 { S.begin := newlabel;
E.true := newlabel;
E.false := S.next;
S1 .next := S.begin;
S.code := gen (S.begin ':' ) || E.code ||
gen (E.true ':' ) || S1 .code ||
gen ('goto' S.begin) }
Control-Flow Translation of Boolean
Expressions
Now we can see how to implement the flow-of-control version
of boolean expression translation.
E.g.,
a < b or c < d and e < f
if a
goto
L1: if c
goto
L2: if e
goto
Control-Flow Translation
E
E1 or E2
{ E1.true := E.true;
E1.false := newlabel
E2.true := E.true;
E2.false := E.false;
< b goto Ltrue // whole thing true
L1
< d goto L2
Lfalse
// whole thing false
< f goto Ltrue
Lfalse
E.code := E1.code || gen (E1.false ':' ) || E2.code }
E
E1 and E2
{ E1.true := newlabel;
E1.false := E.false
E2.true := E.true;
E2.false := E.false;
E.code := E1.code || gen (E1.true ':' ) || E2.code }
Control-Flow Translation
E
not E1
{ E1.true := E.false;
E1.false := E.true
E.code := E1.code; }
( E1 )
E
{E1.true := E.true;
E1.false := E.false
E.code := E1.code;}
E
E
true
{ E.code := gen ( 'goto' ) || E.true }
false
{ E.code := gen ( 'goto' ) || E.false}
Control-Flow Translation
E
id1 relop id2 { gen ( 'if' id1.place relop.op id2.place
'goto' E.true) ||
gen ( 'goto' E.false) }