Module 5
Module 5
M (AP, CSE)
IES College of Engineering
MODULE 5
Run-Time Environments: Source Language issues,
Storage organization, Storage- allocation strategies.
Intermediate Code Generation (ICG): Intermediate
languages – Graphical representations, Three-Address
code, Quadruples, Triples. Assignment statements,
Boolean expressions.
1
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
Runtime environment is a state of the target machine, which may include software libraries,
environment variables, etc., to provide services to the processes running in the system.
When a procedure name appears with in an executable statement, the procedure is said to be
called at that point.
Activation Tree
Each execution of procedure is referred to as an activation of the procedure. Lifetime
of an activation is the sequence of steps present in the execution of the procedure.
If ‘a’ and ‘b’ be two procedures, then their activations will be non-overlapping (when
one is called after other) or nested (nested procedures).
2
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
EXAMPLE
Consider the following program of quicksort
main()
{
readarray();
quicksort(1,10);
}
quicksort(int m, int n)
int i= partition(m,n);
quicksort(m,i-1);
quicksort(i+1,n);
}
First main function as root then main calls readarray and quicksort.
Quicksort in turn calls partition and quicksort again. The flow of control in a program
corresponds to the depth first traversal of activation tree which starts at the root.
3
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
Control Stack
Control stack or runtime stack is used to keep track of the live procedure activations
i.e the procedures whose execution have not been completed.
A procedure name is pushed on to the stack when it is called (activation begins) and
it is popped when it returns (activation ends).
When a procedure is called, an activation record is pushed into the stack and as soon
as the control returns to the caller function the activation record is popped.
Then the contents of the control stack are related to paths to the root of the activation
tree. When node n is at the top of the control stack, the stack contains the nodes along
the path from n to the root.
Consider the above activation tree, when quicksort(4,4) gets executed, the contents of
control stack were main() quicksort(1,10) quicksort(1,4), quicksort(4,4)
var i : integer;
or may be explicit. The portion of program to which a declaration applies is called the
scope of that declaration.
Binding Of Names
Even if each name is declared once in a program, the same name may denote different
data object at run time. “Data objects” corresponds to a storage location that hold
values.
The term environment refers to a function that maps a name to a storage location.
The term state refers to a function that maps a storage location to the value held there.
4
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
The management and organization of this logical address space is shared between the
compiler, operating system and target machine. The operating system maps the
logical address into physical addresses, which are usually spread through memory.
Code area: used to store the generated executable instructions, memory locations for
the code are determined at compile time
Static Data Area: Is the locations of data that can be determined at compile time
Stack Area: Used to store the data object allocated at runtime. eg. Activation records
Heap: Used to store other dynamically allocated data objects at runtime ( for ex:
malloac)
5
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
Activation Records
It is LIFO structure used to hold information about each instantiation.
Procedure calls and returns are usually managed by a run time stack called control
stack.
Each live activation has an activation record on control stack, with the root of the
activation tree at the bottom, the latter activation has its record at the top of the stack
The contents of the activation record vary with the language being implemented.
The purpose of the fields of an activation record is as follows, starting from the field
for temporaries.
2. The field for local data holds data that is local to an execution of a procedure.
3. The field for saved machine status holds information about the state of the
machine just before the procedure is called. This information includes the
values of the program counter and machine registers that have to be restored
when control returns from the procedure.
4. The optional access link is used to refer to nonlocal data held in other activation
records.
5. The optional control /ink paints to the activation record of the caller
6. The field for actual parameters is used by the calling procedure to supply
parameters to the called procedure.
7. The field for the returned value is used by the called procedure to return a
value to the calling procedure, Again, in practice this value is often returned
in a register for greater efficiency.
Returned value
Actual parameters
Local data
temporaries
6
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
Static allocation - lays out storage for all data objects at compile time
Heap allocation - allocates and deallocates storage as needed at run time from a data
area known as heap.
Static Allocation
In static allocation, names bound to storage as the program is compiled, so there is no
need for a run-time support package.
Since the bindings do not change at runtime, every time a procedure activated, its run-
time, names bounded to the same storage location.
From the type of a name, the compiler decides amount of storage for the name and
decides where the activation records go. At compile time, we can fill in the address at
which the target code can find the data it operates on.
Stack Allocation
All compilers for languages that use procedures, functions or methods as units of user
functions define actions manage at least part of their runtime memory as a stack run-
time stack.
Each time a procedure called, space for its local variables is pushed onto a stack, and
when the procedure terminates, space popped off from the stack
Calling Sequences
A return sequence is similar to code to restore the state of a machine so the calling
procedure can continue its execution after the call.
The code is calling sequence of often divided between the calling procedure (caller)
and a procedure is calls (callee)(callee).
When designing calling sequences and the layout of activation record, the following
principles are helpful:
7
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
1. Value communicated between caller and callee generally placed at the caller
beginning of the callee’s activation record, so they as close as possible to the
caller’s activation record.
2. Fixed length items generally placed in the middle. Such items typically include
the control link, the access link, and the machine status field.
3. Items whose size may not be known early enough placed at the end of the
activation record.
4. We must locate the top of the stack pointer judiciously. A common approach
is to have it point to the end of fixed length fields in the activation is to have it
point to fix the end of fixed length fields in the activation record. Fixed length
data can then be accessed by fixed offsets, known to the intermediate code
generator, relative to the top of the stack pointer.
The calling sequence and its division between caller and callee are as follows:
2. The caller stores a return address and the old value of top_sp into the callee’s
activation record. The caller then increments the top_sp to the respective
positions.
8
Prepared by EBIN P.M (AP, CSE)
IES College of Engineering
In modern languages, objects whose size cannot be determined at compile time are
allocated space in the heap
We avoid the expense of garbage collecting their space. Note that the stack can be
used only for an object if it is local to a procedure and becomes inaccessible when the
procedure returns.
9
CS304 Compiler Design /B.Tech/S6
Heap Allocation
Stack allocation strategy cannot be used if either of the following is possible :
Heap allocation parcels out pieces of contiguous storage, as needed for activation
records or other objects.
Pieces may be deallocated in any order, so over the time the heap will consist of
alternate areas that are free and in use.
The record for an activation of procedure r is retained when the activation ends.
Therefore, the record for the new activation q(1 , 9) cannot follow that for s physically.
If the retained activation record for r is deallocated, there will be free space in the heap
between the activation records for s and q.
10
CS304 Compiler Design /B.Tech/S6
2. IC eliminates the need of a new full compiler for every machine by keeping the
analysis portion for all the compilers.
2 important things:
A source program can be translated directly into the target language, but some benefits of
using intermediate form are:
11
CS304 Compiler Design /B.Tech/S6
Syntax Tree
DAG (Direct Acyclic Graph)
Postfix Notation
3 Address Code
Syntax Tree
DAG (Direct Acyclic Graph)
Syntax tree (AST) is a condensed form of parse tree useful for representing language
constructs.
EXAMPLE
EE-T
E T E + T * 4
TT * F
T F
TF 3 5
F digit
T * F digit
F digit 4
digit 5
12
CS304 Compiler Design /B.Tech/S6
Each interior node represents a grammar Each interior node represents an operator
rule
Each leaf node represents a terminal Each leaf node represents an operand
Parse tree represent every detail from the Syntax tree does not represent every detail
real syntax from the real syntax
Eg : No parenthesis
In the node of an operator, one field contains operator and remaining field contains
pointer to the nodes for the operands.
When used for translation, the nodes in a syntax tree may contain addition of fields
to hold the values of attributes attached to the node.
13
CS304 Compiler Design /B.Tech/S6
EXAMPLE
a–4+c
The tree is constructed
bottom up
P1 = mkleaf(id,entry a)
P2 = mkleaf(num, 4)
P3 = mknode(-, P1, P2)
P4 = mkleaf(id,entry c)
P5 = mknode(+, P3, P4)
Syntax Tree
The two binary operators + and * are examples of the full operator set in a typical
language. Operator associates and precedences are the usual ones, even though they
have not been put into the grammar. This definition constructs the tree from the input
a:=b* -c + b* -c
The token id has an attribute place that points to the symbol-table entry for the
identifier.
A symbol-table entry can be found from an attribute id.name, representing the lexeme
associated with that occurrence of id.
14
CS304 Compiler Design /B.Tech/S6
If the lexical analyser holds all lexemes in a single array of characters, then attribute
name might be the index of the first character of the lexeme.
In (a), each node is represented as a record with a field for its operator and additional
fields for pointers to its children.
In Fig (b), nodes are allocated from an array of records and the index or position of
the node serves as the pointer to the node.
All the nodes in the syntax tree can be visited by following winters, starting from the
root at position 10.
Dag also gives the hierarchical structure of source program but in a more compact
way because common sub expressions are identified.
15
CS304 Compiler Design /B.Tech/S6
EXAMPLE
a=b*-c + b*-c
Postfix Notation
Linearized representation of syntax tree
In postfix notation, each operator appears immediately after its last operand.
Operators can be evaluated in the order in which they appear in the string
EXAMPLE
Source String : a := b * -c + b * -c
Postfix Rules
2. If E is an expression of the form E1 op E2 then postfix notation for E is E1’ E2’ op, here
E1’ and E2’ are the postfix notations for E1and E2, respectively
3. If E is an expression of the form (E), then the postfix notation for E is the same as the
postfix notation for E.
16
CS304 Compiler Design /B.Tech/S6
The reason for the term “three address code” is that each statement contains 3
addresses at most. Two for the operands and one for the result.
a = b op c
where,
t1 := y*z
t2 := x+t1 where, t1 and t2 are compiler generated
temporary names.
Three Address Code corresponding to the syntax tree and DAG given above (page no: )
17
CS304 Compiler Design /B.Tech/S6
1. Assignment statements
2. Assignment instructions
3. Copy statements
4. Unconditional jump
5. Conditional jump
param x and call p, n for procedure calls and return y, where y representing a
returned value is optional. Their typical use is as the sequence of three-address
statements
param x1
param x2
……….
param xn
call p,n
generated as part of the call procedure p( xl , x2, . . . , xn ) . The integer n indicating
the number of actual-parameters in ''call p , n" is not redundant because calls can be
nested.
7. Indexed Assignments
Indexed assignments of the form x = y[i] or x[i] = y
18
CS304 Compiler Design /B.Tech/S6
Given input a:= b * - c + b + - c, it produces the three address code in given above
(page no: ) The synthesized attribute S.code represents the three address code for
the assignment S. The nonterminal E has two attributes:
19
CS304 Compiler Design /B.Tech/S6
The function newtemp returns a sequence of distinct names t1, t2,……… in respose
of successive calls. Notation gen(x ‘:= ‘y ‘+’ z is used to represent the three address
statement x := y + z.
Expressions appearing instead of variables like x, y and z are evaluated when passed
to gen, and quoted operators or operand, like ‘+’ are taken literally.
Flow of control statements can be added to the language of assignments. The code for
S while E do S1 is generated using new attributes S.begin and S.after to mark the
first statement in the code for E and the statement following the code for S,
respectively.
The function newlabel returns a new label every time is called. We assume that a
nonzero expression represents true; that is when the value of E becomes zero, control
laves the while statement
Quadruples
Triples
Indirect triples
5.2.1.3 QUADRUPLES
A quadruple is a record structure with four fields, which are op, ag1, arg2 and result
The op field contains an internal code for the operator. The three address statement
x:= y op z is represented by placing y in arg1, z in arg2 and x in result.
The contents of arg1, arg2, and result are normally pointers to the symbol table
entries for the names represented by these fields. If so temporary names must be
entered into the symbol table as they are created.
EXAMPLE 1
a+b*c|e^f+b*a
For the first construct the three address code for the expression
t1 = e ^ f
t2 = b * c
t3 = t2 / t1
t4 = b * a
t5 = a + t3
t6 = t5 + t4
20
CS304 Compiler Design /B.Tech/S6
A statement like param t1 is represented by placing param in the operator field and
t1 in the arg1 field. Neither arg2 not result field is used
Unconditional & Conditional jump statements are represented by placing the target
in the result field.
5.2.1.4 TRIPLES
In triples representation, the use of temporary variables is avoided & instead reference
to instructions are made
So three address statements can be represented by records with only there fields OP,
arg1 & arg2.
Since, there fields are used this intermediated code formal is known as triples
Advantages
No need to use temporary variable which saves memory as well as time
Disadvantages
Triple representation is difficult to use for optimizing compilers
Because for optimization statements need to be suffled.
for e.g. statement 1 can be come down or statement 2 can go up ect.
So the reference we used in their representation will change.
EXAMPLE 1
a+b*c|e^f+b*a
t1 = e ^ f
t2 = b * c
t3 = t2 / t1
t4 = b * a
t5 = a + t3
t6 = t5 + t4
21
CS304 Compiler Design /B.Tech/S6
EXAMPLE 2
A ternary operation like x[i] : = y requires two entries in the triple structure while x : = y[i] is
naturally represented as two operations.
x[i] := y x := y[i]
INDIRECT TRIPLES
This representation is an enhancement over triple representation.
It uses an additional instruction array to led the pointer to the triples in the desired
order.
Since, it uses pointers instead of position to stage reposition the expression to produce
an optimized code.
EXAMPLE 1
22
CS304 Compiler Design /B.Tech/S6
Comparison
When we ultimately produce the target code each temporary and programmer
defined name will assign runtime memory location
This location will be entered into symbol table entry of that data.
Using the quadruple notation, a three address statement containing a temporary can
immediately access the location for that temporary via symbol table.
With quadruple notation, statements can often move around which makes
optimization easier.
This is achieved because using quadruple notation the symbol table interposes high
degree of indirection between computation of a value and its use.
But with triples, moving a statement that defines a temporary value requires us to
change all references to that statement in arg1 and arg2 arrays. This makes triples
difficult to use in optimizing compiler
Space Utilization
Quadruples and indirect triples requires same amount of space for storage (normal
case).
But if same temporary value is used more than once indirect triples can save some
space. This is bcz, 2 or more entries in statement array can point to the same line of
op-arg1-arg2 structure.
Quadruples
direct access of the location for temporaries
easier for optimization
Triples
space efficiency
Indirect Triples
easier for optimization
space efficiency
23
CS304 Compiler Design /B.Tech/S6
PROBLEM 1
a=b*-c+b*-c
Sol : - Three address code for given expression is
TAC
t1 = uniminus c
t2 = b* t1
t3 = uniminus c
t4 = b* t3
t5 = t2 + t4
Q = t5
QUADRUPLES
Location OP arg1 arg2 result
(0) uniminus c t1
(1) * b t1 t2
(3) uniminus c t3
(4) * b t3 t4
(5) + t2 t4 t5
(6) = t5 a
TRIPLES
Location OP arg1 arg2
(1) uniminus c
(2) * b (1)
(3) uniminus c
(4) * b (3)
(5) + (2) (4)
(6) = a (5)
INDIRECT TRIPLES
24
CS304 Compiler Design /B.Tech/S6
if p ≠ nil then
emit( p ‘ : =’ E.place)
else error }
if p ≠ nil then
E.place : = p
else error }
25
CS304 Compiler Design /B.Tech/S6
EXAMPLE : Annotated Parse Tree For Generation Of TAC For Assignment Statements
26
CS304 Compiler Design /B.Tech/S6
But more often they are used as conditional expressions in statements that alter
the flow of control, such as if-then-else, or while-do statements.
Boolean expressions are composed of the Boolean operators (and, or, and not) applied
to elements that are Boolean variables or relational expressions.
Relational expressions are of the form E1 relop E2, where E1 and E2 are arithmetic
expressions and relop can be <, <=, =!, =, > or >=
EXAMPLE
The translation for a or b and not c will result following three-address sequence
t1 : = not c
t2 : = b and t1
t3 : = a or t2
27
CS304 Compiler Design /B.Tech/S6
where the function emit( ) output the three address statement into the output file and
nextstat( ) gives the index of the next three address statement in the output sequence
and emit increments nextstat after producing each three address statement.
if a < b then 1 else 0 which can be translated into the three-address code sequence (let
101 t : = 0
103 t : = 1
104
This is normally used for flow-of-control statements, such as the if-then, if-then-else
and while-do statements those generated by the following grammar:
28
CS304 Compiler Design /B.Tech/S6
S → if E then S1
| if E then S1 else S2
| while E do S1
S → if E then S1
| if E then S1 else S2
| while E do S1
With each E we associate two labels E.true and E.false. E.true is the label to which
control flows if E is true, and E.false is the label to which control flows if E is false.
The inherited attribute S.next is a label that is attached to the first three-address
instruction to be executed after the code for S and another inherited attribute S.begin
is the first instruction of S
29
CS304 Compiler Design /B.Tech/S6
E.false := S.next;
S1.next := S.next;
E.false := newlabel;
S1.next := S.next;
S2.next := S.next;
E.true := newlabel;
E.false := S.next;
S1.next := S.begin;
**********
30