07. intermediate code generation
TRANSCRIPT
-
7/28/2019 07. Intermediate Code Generation
1/31
Laszlo Bszrmenyi Compilers Intermediate Code - 1
Compilers
7. Intermediate Code Generation
-
7/28/2019 07. Intermediate Code Generation
2/31
Laszlo Bszrmenyi Compilers Intermediate Code - 2
Separating Analysis and Synthesis
The front-end generates intermediate code
The back-end generates code for target machines
Advantages
StaticChecker IntermediateCode Generator Code GeneratorParserScanner
Optimizer
For k languages and n target
architectures we need onlyk+n compilers, instead of k*n
Language independentoptimizations only once
L1
L2
Lk
M1
M2
Mn
Interm.Code
-
7/28/2019 07. Intermediate Code Generation
3/31
Laszlo Bszrmenyi Compilers Intermediate Code - 3
Three-Address Code (1)
Simulates a hypothetical computer
For intermediate results temporary variables are created
Basic form of statements
x := y op z; // resul:= operand1 op operand2
x := op y; // for unary operations (e.g. -, !)
x := y; // assignment
goto L; // jump to statement labeled by L
if b goto L // conditional jump
if x relop y goto L;
-
7/28/2019 07. Intermediate Code Generation
4/31
Laszlo Bszrmenyi Compilers Intermediate Code - 4
Three-Address Code (2)
param x1, x2,, xn;
call Proc, n; Proc(x1, x2,, xn) y
return y
x := y[i]; // The value at y+i assigned to x
x[i] := y; // Value of y assigned to x+i
x := & y x := ADR (y) // The address of y assigned to x
x := * y x := y- // The value y points at, assigned to x
* x : = y x-:= y // Value of y assigned to the place
// x points at
-
7/28/2019 07. Intermediate Code Generation
5/31Laszlo Bszrmenyi Compilers Intermediate Code - 5
Three-Address Code - Example
Compile: a : = b * -c + b * -cCode for syntax tree
t1 := - c
t2 := b * t1
t3 := - c
t4 : = b * t3
t5 := t2 + t4a := t5
Code for DAG
t1 := - c
t2 := b * t1t5 := t2 + t2
a := t5
-
7/28/2019 07. Intermediate Code Generation
6/31
Laszlo Bszrmenyi Compilers Intermediate Code - 6
SDD generating 3-A Code for Assignments
Production Semantic Rule
S id:= E S.code:= E.code || gen(id.place := E.place)
E E1 + E2 E.place := newtemp;
E.code:= E1.code || E2.code ||
gen(E.place :=E1.place + E2.place)
E E1 * E2 E.place := newtemp;
E.code:= E1.code || E2.code ||
gen(E.place :=E1.place * E2.place)
E -E1 E.place := newtemp;
E.code:= E1.code || gen(E.place := uminusE1.place)
E (E1) E.place := E1.place; E.code:= E1.code
E id E.place :=id.place; E.code:=
concatenation(not or)!concatenation(not or)!
-
7/28/2019 07. Intermediate Code Generation
7/31
-
7/28/2019 07. Intermediate Code Generation
8/31
Laszlo Bszrmenyi Compilers Intermediate Code - 8
Implementation of 3-Addr. Code (1)
With a quadrupel
Operator, argument1, argument2, result
Operator Arg1 Arg2 Result Code
0 uminus c t1 t1:= -c
1 * b t1 t2 t2:= b * t1
2 uminus c t3 t3:= -c
3 * b t3 t4 t4:= b * t3
4 + t2 t4 t5 t5:= t2 + t45 := t5 a a:= t5
-
7/28/2019 07. Intermediate Code Generation
9/31
-
7/28/2019 07. Intermediate Code Generation
10/31
Laszlo Bszrmenyi Compilers Intermediate Code - 10
Static Single-Assignment (SSA)
All assignments with different names at the left side
Easier to find dependencies
Optimization and parallelization gets easier
p:= a + b; p1:= a + b;
q:= p - c; q1:= p1 - c;
p:= q * d; p2:= q1 * d;
p:= e - p; p3:= e - p2;
q:= p + q; q2:= p3 + q1;
In case of two different control flows: (x1
, x2
)
ifflag then x:= -1else x:= 1; y:= x * a;
ifflag then x1:= -1else x2:= 1; x3:=(x1, x2); y:= x3 * a;
Swapallowed?Swapallowed?
Swapallowed?Swapallowed?
-
7/28/2019 07. Intermediate Code Generation
11/31
Laszlo Bszrmenyi Compilers Intermediate Code - 11
Declarations (1)
Memory assignment for variables
Offsets relative to a basis (local or global) Scope management
Help functions mktable (previous)
Generates a new symbol table, and chains it to the previous one
enter (table, name, type, offset) New entry for name in the symbol table (table maybe omitted if obvious)
Type and offset will be set
addwith (table, width) Stores width (the total length of all variables in the scope) in a descriptor
of the actual scope (table)
enterproc (table, name, newtable) New entry for a procedure in table, called name
newtable points to the symbol table of this procedure
-
7/28/2019 07. Intermediate Code Generation
12/31
Laszlo Bszrmenyi Compilers Intermediate Code - 12
Declarations (2)
Type and offset for the declared variablesP {offset := 0} D
D D; D
Did : 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}T array [ num ] ofT1 {T.type := array(num.val, T1.type)
T.width:=num.val * T1.width}
T -T1 {T.type := pointer(T1.type); T.width := 4}
Turning offset into a synthesized attributeP {offset := 0}D
P M D
M e{offset := 0}
-
7/28/2019 07. Intermediate Code Generation
13/31
Laszlo Bszrmenyi Compilers Intermediate Code - 13
Declarations (3)
Nested proceduresP M D {addwidth(top(tblptr), top(offset));
pop(tblptr); pop(offset) }
Me {t := mktable(nil); push(t, tblptr); push(0, offset) }
D D1 ; D2
Dproc id ; N D1 ; S {t := top(tblptr); addwidth(t, top(offset));
pop(tblptr); pop(offset); enterproc(top(tblptr), id.name, t) }Did: T {enter(top(tblptr), id.name, T.type, top(offset));
top(offset) := top(offset) + T.width }
Ne {t := mktable(top(tblptr)); push(t, tblptr); push(0, offset) }
Nested recordsT record L D end {T.type := record(top(tblptr));
T.width := top(offset); pop(tblptr); pop(offset) }
Le {t := mktable(nil); push(t, tblptr); push(0, offset) }
-
7/28/2019 07. Intermediate Code Generation
14/31
Laszlo Bszrmenyi Compilers Intermediate Code - 14
Array-Addressing
1 dimensional arrays (ARRAY [n] OF T)Array limits: [0.. n-1]; w: T.widthComputing address of A [i]
base + i * w (base is relative address of A[0])
2 dimensional arrays (ARRAY [n1, n2] OF T)
n1 lines, width w1 (w1=n2*w); n2 columns, width w2 (w2=w)A [i1, i2] (must be mapped to the 1-dimensional memory)
base + i1 * w1 + i2* w2 base + (i1 * n2+ i2 )* w
Many dimensional arrays (ARRAY [n1, nk] OF T)
A [i1, i2 , , ik]base + i1 * w1 + i2* w2 + + ik * wk
base + ((... (( i1 * n2 + i2) * n3 + i3) ... ) * nk + ik) * w
-
7/28/2019 07. Intermediate Code Generation
15/31
-
7/28/2019 07. Intermediate Code Generation
16/31
Laszlo Bszrmenyi Compilers Intermediate Code - 16
t1 = i * 12 //w1 = 3*4
t2 = j * 4 //w2 = 4t3 = t1 + t2
t4 = a [t3]
t5 = c + t4
3-addr. code
Array References - Example
E.addr = t5
E.addr = cE.addr = t4
L.type = intL.addr = t3
L.array = a
L.type = array(3, int)L.addr = t1
L.array = a
E.addr = j
a.type = array( 2,array(3, int))
E.addr = i
[ ]
+
[ ]
i
c
j
Annotated
parse tree
VAR c: INTEGER;
a: ARRAY [2, 3] OF INTEGER;
BEGIN c + a[i, j]
-
7/28/2019 07. Intermediate Code Generation
17/31
Laszlo Bszrmenyi Compilers Intermediate Code - 17
Boolean Expressions
Two different roles
1. Alter the flow of control2. Compute logical values
Possibilities of compilation Similarly to arithmetic expressions
Using numerical values (e.g. 0 for false and 1 for true)
By altering the control flow (jumping code) Enables lazy evaluation as many languages need (e.g. J ava)
Logical expressions E E || E | E && E | ! E | (E) | E rel E | true | false rel : = || (or) and && (and) are left associative ! rel && || ( for higher precedence)
-
7/28/2019 07. Intermediate Code Generation
18/31
Laszlo Bszrmenyi Compilers Intermediate Code - 18
Numerical Representation - Example
a || b && ! c a || (b && (! c))
t1 := ! c
t2 := b && t1
t3 := a || t2
a < b
Evaluates to 1 if true, to 0 if false
0: if a < b goto 3
1: t:= 0
2: goto 4
3: t:= 1
4: . . . // t = 0 if false, 1 if true
-
7/28/2019 07. Intermediate Code Generation
19/31
Laszlo Bszrmenyi Compilers Intermediate Code - 19
Numerical Representation Translation scheme
E E1 || E2 {E.place:= newtemp;
gen(E.place :=E1.place || E2.place)}E E1 && E2 {E.place:= newtemp;
gen(E.place :=E1.place && E2.place)}
E !E1 {E.place:= newtemp;
gen(E.place := ! E1.place)}
E
E1rel
E2 {E.place:= newtemp;gen(if E1.place rel E2.place goto next+3);
gen(E.place := 0);
gen(goto next+2);
gen(E.place := 1);}
E (E1) {E.place:= E1.place}
E true {E.place:= newtemp; gen(E.place := 1)}
E false {E.place:= newtemp; gen(E.place := 0)}
-
7/28/2019 07. Intermediate Code Generation
20/31
-
7/28/2019 07. Intermediate Code Generation
21/31
Laszlo Bszrmenyi Compilers Intermediate Code - 21
Flow-of-Control Statements (1)
Grammar for conditional statements
S if(B) S1 | if(B) S1else S2 | while (B) S1
Help functions and attributesnewlabel - Generates a new label
label(L) - Attaches label L to the next 3-addr. stat.
E.true The label of the target to spring if E true
E.false The label of the target to spring if E false
S.next - Inherited attribute Denotes the label pointing at the place after statement S
S.code, E.code - contains the code for S resp. E
-
7/28/2019 07. Intermediate Code Generation
22/31
Laszlo Bszrmenyi Compilers Intermediate Code - 22
Flow-of-Control Statements (2)
Production Semantic Rule
P S S.next:= newlabel; P.code:= S.code ||label(S.next)
S if(B)S1
B.true:= newlabel; B.false:= S1.next:= S.next;
S.code:= B.code || label(B.true) || S1.code ||label(S.next)
S if (B)S1 else S2
B.true:= newlabel; B.false:= newlabel;S1.next:= S2.next:= S.next;
S.code:= B.code || label(B.true) || S1.code ||
Gen(goto S.next) || label(B.false) || S2.code ||label(S.next)
S while(B) S1begin:= newlabel; B.true:= newlabel;B.false:= S.next; S1.next:= begin;
S.code:= label(begin) || B.code || label(B.true)|| S1.code || gen(goto begin) || label(S.next)
B.code
S1.code
S2.code
goto S.next
B.true
B.false
S.next
B.code
S1.code
goto begin
B.true
B.false
begin
B.code
S1.codeB.true
B.false
B.tB.f
B.tB.f
-
7/28/2019 07. Intermediate Code Generation
23/31
Laszlo Bszrmenyi Compilers Intermediate Code - 23
Control-Flow Transl. of Boolean Expr. (1)
Instead of generating numerical values, we jump
to the proper placeE: a < b
if a < b goto E.true
goto E.false
E: E1 || E2 (E1orE2 )if E1 ==true, then E ==true, otherwise E == E2
E: E1 && E2 (E1and E2 )if E1 ==false, then E ==false, otherwise E == E2
E: !E1 (not E1)
We just swap the true and false exits if E and E1
-
7/28/2019 07. Intermediate Code Generation
24/31
-
7/28/2019 07. Intermediate Code Generation
25/31
Laszlo Bszrmenyi Compilers Intermediate Code - 25
Control-Flow Transl. of Boolean Expr. (3)
a < b || c < d && e < f
if a < b goto Ltruegoto L1 // This jump is redundant
L1: if c < d goto L2 // if c >= d goto Lfalse were better
goto Lfalse
L2: if e < f goto Ltrue // if e >= f goto Lfalse were bettergoto Lfalse
Ltrue resp. Lfalse are the targets if the entireexpression evaluates to true resp. false
Ltrue and Lfalse are set by the environment Code is suboptimal: redundant jumps
Can be reduced by inverting the condition
-
7/28/2019 07. Intermediate Code Generation
26/31
Laszlo Bszrmenyi Compilers Intermediate Code - 26
Inversion of the conditions
Number of jumps can be reduced
WHILE a < b DOIF c < d THEN x:= y + z ELSE x:= y z ENDEND (*WHILE*)
L1: if a < b goto L2 if a >= b goto Lnextgoto Lnext
L2: if c < d goto L3 if c >= d goto L4goto L4
L3: t1:= y + zx:= t1goto L1
L4: t2:= y z
x:= t2goto L1
Lnext: . . .
-
7/28/2019 07. Intermediate Code Generation
27/31
Laszlo Bszrmenyi Compilers Intermediate Code - 27
Switch statement
Switch (case) statement
Efficient with jump-tables
If the range is large, the jump-table becomes too big
break jumps to S.next break is a bad construction in switch, is o.k. in a loop
Continue in a loop jumps to the start of the iterationswitch (E) {
0: S0 ; break;
1: S1 ; break;
n: Sn ; break;
}
0: goto 0
1: goto 1
...
n: goto n
n+1: Next statement
-
7/28/2019 07. Intermediate Code Generation
28/31
Laszlo Bszrmenyi Compilers Intermediate Code - 28
Backpatching (1)
Backpatching
While generating forward jumps, target is not known
We generate jumps with open target
We keep such jumps on a list (e.g. E.truelist, E.falselist)
We update the jumps when the target has been reached
Help functions
makelist(i)
creates new patch-list, pointing at statement-i
(i is an index of the code-array)
merge(p1,p2): merges two patch-lists
backpatch(p,i): sets i as target in all statements of p
-
7/28/2019 07. Intermediate Code Generation
29/31
Laszlo Bszrmenyi Compilers Intermediate Code - 29
Backpatching (2)
E E1 orM E2 |
E1 and M E2 |not E1 |
(E1) |
id1relopid2 |
true |
false
Me
truelist resp. falselist contain open targets for the case, the expressionevaluates to true resp. to false
nextquad points at the next index value
M.quad contains the number of the first statement ofE2.code {M.quad := nextquad}
-
7/28/2019 07. Intermediate Code Generation
30/31
Laszlo Bszrmenyi Compilers Intermediate Code - 30
Backpatching (3)
-
7/28/2019 07. Intermediate Code Generation
31/31
Laszlo Bszrmenyi Compilers Intermediate Code - 31
Backpatching (4)
a < b || c < d && e < f