Unit-4 Chapter-2
Unit-4 Chapter-2
Tech-II Sem
Name of the Course: Compiler Design(15A05601) Regulation: R15
4 II Part
Unit-3-
Intermediate Code Generation: Variants of syntax trees, three address code, Types and
declarations, Translations of expressions, Type checking, control flow statements, backpatching,
switch statements, intermediate code for procedure.
a + a * (b - c) + (b - c)* d
The nodes of a syntax tree or DAG are stored in an array of records, as suggested by Fig.. Each row of
the array represents one record, and therefore one node. In each record, the first field is an
operation code, indicating the label of the node. In Fig.(b), leaves have one additional field, which
holds the lexical value (either a symbol-table pointer or a constant, in this case), and interior nodes
have two additional fields indicating the left and right children.
In this array, we refer to nodes by giving the integer index of the record for that node within the
array. This integer historically has been called the value number for the node or for the expression
represented by the node. For instance, in Fig. 6.6, the node labeled -I- has value number 3, and its
left and right children have value numbers 1 and 2, respectively. In practice, we could use pointers to
records or references to objects instead of integer indexes, but we shall still refer to the reference to
Type Checking:-
A compiler has to do semantic checks in addition to syntactic checks.
Type Checking is the process of verifying that each operation executed in a program respects
the type system of the language.
Semantic Checks
Static – done during compilation
Dynamic – done during run-time
A type system is a collection of rules for assigning type expressions to the parts of a program.
Static Type Checking:-
1. Type checks: A compiler should report an error if an operator is applied to an incompatible
operand.(Incompatible Operand)
2. Flow of control checks: Places for transfer of control should be specified.(break statement)
3. Uniqueness checks: An object must be defined exactly (like the type of an identifier, statements
inside a case/switch statement.) (Uniquely declared identifier)
4. Name Related checks: Same name must appear two or more times.
Usage of Temporaries:-
Temporaries are used to hold intermediate values when evaluated expressions need to be stored in
the symbol-table.
They can require a lot of space for their values.
Moreover wasting space implies wasting time. Indeed they have to be loaded into registers,
written back, etc.
For nowadays compilers, time performance is a crucial issue since space is almost illumined.
Temporaries can be re-used!
There are a lot of different approaches to doing this and a lot of discussion about when
during compilation it should be done.
1. Assignment statement-
x = y op z and x = op y
Here, x, y and z are the operands and op represents the operator.
The result obtained after solving the right side expression of the assignment operator is
being assigned to the left side operand.
2. Copy statement-
x=y
Here, x and y are the operands and ‘=’ is an assignment operator.
The value of operand y is being copied / assigned to the operand x.
3. Conditional jump-
If x relop y goto X
Here, x & y are the operands, X is the tag or label of the target statement and relop is a
relational operator.
If the condition “x relop y” gets satisfied on executing the statement, then the control is
directly sent to the location specified by the label X and all the statement in between them
are skipped.
If the condition “x relop y” fails on executing the statement, then the next statement
appearing in the usual sequence is executed.
4. Unconditional jump-
goto X
Here, X is the tag or label of the target statement.
When the statement is executed, the control is directly sent to the location specified by the
label X without checking any condition and all the statements in between them are skipped.
Solution-
We can write Three Address Code for the expression given as-
(1) If (A < B) goto (4)
(2) T1 = 0
(3) goto (5)
(4) T1 = 1
(5)
Example4: Demonstration for Boolean Expressions:
Write Three Address Code for the expression given below-
If A < B and C < D then t = 1 else t = 0
Solution-
We can write Three Address Code for the expression given as-
Example:-
Consider expression a = b * – c + b * – c.
The three address code is:
SRINIVASA RAMANUJAN INSTITUTE OF TECHNOLOGY, ANATHAPURAMU
13
t1 = uminus c
t2 = t1 * b
t3 = uminus c
t4 = t3 * b
t5 = t2 + t4
a = t5
2. Triples: - Fields are corresponding to temporary results are not used and references to
This representation makes use of pointer to the listing of all references to computations which is
made separately and stored. It’s similar in utility as compared to quadruple representation but
requires less space than it. Temporaries are implicit and easier to rearrange code. In addition to
triples we use a list of triples of pointers to triples.
Example – Consider expression a = b * – c + b * – c
1) S if E then S1
Semantic Rules for the above statement is
E.true:== new_label ();
E.false:= S.next;
S1.next:= S.next;
S.code:= E.code || gen_code (E.true’ :’) || S1.code.
2) S if E then S1 else S2
E.true:== new_label ();
E.false:= new_label ();
S1.next:= S.next;
S2.next:= S.next;
S.code:= E.code||gen_code (E.true ‘:’) ||S1.code||gen_code (‘goto’ S.next) ||
gen_code (E.false‘:’) ||S2.code
Backpatching:-
The syntax directed definition we discussed before can be implemented in two or more passes (we
have both synthesized attributes and inheriting attributes).
Build the tree first
Walk the tree in the depth first order.
The main difficulty with code generation in one pass is that we may not know the target of a branch
when we generate code for flow-of –control statements.
Backpatching is the technique to get around this problem.
Generate branch instructions with empty targets
When the target is known, fill in the label of the branch instructions (backpatching).
The problem in generating three address codes in a single pass is that we may not know the labels
that control must go to at the time jump statements are generated.
So to get around this problem a series of branching statements with the targets of the jumps
temporarily left unspecified is generated.
Back Patching is putting the address instead of labels when the proper label is determined.
References:-
https://slideplayer.com/slide/9936796/
https://www.geeksforgeeks.org/three-address-code-compiler/
https://www.brainkart.com/article/Variants-of-Syntax-Trees_8160/