Unit-5 Compiler Design - Code Generation
Unit-5 Compiler Design - Code Generation
By Varun Arora
Outline
Variants of Syntax Trees
Three-address code
Types and declarations
Translation of expressions
Type checking
Control flow
Backpatching
By Varun Arora
Introduction
Intermediate code is the interface between front end
and back end in a compiler
Ideally the details of source language are confined to
the front end and the details of target machines to the
back end (a m*n model)
In this chapter we study intermediate representations,
static type checking and intermediate code generation
+ *
*
d
a -
By Varun Arora b c
SDD for creating DAG’s
Production Semantic Rules
1) E -> E1+T E.node= new Node(‘+’, E1.node,T.node)
2) E -> E1-T E.node= new Node(‘-’, E1.node,T.node)
3) E -> T E.node = T.node
4) T -> (E) T.node = E.node
5) T -> id T.node = new Leaf(id, id.entry)
6) T -> num T.node = new Leaf(num, num.val)
Example:
1) p1=Leaf(id, entry-a) 8) p8=Leaf(id,entry-b)=p3
2) P2=Leaf(id, entry-a)=p1 9) p9=Leaf(id,entry-c)=p4
3) p3=Leaf(id, entry-b) 10) p10=Node(‘-’,p3,p4)=p5
4) p4=Leaf(id, entry-c) 11) p11=Leaf(id,entry-d)
5) p5=Node(‘-’,p3,p4) 12) p12=Node(‘*’,p5,p11)
6) p6=Node(‘*’,p1,p5) 13) p13=Node(‘+’,p7,p12)
7) p7=Node(‘+’,p1,p6) By Varun Arora
Value-number method for
constructing DAG’s
= id To entry for i
num 10
+ + 1 2
3 1 3
i 10
Algorithm
Search the array for a node M with label op, left child l
and right child r
If there is such a node, return the value number M
If not create in the array a new node N with label op, left
child l, and right child r and return its value
We may use a hash table
By Varun Arora
Three address code
In a three address code there is at most one operator at
the right side of an instruction
Example:
+
t1 = b – c
+ * t2 = a * t1
t3 = a + t2
* t4 = t1 * d
d
t5 = t3 + t4
a -
b c
By Varun Arora
Forms of three address
instructions
x = y op z
x = op y
x=y
goto L
if x goto L and ifFalse x goto L
if x relop y goto L
Procedure calls using:
param x
call p,n
y = call p,n
x = y[i] and x[i] = y
x = &y and x = *y and *x =y
By Varun Arora
Example
do i = i+1; while (a[i] < v);
L: t1 = i + 1 100: t1 = i + 1
i = t1 101: i = t1
t2 = i * 8 102: t2 = i * 8
t3 = a[t2] 103: t3 = a[t2]
if t3 < v goto L 104: if t3 < v goto 100
By Varun Arora
Data structures for three
address codes
Quadruples
Has four fields: op, arg1, arg2 and result
Triples
Temporaries are not used and instead references to
instructions are made
Indirect triples
In addition to triples we use a list of pointers to triples
By Varun Arora
Three address code
Example t1 = minus c
t2 = b * t1
b * minus c + b * minus c t3 = minus c
t4 = b * t3
t5 = t2 + t4
a = t5
By Varun Arora
Type Expressions
Example: int[2][3]
array(2,array(3,integer))
By Varun Arora
Declarations
By Varun Arora
Storage Layout for Local Names
Computing types and their widths
By Varun Arora
Storage Layout for Local Names
Syntax-directed translation of array types
By Varun Arora
Sequences of Declarations
By Varun Arora
Fields in Records and Classes
By Varun Arora
Translation of Expressions and
Statements
We discussed how to find the types and offset of
variables
We have therefore necessary preparations to discuss
about translation to intermediate code
We also discuss the type checking
By Varun Arora
Three-address code for expressions
By Varun Arora
Incremental Translation
By Varun Arora
Addressing Array Elements
Layouts for a two-dimensional array:
By Varun Arora
Semantic actions for array reference
By Varun Arora
Translation of Array References
By Varun Arora
Conversions between primitive
types in Java
By Varun Arora
Introducing type conversions into
expression evaluation
By Varun Arora
Abstract syntax tree for the
function definition
fun length(x) =
if null(x) then 0 else length(tl(x)+1)
By Varun Arora
Inferring a type for the function length
By Varun Arora
Algorithm for Unification
By Varun Arora
Unification algorithm
boolean unify (Node m, Node n) {
s = find(m); t = find(n);
if ( s = t ) return true;
else if ( nodes s and t represent the same basic type ) return true;
else if (s is an op-node with children s1 and s2 and
t is an op-node with children t1 and t2) {
union(s , t) ;
return unify(s1, t1) and unify(s2, t2);
}
else if s or t represents a variable {
union(s, t) ;
return true;
}
else return false;
}
By Varun Arora
Control Flow
boolean expressions are often used to:
Alter the flow of control.
Compute logical values.
By Varun Arora
Short-Circuit Code
By Varun Arora
Flow-of-Control Statements
By Varun Arora
Syntax-directed definition
By Varun Arora
Generating three-address code for booleans
By Varun Arora
translation of a simple if-statement
By Varun Arora
Backpatching
Previous codes for Boolean expressions insert symbolic labels for
jumps
It therefore needs a separate pass to set them to appropriate addresses
We can use a technique named backpatching to avoid this
We assume we save instructions into an array and labels will be indices
in the array
For nonterminal B we use two attributes B.truelist and B.falselist
together with following functions:
makelist(i): create a new list containing only I, an index into the array
of instructions
Merge(p1,p2): concatenates the lists pointed 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 instruction
on the list pointed to by p
By Varun Arora
Backpatching for Boolean Expressions
By Varun Arora
Backpatching for Boolean Expressions
Annotated parse tree for x < 100 || x > 200 && x ! = y
By Varun Arora
Flow-of-Control Statements
By Varun Arora
Translation of a switch-statement
By Varun Arora
Readings
Chapter 6 of the book
By Varun Arora