CH 5 - Intermediate Code Generation
CH 5 - Intermediate Code Generation
CH 5 - Intermediate Code Generation
1
Intermediate Code Generation
• The compiler converts the source program
into an intermediate representation at the
end of the analysis phase
3
Three Address Code
• Important notes about statements in three
address code statements:
– No predefined arithmetic (or any) operator is
permitted.
– Only one operation is allowed in a statement
Ex. w = x+ y * z
becomes
t1 = y * z
w = x + t1
• 3 @ code statements can have labels and
statements for flow control (ex. goto) 4
Types of 3 @ Statements
• Assignment (binary operation)
– x := z op w
• Assignment (unary operation)
– x := op y
• Copy
– x := y
• Unconditional Jump
– Goto L
• Conditional Jump
– if x relop y goto L 5
Types of Statements (cont'd)
• Function call
– Parameter specification
• param x1
– Calling the function
• call P, N { P : function & N : no. of parameters }
• Indexed Arguments
– x := y[I] { x = value at address y+I }
– y[I] := x { value at address y+I = x }
6
Types of Statements (cont'd)
• Address and Pointer Assignments
– x := &y { x = address of y }
– x := *y { x = the value at address y }
– *x := y { value at address x = y }
7
Syntax Directed Translation into
Three Address Code
• The 3 @ code is generated either as an attribute
of the parse tree or by writing the statements in
a file as soon as they are generated.
• NewLabel() :
each time it is called gives distinct names that
can be used for label names.
9
3 @ Code Generation
(Assignment & Expression)
S → id := E S.code := E. code || gen(id.lexeme,”:=”, E.place)
E1 → E2 + E3 E1.place := newTemp();
E1.code := E2.code || E3.code || gen(E1.place, “:=”, E2.place, “+”,
E3.place)
E1 → E2 * E3
E1 → - E2 E1.place := newTemp();
E1.code := E2.code || gen(E1.place, “:=”, “-”, E2.place)
E1 → (E2) E1.code := E2.code
E1.place := E2.place
E → id E.place := id.lexeme
E1 → E2 < E3 E1.place = newTemp()
E1.code = E2.code || E3.code || gen(E1.place, “:=“, E2.place, “<“,
E3.place);
10
3 @ Code Generation (Assignment
& Expression)
S1 → while E do S2
S1.begin := newLabel();
S1.after := newLabel();
S1.code := gen(S1.begin, “:”) || E.code || gen(
“if”, E.place, “= 0 goto”, S1.after) || S2.code ||
gen( “goto”, S1.begin) || gen( S1.after, “:”);
11
3 @ Code Generation
(Assignment & Expression)
• Example:
1. Consider the string:
A := B + C
Draw the decorated parse tree based on the
previous syntax directed translation.
2. Consider the string:
while a < b do a := a + 1
Draw the decorated parse tree.
12
Declarations
• While process declarations, the compiler
– reserves memory area for the variables
– stores the relative address of each variable in the symbol table (the
relative address is an address in the static data area relative to the
beginning – offset address)
• For this purpose, the compiler maintains an offset variable
that indicates the first address not yet allocated.
• Initially, offset is set to zero.
• Each time an address is allocated to a variable, the offset
is incremented by the width of the data object denoted by
the name.
• The procedure enter (name, type, address) creates a
symbol table entry for name with type type and address
address. 13
Declarations (cont’d)
P → {offset = 0} D S
D → D;D
D → id : T enter(id.lexeme, T.type, offset);
T → integer T.type = integer;
T.size = 2;
T → real T.type = real;
T.size = 4;
T → array[num] of T T1.type = array([num.value], T2.type);
T1.size = num.value*T2.size;
T → ^T T1.type = pointer( T2.type);
T1.size = 2;
14
Declarations (cont’d)
• Example
Consider the following declaration
x : integer;
y : real;
z : char;
t : array[10] of integer;
v : ^Integer;
What would be the content of the symbol
table after this declaration is processed?
15
Declarations (cont’d)
Symbol table after processing the previous declarations.
16