You are on page 1of 5

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) }

You might also like