Module 6 - Intermediate Code
Module 6 - Intermediate Code
Compiler Design
MODULE - 4
Dr. WI. Sureshkumar
Associate Professor
School of Computer Science and Engineering (SCOPE)
VIT Chennai
wi.sureshkumar@vit.ac.in
Module -4
Intermediate Code Generation
• Intermediate Languages
• Declarations
• Assignment Statements
• Boolean Expressions
• Case Statements
• Backpatching
• Procedure Calls.
Intermediate code generator
• A compiler while translating a source program into its equivalent object
code representation, may first generate an intermediate representation.
• The advantage of generating an intermediate representation are
• Easy of conversion from source program to the intermediate code
• Easy to do the subsequent processing from the intermediate code
Intermediate
Parse
code
Tree Intermediate Code Code
Parser
Generator Generator
+
c
-
a 4
Construction of syntax tree for expression
• The construction of a syntax tree for an expression is similar to the translation of the
expression into postfix form.
• Each node in a syntax tree can be implemented as a record with several fields.
• The following functions are used to create the nodes of a syntax tree for an
expression with binary operators
+ *
a - d
*
b c
a -
b c
Postfix notation
a–4+c
a4–c+
a + a * (b – c) + (b – c) * d
a a bc– * + b c– d*+
Three address code
• Three address code is a sequence of statements of the form
x := y op z
x, y, z are names, constants, or compiler generated
temporaries and op stands for operator.
Ex: Three address code for the exp a + b * c + d
t1 = b * c
t2 = a + t1
t3 = t2 + d
16 t1 = c + 1
17 c = t1
18 goto 10
19 if a <= d goto 21
Example: 4
switch (i + j) 10 t1 = i + j 21 if t1 = 1 goto 12
{ 11 goto 21 22 if t1 = 2 goto 15
case 1: x = y + z; break; 12 t2 = y + z 23 goto 18
case 2: u = v + w; break; 13 x = t2 24
default: p = q + r; 14 goto 24
} 15 t3 = v + w
16 u = t3
17 goto 24
18 t4 = q + r
19 p = t4
20 goto 24
Example: 5
switch (a + b)
{
case 2: { x = y; break; }
case 5: { switch x
{
case 0: { a = b + 1; break;}
case 1: { a = b + 3; break;}
default: { a = 2; break;}
}
break;
case 9: { x = y - 1; break; }
default: { a = 2; break; }
}
10 t1 = a + b 21 a = 2 32 if t1 = 2 goto 12
11 goto 32 22 goto 36 33 if t1 = 5 goto 14
12 x = y 23 if x = 0 goto 15 34 if t1 = 9 goto 27
13 goto 36 24 if x = 1 goto 18 35 goto 30
14 goto 23 25 goto 21 36
15 t2 = b+ 1 26 goto 36
16 a = t2 27 t4 = y - 1
17 goto 36 28 x = t4
18 t3 = b + 3 29 goto 36
19 a = t3 30 a = 2
20 goto 36 31 goto 36
Syntax Directed Definition
• The following CFG
S→ABC , A→aA / a , B→bB / b , C→cC / c generates
L = { anbmcp /m, n, p ≥ 1}
• We define an Attributed grammar (AG) based on the above CFG to
generate
L = { anbncn / n ≥ 1}
• All the non terminal will have only synthesized attributes.
S.equal , A.count, B.count, C.count
SDD
S→ABC { S.equal = if A.count = B.count & B.count = C.count then T
else F}
A→ a { A.count = 1}
A→aA { A1.count = A2 . count +1}
B→b { B.count = 1}
B→bB { B1.count = B2 . count +1}
C→ c { C.count = 1}
C→cC { C1.count = C2.count +1}
• Attributed grammar (AG) for the evaluation of real number from its
binary representation,
110 . 101 = 6 . 625
N→ L . R , L→BL / B , R→BR / B , B→ 0 / 1
id := E b+c*d
a
t1 = c * d E + E c*d
t2 = b + t1
a = t2
id * E
b E
id id
c d
SDT for Expressions
E→E+T { E.val := E.val + T.val}
E→ T { E.val := T.val}
T→T*F { T.val := T.val * F.val}
T→ F { T.val := F.val}
F →id { F.val := num.lexval}
5+6*4 E
E + T
T T * F
F id
F
4
id id
5
6
5+6*4 E.val = 5 + 24 = 29
E.val = 5 + T.val = 6 * 4 = 24
F.val = 5 id
F.val = 6
4
id id
5
6
SDT for Boolean Expression
Example: Three address code for a < b or c < d and e < f
100: if a < b goto 103 110 goto 112
101: t1 = 0 111 t3 = 1
102 goto 104 112 t4 = t2 and t3
103 t1 =1 113 t5 = t1 or t4
104 if c < d goto 107
105 t2 = 0
106 goto 108
107 t2 =1
108 if e < f goto 111
109 t3=0
SDT for Flow of Control Statements
if (B.code) if (B.code)
{ {
B.true: B.true:
} }
B.false: goto S.next
{
B.false:
}
SDT for Flow of Control Statements
SDT for Declarations
D → TL { L.type := T.type}
T → int { T.type := int}
T → real { T.type := real}
L → L1,id { L1.type := L.type}
{ enter(id.ptr, L.type)
L →id {enter(id.ptr, L.type)}
int id1, id2, id3
D L. type = T. type = int
L , id
L. type = int
id
T → BC { T.a := C.a , C.b = B.a}
B → int {B.a := int}
B → float { B.a := float}
C → [num]C1 { C.a := array(num.val,
C1.a )
C1.b := C.b}
C →e {C.a = C.b}
Back-patching
• To implement SDT is to uses two passes. In the first pass, construct the
syntax tree for the input. In the second pass, walk through the tree in
depth first order, computing the translation in the definition.
• The main problem for generating three address code for Boolean
statement and flow of control statements in a single pass we may not
know the labels that control must go to at the time the jump statements
are generated.
• We can solve this problem by generating a series of branching statements
with target of the jumps temporarily unspecified.
• Each such statement will be put on a list of goto statements whose label
will be filled in when the proper label can be determined.
• We call this subsequent filling in of labels backpatching.
We show how backpatching can be used to generate code for Boolean
expression in one pass.
To manipulate list of labels, we use three functions:
makelist(i) - creates a new list containing only i, an index into the
array of quadruples.
merge(p1, p2) – concatenates the lists pointed to by p1 and p2 , and
returns a pointer to the concatenated list.
backpatch(p, i) – inserts i as the target label for each of the statements
on the list pointed to by p.
Boolean Expressions
(1) E → E1 or M E2
(2) E → E1 and M E2
(3) E → not E1
(4) E → (E1)
(5) E → id1 reop id2
(6) E → true
(7) E → false
(8) M→ ε
• Consider the production E → E1 and M E2 .
• If E1 is false, then E is also false, so E1.falselist become part of
E.falselist.
• If E1 is true, then we must next test E2. So the target for the
statements E1.truelist must be the beginning of the code generated
for E2.
• This target is obtained using the marker nonterminal M.
• Attribute M.quad records the number of the first statement E2.code
• With the production M → ε we associate the semantic action
{M.quad := nextquad}
Example: a < b or c < d and e < f
Apply production (5) for a < b
100 if a < b goto ___
101 goto ___
E1 or M
E2
ε
a < b E1 and M
E2
ε
c < d e < f
We now reduce E → E1 and M E2. The corresponding semantic action
calls backpatch({102}, 104).
This call to backpatch fills in 104 in statement 102.
100 if a < b goto ___
101 goto ___
102 if c < d goto 104
103 goto ___
104 if e < f goto ___
105 goto ___
The semantic action associated with the final reduction E → E1 or M E2
calls backpatch({101}, 102).
call id ( Elist )
read
initial Elist , E
final
final
param initial
E
param final initial
call read , 2