16 I R Generation
16 I R Generation
16 I R Generation
Intermediate Representation
Compiler
Lexical Syntax Semantic
Analysis Analysis Analysis
Abstract
Source Token Target
Syntax
Program stream tree Intermediate Program
Code
Front End Back End
(Language specific)
1
Intermediate Code Generation
• Code generation is a mapping from source level
abstractions to target machine abstractions
2
Intermediate Code Generation ...
• Front end translates a source program into an intermediate
representation
• Benefits
– Retargeting is possible
– Machine independent code optimization is possible
Intermediate Machine
Front Code Code
end generator generator
3
Syntax directed translation of
expression into 3-address code
• Two attributes
• E.place, a name that will hold the
value of E, and
• E.code, the sequence of three-address
statements evaluating E.
• A function gen(…) to produce
sequence of three address statements
– The statements themselves are kept in some
data structure, e.g. list
– SDD operations described using pseudo code
4
Syntax directed translation of
expression into 3-address code
S → id := E
S.code := E.code ||
gen(id.place:= E.place)
E → E1 + E2
E.place:= newtmp
E.code:= E1.code || E2.code ||
gen(E.place := E1.place + E2.place)
E → E1 * E2
E.place:= newtmp
E.code := E1.code || E2.code ||
gen(E.place := E1.place * E2.place)
5
Syntax directed translation of
expression …
E → -E1
E.place := newtmp
E.code := E1.code ||
gen(E.place := - E1.place)
E → (E1)
E.place := E1.place
E.code := E1.code
E → id
E.place := id.place
E.code := ‘ ‘
6
Example
For a = b * -c + b * -c
following code is generated
t1 = -c
t2 = b * t1
t3 = -c
t4 = b * t3
t5 = t2 + t4
a = t5
7
Flow of Control
S → while E do S1 S.begin := newlabel
8
Flow of Control …
S → if E then S1 else S2 S.else := newlabel
S.after := newlabel
E.code
if E.place = 0 goto S.else S.code = E.code ||
S1.code gen(if E.place = 0 goto S.else) ||
S1.code ||
goto S.after
gen(goto S.after) ||
S.else: gen(S.else :) ||
S2.code S2.code ||
S.after: gen(S.after :)
9
Declarations
P→ D
D→D;D
D → id : T
T → integer
T → real
10
Declarations
For each name create symbol table entry with information
like type and relative address
P → {offset=0} D
D→D;D
D → id : T
enter(id.name, T.type, offset);
offset = offset + T.width
T → integer
T.type = integer; T.width = 4
T → real
T.type = real; T.width = 8
11
Declarations
For each name create symbol table entry with information
like type and relative address
P → {offset=0} D
D→D;D
D → id : T
enter(id.name, T.type, offset);
offset = offset + T.width
T → integer
T.type = integer; T.width = 4
T → real
T.type = real; T.width = 8
12
Declarations …
T → array [ num ] of T1
T.type = array(num.val, T1.type)
T.width = num.val x T1.width
T → ↑T1
T.type = pointer(T1.type)
T.width = 4
13
Keeping track of local information
• when a nested procedure is seen, processing of
declaration in enclosing procedure is temporarily
suspended
partition
header
i
j 16
Creating symbol table: Interface
• mktable (previous)
create a new symbol table and return a pointer to the
new table. The argument previous points to the
enclosing procedure
• enter (table, name, type, offset)
creates a new entry
• addwidth (table, width)
records cumulative width of all the entries in a table
• enterproc (table, name, newtable)
creates a new entry for procedure name. newtable
points to the symbol table of the new procedure
• Maintain two stacks: (1) symbol tables and (2) offsets
• Standard stack operations: push, pop, top
17
Creating symbol table …
D→ proc id;
{t = mktable(top(tblptr));
push(t, tblptr); push(0, offset)}
D1; S
{t = top(tblptr);
addwidth(t, top(offset));
pop(tblptr); pop(offset);
enterproc(top(tblptr), id.name, t)}
D→ id: T
{enter(top(tblptr), id.name, T.type, top(offset));
top(offset) = top (offset) + T.width}
18
Creating symbol table …
P→
{t=mktable(nil);
push(t,tblptr);
push(0,offset)}
D
{addwidth(top(tblptr),top(offset));
pop(tblptr); // save it somewhere!
pop(offset)}
D→ D;D
19
Field names in records
T → record
{t = mktable(nil);
push(t, tblptr); push(0, offset)}
D end
{T.type = record(top(tblptr));
T.width = top(offset);
pop(tblptr); pop(offset)}
20
Names in the Symbol table
S → id := E
{p = lookup(id.place);
if p <> nil then emit(p := E.place)
else error}
emit is like gen, but
instead of returning
E → id code, it generates
{p = lookup(id.name); code as a side effect
if p <> nil then E.place = p in a list of three
else error} address instructions.
21
Type conversion within assignments
E → E1+ E2
E.place= newtmp;
if E1.type = integer and E2.type = integer
then emit(E.place ':=' E1.place 'int+' E2.place);
E.type = integer;
…
similar code if both E1.type and E2.type are real
…
else if E1.type = int and E2.type = real
then
u = newtmp;
emit(u ':=' inttoreal E1.place);
emit(E.place ':=' u 'real+' E2.place);
E.type = real;
…
similar code if E1.type is real and E2.type is integer
25
Example
real x, y;
int i, j;
x=y+i*j
generates code
t1 = i int* j
t2 = inttoreal t1
t3 = y real+ t2
x = t3
26
Boolean Expressions
• compute logical values
• change the flow of control
• boolean operators are: and or not
E → E or E
| E and E
| not E
| (E)
| id relop id
| true
| false
27
Methods of translation
• Evaluate similar to arithmetic expressions
– Normally use 1 for true and 0 for false
28
Numerical representation
• a or b and not c
t1 = not c
t2 = b and t1
t3 = a or t2
1. if a < b goto 4.
2. t = 0
3. goto 5
4. t = 1
5.
29
Syntax directed translation of
boolean expressions
E → E1 or E2
E.place := newtmp
emit(E.place ':=' E1.place 'or' E2.place)
E → E1 and E2
E.place:= newtmp
emit(E.place ':=' E1.place 'and' E2.place)
E → not E1
E.place := newtmp
emit(E.place ':=' 'not' E1.place)
E → true
E.place := newtmp
emit(E.place = '1')
E → false
E.place := newtmp
emit(E.place = '0')
31
Example:
Code for a < b or c < d and e < f
100: if a < b goto 103 if e < f goto 111
101: tl = 0 109: t3 = 0
102: goto 104 110: goto 112
103: tl = 1 111: t3 = 1
104:
112:
if c < d goto 107
t4 = t2 and t3
105: t2 = 0
106: goto 108 113: t5 = tl or t4
107: t2 = 1
108:
32
Short Circuit Evaluation of boolean
expressions
• Translate boolean expressions without:
– generating code for boolean operators
– evaluating the entire expression
33
E.true
E.code
E.false
E.true
S1.code
E.false
S → if E then S1
E.true = newlabel
E.false = S.next
S1.next = S.next
S.code = E.code ||
gen(E.true ':') ||
S1.code
34
S → if E then S1 else S2
E.true
E.true = newlabel
E.code
E.false E.false = newlabel
E.true S1.next = S.next
S1.code S2.next = S.next
S.code = E.code ||
goto S.next gen(E.true ':') ||
E.false S1.code ||
S2.code gen(goto S.next) ||
gen(E.false ':') ||
S.next
S2.code
35
S → while E do S1
S.begin E.true S.begin = newlabel
E.code E.true = newlabel
E.false E.false = S.next
E.true S1.next = S.begin
S1.code S.ocde = gen(S.begin ':') ||
E.code ||
goto S.begin gen(E.true ':') ||
S1.code ||
E.false gen(goto S.begin)
36
Control flow translation of
boolean expression
E → E1 or E2 E1.true := E.true
E1.false := newlabel
E2.true := E.true
E2.false := E.false
E.code := E1.code || gen(E1.false)
|| E2.code
39
Example
Code for a < b or c < d and e < f
Ltrue:
Lfalse:
40
Example …
Code for while a < b do
if c<d then
x=y+z
else
x=y-z
42
Translation
code to evaluate E into t code to evaluate E into t
if t <> V1 goto L1 goto test
code for S1 L1: code for S1
goto next goto next
L1 if t <> V2 goto L2
L2: code for S2
code for S2
goto next
goto next
……
L2: ……
Ln-2 if t <> Vn-l goto Ln-l Ln: code for Sn
code for Sn-l goto next
goto next test: if t = V1 goto L1
Ln-1: code for Sn if t = V2 goto L2
next: ….
if t = Vn-1 goto Ln-1
goto Ln
next:
Efficient for n-way branch 43
BackPatching
• way to implement boolean expressions and flow of
control statements in one pass
• attributes truelist and falselist are used to generate jump code for
boolean expressions
45
Boolean expressions …
• Consider E → E1 and M E2
46
E → E1 or M E2
backpatch(E1.falselist, M.quad)
E.truelist = merge(E1.truelist, E2.truelist)
E.falselist = E2.falselist
E → E1 and M E2
backpatch(E1.truelist, M.quad)
E.truelist = E2.truelist
E.falselist = merge(E1.falselist, E2.falselist)
E → not E1
E.truelist = E1 falselist
E.falselist = E1.truelist
E → ( E1 )
E.truelist = E1.truelist
E.falselist = E1.falselist
47
E → id1 relop id2
E.truelist = makelist(nextquad)
E.falselist = makelist(nextquad+ 1)
emit(if id1 relop id2 goto --- )
emit(goto ---)
E → true
E.truelist = makelist(nextquad)
emit(goto ---)
E → false
E.falselist = makelist(nextquad)
emit(goto ---)
M→ Є
M.quad = nextquad
48
Generate code for
a < b or c < d and e < f
100: if a < b goto -
Initialize nextquad to 100 101: goto - 102
102: if c < d goto - 104
103: goto -
E.t={100,104} 104: if e < f goto -
E.f={103,105} 105 goto –
backpatch(102,104)
E.t={100} E.t={104} backpatch(101,102)
or M.q=102
E.f={101} E.f={103,105}
Є
a < b
E.t={102} and M.q=104 E.t ={104}
E.f={103} E.f={105}
Є
c < d e < f 49
Flow of Control Statements
S if E then S1
| if E then S1 else S2
| while E do S1
| begin L end
|A
LL;S
| S
S : Statement
A : Assignment
L : Statement list
50
Scheme to implement translation
• E has attributes truelist and falselist
• S while E do S1
requires labels S.begin and E.true
51
Scheme to implement translation …
S if E then M S1
backpatch(E.truelist, M.quad)
S.nextlist = merge(E.falselist, S1.nextlist)
S if E them M1 S1 N else M2 S2
backpatch(E.truelist, M1.quad)
backpatch(E.falselist, M2.quad )
S.next = merge(S1.nextlist, N.nextlist, S2.nextlist)
S while M1 E do M2 S1
backpatch(S1.nextlist, M1.quad)
backpatch(E.truelist, M2.quad)
S.nextlist = E.falselist
emit(goto M1.quad)
52
Scheme to implement translation …
S begin L end S.nextlist = L.nextlist
L L1 ; M S backpatch(L1.nextlist, M.quad)
L.nextlist = S.nextlist
• Calling sequence
– allocate space for activation record
– evaluate arguments
– establish environment pointers
– save status and return address
– jump to the beginning of the procedure
54
Procedure Calls …
Example
55
Code Generation
• Generate three address code needed to evaluate arguments which
are expressions
S call id ( Elist )
for each item p on queue do emit('param' p)
emit('call' id.place)
Elist Elist , E
append E.place to the end of queue
Elist E
initialize queue to contain E.place
56