0% found this document useful (0 votes)
30 views97 pages

CSE-303 Chapter-06 Final

Chapter 6 discusses intermediate code generation, focusing on syntax trees, directed acyclic graphs (DAGs), and three-address code. It explains how DAGs can efficiently represent common subexpressions and outlines the structure of three-address instructions, including their various forms and representations such as quadruples and triples. The chapter provides examples to illustrate the concepts, including the construction of DAGs and the translation of expressions into three-address code.

Uploaded by

Shahadat Hossain
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views97 pages

CSE-303 Chapter-06 Final

Chapter 6 discusses intermediate code generation, focusing on syntax trees, directed acyclic graphs (DAGs), and three-address code. It explains how DAGs can efficiently represent common subexpressions and outlines the structure of three-address instructions, including their various forms and representations such as quadruples and triples. The chapter provides examples to illustrate the concepts, including the construction of DAGs and the translation of expressions into three-address code.

Uploaded by

Shahadat Hossain
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 97

Chapter-06

Intermediate-Code Generation

Slide Courtesy: Moumita Sarker | Modified by: Zinia Sultana 20


21
Outline
 Variants of Syntax Trees
 Directed Acyclic Graphs for Expressions
 The Value-Number Method for Constructing DAG's
 Three-Address Code
 Addresses and Instructions
 Quadruples
 Triples
 Static Single-Assignment Form
 Types and Declarations
 Type Expressions
 Type Equivalence
 Declarations
 Storage Layout for Local Names
 Sequences of Declarations
 Translation of Expressions
Introduction
Variants of Syntax Trees
Variants of Syntax Trees
• Nodes in a syntax tree represent constructs in the source program
• The children of a node represent the meaningful components of a construct
• A directed acyclic graph (hereafter called a DAG) for an expression
identifies the common subexpressions (subexpressions that occur more
than once) of the expression
• As we shall see, DAG’s can be constructed by using the same techniques that
construct syntax trees
Directed Acyclic Graphs for Expressions
• Like the syntax tree for an expression, a DAG has leaves corresponding to
atomic operands and interior nodes corresponding to operators
• The difference is that a node N in a DAG has more than one parent if N
represents a common subexpression
• In a syntax tree, the tree for the common subexpression would be replicated
as many times as the subexpression appears in the original expression
• Thus, a DAG not only represents expressions more succinctly, it gives the
compiler important clues regarding the generation of efficient code to
evaluate the expressions
Example 6.1
Figure shows the Syntax Tree and DAG for the expression, a + a*(b−c) + (b−c)*d

+ +

+ * + *
_ d
a d
* *
a _ b c a _

b c b c
Syntax Tree DAG
Example 6.1 (Cont…)
+
• The leaf for ‘a’ has two parents, because ‘a’
appears twice in the expression + *
• More interestingly, the two occurrences of
the common subexpression ‘b−c’ are
represented by one node, the node labeled d
‘−’ *
a _

b c
DAG
Example 6.1 (Cont…)
+
• That node has two parents,
representing its two uses in the + *
subexpressions ‘a∗(b−c)’ and
‘(b−c)∗d’ d
*
• Even though ‘b’ and ‘c’ appear twice in
the complete expression, their nodes a _
each have one parent, since both uses
are in the common subexpression ‘b−c’
b c
DAG
Example 6.1(Cont…)
The SDD of figure can construct either syntax trees or DAG’s
Example 6.2
The sequence of steps shown in figure constructs the DAG
a + a*(b−c) + (b−c)*d
1) p1 = Leaf p1
(id, entry-a)
+ 2) p2 = Leaf (id, entry-a) = p1
3) p3 = Leaf (id,
p1 entry-b)
4) p4 = Leaf (id, entry-c)
+ * 5) p5 = Node (‘−’, p3 , p4)
6) p6 = Node (‘*’, p1 , p5)
d 7) p7 = Node (‘+’, p1 , p6)

* 8) p8 = Leaf (id, entry-b) = p3


9) p9 = Leaf (id, entry-c) = p4
a _ 10) p10 = Node (‘−’, p3 , p4) = p5
11) p11 = Leaf (id, entry-d)
12) p12 = Node (‘*’, p5 , p11)
b c 13) p13 = Node (‘+’, p7 , p12)

DAG Steps for Constructing DAG


The Value-Number Method for Constructing DAG’s
• Often, the nodes of a syntax tree or DAG are stored in an array of records
• 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

op field other field

Syntax Tree or DAG Node Representation as a Record


The Value-Number Method for Constructing DAG’s (Cont…)

• Leaves have one additional field, which holds the lexical value (either a
symbol-table pointer or a constant, in this case)

op field val field

Syntax Tree or DAG Node for a Leaf Node


The Value-Number Method for Constructing DAG’s (Cont…)

• Interior nodes have two additional fields indicating the left and right children

op field left child right child

Syntax Tree or DAG Node for an Interior Node with two children
The Value-Number Method for Constructing DAG’s (Cont…)

• In the 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
The Value-Number Method for Constructing DAG’s (Cont…)
DAG for i = i + 10

1 id to entry for i
=
2 num 10
3 + 1 2
+
4 = 1 3
i 10 5 …

(a) DAG (b) Array

Nodes of a DAG for i = i + 10 allocated in an array


Algorithm 6.3
The Value-Number Method for Constructing DAG’s (Cont…)
Three-Address Code
Three-Address Code
• In three-address code, there is at most one operator on the right side of an
instruction
• Thus a source-language expression like ‘x + y ∗ z’ might be translated into
the sequence of three-address instructions
• t1 = y ∗ z
• t2 = x + t1
where t1 and t2 are compiler-generated temporary names
• Three-address code is a linearized representation of a syntax tree or a DAG
in which explicit names correspond to the interior nodes of the graph
Example 6.4
Figure shows the DAG and Three-Address Code for the expression,
a + a*(b−c) + (b−c)*d
p1
+
t1 = b − c p1

t2 = a * t1
+ *
t3 = a + t2
* t4 = t1 * d
a _
d
t5 = t3 + t4

b c

(a) DAG (b) Three-Address Code

A DAG and its Corresponding Three-Address Code


Addresses and Instructions
• Three-address code is built from two concepts: addresses and instructions
• An address can be one of the following:
• Name
• a = b + c where a, b and c are source program names used as addresses
• Constant
• a = 10 + 20 where 10 and 20 are constants used as addresses
• Compiler-generated temporary
• t1 = t2 + t3 where t1, t2 and t3 are compiler-generated temporary used as
addresses
Addresses and Instructions (Cont…)

A list of the common three-address instruction forms:


 Assignment instructions of the form x = y op z, where op is a binary
arithmetic or logical operation, and x, y, and z are addresses
For example: a = b + c
 Assignments of the form x = op y, where op is a unary operation including
unary minus, logical negation, shift operators, and conversion operators
that, for example, convert an integer to a floating-point number
For example: a = − c ; a = (float) c
Addresses and Instructions (Cont…)

 Copy instructions of the form x = y, where x is assigned the value of y


For example, a = b
 An unconditional jump goto L where the three-address instruction with
label L is the next to be executed
 Conditional jumps of the form if x goto L and ifFalse x goto L
 These instructions execute the instruction with label L next if x is true and
false, respectively
 Otherwise, the following three-address instruction in sequence is
executed next, as usual
Addresses and Instructions (Cont…)

 Conditional jumps such as if x relop y goto L, which apply a relational


operator (<, ==, >=, etc.) to x and y, and execute the instruction with label L
next if x stands in relation relop to y. If not, the three-address instruction
following if x relop y goto L is executed next, in sequence
 Procedure calls and returns are implemented using the following
instructions:
 param x for parameters
 call p,n for procedure calls
 y = call p,n for function calls
 return y, where y representing a returned value is optional
Addresses and Instructions (Cont…)
Example: call of the procedure
p(X1 , X2 ,..., Xn)
The sequence of three-address instructions will be,
param X1
param X2
...
param Xn
call p,n
The integer n, indicating the number of actual parameters in call p,n, is not
redundant because calls can be nested. That is, some of the first param statements
could be parameters of a call that comes after p returns its value. That value
becomes another parameter of the later call.
Example 1 of Procedure Calls:

• Suppose that a is an array of integers


• f is a function from integers to integers
• Then, the n = f(a[i]) assignment translate into the following three-address
code:
1) t1 = i * 4
2) t2 = a [ t1 ]
3) param t2
4) t3 = call f, 1
5) n = t3
Example 2 of Procedure Calls:
• Now let us suppose we need to execute the nested procedure call
• Then, the n = f(a,g(a)) assignment translate into the following three-address
code:

param a
t1 = call g, 1
param t1
t2 = call f, 2
n = t2
Addresses and Instructions (Cont…)
 Indexed copy instructions of the form x = y[i] and x[i] = y
 The instruction x = y[i] sets x to the value in the location i memory units
beyond location y
 The instruction x[i] = y sets the contents of the location i units beyond x to
the value of y
Addresses and Instructions (Cont…)

 Address and pointer assignments of the form x = &y, x = ∗y and ∗x = y


 The instruction x = &y sets the r-value of x to be the location (l-value) of y
 Presumably y is a name and x is a pointer name
 In the instruction x = ∗y, presumably y is a pointer whose r-value is a
location
 The r-value of x is made equal to the contents of that location
 Finally ∗x = y sets the r-value of the object pointed to by x to the r-value
of y
Example 6.5
• Consider the statement
do i = i+1; while (a[i] < v);
• Two possible translations of this statement are shown in figure

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

(a) Symbolic Labels (b) Position Numbers

Two Ways of Assigning Labels to Three-Address Statements


Quadruples
• The description of three-address instructions specifies the components of
each type of instruction
• But it does not specify the representation of these instructions in a data
structure
• In a compiler, these instructions can be implemented as objects or as
records with fields for the operator and the operands
• Three such representations are called “quadruples,” “triples”, and “indirect
triples”
Quadruples (Cont…)
• A quadruple (or just “quad”) has four fields, which we call op, arg1, arg2, and
result
• The op field contains an internal code for the operator
• For instance, the three-address instruction x = y + z is represented by placing
+ in op, y in arg1, z in arg2, and x in result

op arg1 arg2 result

+ y z x
Quadruples (Cont…)
The following are some exceptions to this rule:
• Instructions with unary operators like x = minus y or x = y do not use arg2

op arg1 arg2 result

minus y x
Quadruples (Cont…)

The following are some exceptions to this rule:


• For a copy statement like x = y, op is =, while for most other operations, the
assignment operator is implied

op arg1 arg2 result

= y x
Quadruples (Cont…)
The following are some exceptions to this rule:
• Operators like param use neither arg2 nor result. For example, param x

op arg1 arg2 result

param x
Quadruples (Cont…)

The following are some exceptions to this rule:


• Conditional and unconditional jumps put the target label in result
• For example, goto L

op arg1 arg2 result

goto L
Quadruples (Cont…)
The following are some exceptions to this rule:

• Conditional and unconditional jumps put the target label in result


• For example, if x goto L

op arg1 arg2 result

goto x L
Quadruples (Cont…)
The following are some exceptions to this rule:
• Conditional and unconditional jumps put the target label in result
• For example, if x < y goto L

op arg1 arg2 result

< x y t1

goto t1 L
Example 6.6
Three-Address Code and Quadruples for the expression, a = b * -c + b * -c

op arg1 arg2 result


t1 = minus c 0 minus c t1
t2 = b * t1 1 * b t1 t2
t3 = minus c 2 minus c t3
t4 = b * t3 3 * b t3 t4
t5 = t 2 + t4 4 + t2 t4 t5
5 = t5 a
a = t5

(a) Three-Address Code (b) Quadruples
A Three-Address Code and its Corresponding Quadruples
Triples
• A triple has only three fields, which we call op, arg1, arg2
• Using triples, we refer to the result of an operation x op y by its position,
rather than by an explicit temporary name
• Thus, instead of the temporary t1 a triple representation would refer to
position (0)
• Parenthesized numbers represent pointers into the triple structure itself

op arg1 arg2
Example 6.7
Syntax Tree and Triples for the expression, a = b * -c + b * -c
op arg1 arg2
=
0 minus c
a + 1 * b (0)
2 minus c
* 3 * b (2)
*
4 + (1) (3)
b minus b 5 = a (4)
minus

c c
(a) Syntax Tree (b) Triples
A Syntax Tree and its Corresponding Triples
Triples (Cont…)
• In the triple representation in (b), the copy statement a = t5 is encoded in the
triple representation by placing a in the arg1 field and (4) in the arg2 field

op arg1 arg2

5 = a (4)
Triples (Cont…)
• A ternary operation like x[i] = y requires two entries in the triple structure
• For example, we can put x and i in one triple and y in the next

op arg1 arg2
0 * i 4
1 + x (0)
2 = (1) y
Triples (Cont…)
• Similarly, x = y[i] can implemented by treating it as if it were the two
instructions t = y[i] and x = t, where t is a compiler-generated temporary
• Note that the temporary t does not actually appear in a triple, since
temporary values are referred to by their position in the triple structure

op arg1 arg2

0 * i 4
1 + y (0)
2 = x (1)
Benefit of Quadruples over Triples
• A benefit of quadruples over triples can be seen in an optimizing compiler,
where instructions are often moved around
• With quadruples, if we move an instruction that computes a temporary t, then
the instructions that use t require no change
• With triples, the result of an operation is referred to by its position, so moving
an instruction may require us to change all references to that result. This
problem does not occur with indirect triples, which we consider next.
Benefit of Quadruples over Triples (Cont…)
Before Optimizing,
t1 = itof (60)
t2 = a * t 1
t3 = t2 + 40
op arg1 arg2 result op arg1 arg2
0 itof 60 t1 0 itof 60
1 * a t1 t2 1 * a (0)
2 + t2 40 t3 2 + (1) 40
Quadruples Triples
Benefit of Quadruples over Triples (Cont…)
After Optimizing,
t2 = a * 60.0
t3 = t2 + 40

op arg1 arg2 result op arg1 arg2


0 * a 60.0 t2 0 * a 60.0
1 + t2 40 t3 1 + (0) 40

Quadruples Triples
Indirect Triples

• Indirect triples overcomes the limitation of triples


• It consists of a listing of pointers to triples, rather than a listing of triples
themselves
• For example, let us use an array instruction to list pointers to triples in the
desired order
• With indirect triples, an optimizing compiler can move an instruction by
reordering the instruction list, without affecting the triples themselves
Indirect Triples(Cont…)
The triples in (b) might be represented as in this figure
op arg1 arg2 instruction op arg1 arg2
0 minus c (0) 0 minus c
1 * b (0) (1) 1 * b (0)
2 minus c (2) 2 minus c
3 * b (2) (3) 3 * b (2)
4 + (1) (3) (4) 4 + (1) (3)
5 = a (4) (5) 5 = a (4)
… … …

(b) Triples Indirect Triples Representation


Use of Indirect Triples by an Optimized Compiler

Before Optimizing, After Optimizing,


t1 = itof (60) t2 = a * 60.0
t2 = a * t 1 t3 = t2 + 40
t3 = t2 + 40

(0) op arg1 arg2 (1) op arg1 arg2

(1) 0 itof 60 (2) 1 * a 60.0

(2) 1 * a (0) … 2 + (1) 40

… 2 + (1) 40 3 …

Indirect Triples Indirect Triples


Static Single-Assignment Form (SSA)

• Static single-assignment form (SSA) is an intermediate representation that


facilitates certain code optimizations
• Two distinctive aspects distinguish SSA from three-address code
• The first is that all assignments in SSA are to variables with distinct names
• Hence the term static single-assignment
Static Single-Assignment Form (Cont…)
• Following shows the same intermediate program in three-address code and in
static single assignment form
• Note that subscripts distinguish each definition of variables p and q in the SSA
representation
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

(a) Three-Address Code (b) Static Single-Assignment Form


Intermediate Program in Three-Address Code and SSA
Static Single-Assignment Form (Cont…)
• The same variable may be defined in two different control-flow paths in a
program
• For example, the source program
if ( flag ) x = -1; else x = 1;
y = x * a;
has two control-flow paths in which the variable x gets defined
• If we use different names for x in the true part and the false part of the
conditional statement, then which name should we use in the assignment y
= x * a?
Static Single-Assignment Form (Cont…)
• Here is where the second distinctive aspect of SSA comes into play
• SSA uses a notational convention called the φ-function to combine the two
definitions of x:
if ( flag ) x1 = -1; else x2 = 1;
x3 = φ(x1, x2)
y = x3* a;
• Here, φ(x1, x2) has the value x1 if the control flow passes through the true
part of the conditional and the value x2 if the control flow passes through
the false part.
• That is to say, the φ-function returns the value of its argument that
corresponds to the control-flow path that was taken to get to the
assignment statement containing the φ-function
Practice Problem-1
Expression: (( x + y ) – (( x + y ) * ( x – y ))) + (( x + y ) * ( x – y))
• Construct for the above expression by maintaining precedency
• Syntax Tree
• DAG
• Allocate the Nodes of the DAG in an Array by using Value-Number Method
• Three-Address Code
• Quadruples
• Triples
• Indirect Triples
• SSA
Types and Declarations
Types and Declarations
• The applications of types can be grouped under checking and translation
• Type checking uses logical rules to reason about the behavior of a
program at run time
• Specifically, it ensures that the types of the operands match the type
expected by an operator
• For example, the && operator in Java expects its two operands to be
booleans and the result is also of type Boolean
Types and Declarations(Cont…)
• The applications of types can be grouped under checking and translation
• Translation Applications: From the type of a name, a compiler can
determine the storage that will be needed for that name at run time
• Type information is also needed to calculate the address denoted by an
array reference, to insert explicit type conversions etc.
Type Expressions
• Types have structure, which we shall represent using type expressions
• A type expression is either a basic type or is formed by applying an operator
called a type constructor to a type expression
• The sets of basic types and constructors depend on the language to be
checked
Example 6.8

• In C, the type int [2][3] can be read as, “array of 2 arrays of 3 integers”
• The corresponding type expression array(2,array(3,integer)) is represented
by the tree in figure

• The operator array takes two parameters, a number and a type


• If types are represented by trees, then this operator returns a tree node labeled
array with two children for a number and a type
Type Expressions (Cont…)
• We shall use the following definition of type expressions:
• A basic type is a type expression
• Typical basic types for a language include boolean, char, integer, float, and
void
• “void” denotes “the absence of a value”
• All these are examples of basic types
float x; //Type Expression: float
int i; //Type Expression: int
float m; //Type Expression: float
Type Expressions (Cont…)
• We shall use the following definition of type expressions:
• A type name is a type expression
• A type expression can be formed by applying the array type constructor
to a number and a type expression
• All these are examples of array type constructor applied to a number and a
type expression
array int[2]; //Type Expression: array(2,int)
array float[2][3]; //Type Expression: array(2,array(3,float))
array float[2][3][4]; //Type Expression: array(2,array(3,array(4,float)))
Type Expressions (Cont…)

• We shall use the following definition of type expressions:


• A record is a data structure with named fields
• A type expression can be formed by applying the record type
constructor to the field names and their types
• The use of a name x for a field within a record does not conflict with other
uses of the name outside the record
• Thus, the three uses of x in the following declarations are distinct and do
not conflict with each other:
float x; //Type Expression: float
struct {float x; float y;} p; //Type Expression: record(x:float,y:float)
struct {int t; float x; float y;} q; //Type Expression: record(t:int,x:float,y:float)
Type Expressions (Cont…)
• We shall use the following definition of type expressions:
• A type expression can be formed by using the type constructor → for
function types
• We write s → t for “function from type s to type t”
• Here the functions map one type expression to the other

function int f(float x); Type Expression: float → int

function float g(int a, float b, int c);


Type Expression: int × float × int → float
Type Expressions (Cont…)
• We shall use the following definition of type expressions:
• If s and t are type expressions, then their Cartesian product s×t is a type
expression
• They can be used to represent function parameters
• We assume that × associates to the left and that it has higher precedence
than →
• Type expressions may contain variables whose values are type
expressions
Type Expressions (Cont…)
• A convenient way to represent a type →
expression is to use a graph
• Example: Type expression for
function float g(int a, float b, int c); X float
is int × float × int → float
• It can be represented by generating X int
expression tree like below
• Interior Nodes: type constructor
• Leaves: basic types, types names and type int float
variables
Type Equivalence
• When are two type expressions equivalent?
• Many type-checking rules have the form, “if two type expressions are equal
then return a certain type else error.”
• Two types can be either
• Structurally Equivalent or
• Name Equivalent
Type Equivalence (Cont…)

• When type expressions are represented by graphs, two types are structurally
equivalent if and only if one of the following conditions is true:
• They are the same basic type
• They are formed by applying the same constructor to structurally
equivalent types
• One is a type name that denotes the other
• If type names are treated as standing for themselves, then the first two
conditions in the above definition lead to name equivalence of type
expressions
Name Equivalence
• Name Equivalence: two types are equal if and only if they have the same
name
• Thus, for example in the code (using C syntax)
struct ST{ struct T{
int a; int a;
float b; float b;
}X,Y; }M,N;
Name Equivalence (Cont…)
struct ST{ struct T{
int a; int a;
float b; float b;
}X,Y; }M,N;

• If name equivalence is used in the language then


• X and Y would be of the same type and
• M and N would be of the same type but
• The type of X or Y would not be equivalent to the type of M or N
• This means that statements such as:
• X = Y and M = N would be valid but
• X = M would not be valid (would not be accepted by a translator)
Structural Equivalence

• Structural Equivalence: two types are equal if and only if, they have the
same structure which can be interpreted in different ways
• A strict interpretation would be that the names and types of each
component of the two types must be the same and must be listed in the
same order in the type definition
• A less stringent requirement would be that the component types must be
the same and in the same order in the two types, but the names of the
components could be different
Structural Equivalence (Cont…)
struct ST{ struct T{
int a; int a;
float b; float b;
}X,Y; }M,N;

• Again looking at the example above using structural equivalence the two
types ST and T would be considered equivalent which means that a translator
would accept statements such as X = M
• Note that C doesn't support structural equivalence for struct and classes and
will give error for above assignment
Declarations

• Following grammar consisting of types and declarations that declares just


one name at a time
Declarations (Cont…)

• Nonterminal D generates a sequence of declarations


• Nonterminal T generates basic, array or record types
• Nonterminal B generates one of the basic types int and float
Declarations (Cont…)
• Nonterminal C for “component”
generates strings of zero or more
integers and each integer surrounded
by brackets
• An array type consists of a basic type
specified by B followed by array
components specified by nonterminal
C
• A record type (the second production
for T) is a sequence of declarations for
the fields of the record and all
surrounded by curly braces
Practice Problem-2

• For the grammar given above, construct parse tree for the following input
strings:
• int a; float b;
• int [3] [4] a;
• record { int a; float b; int [3] [4] a; }
Practice Problem-3

• Modify the grammar given above so that it can construct parse tree for
declarations with list of names and then construct parse tree for the following
input
• record { int a, b; int [3] [4] a; }
[Hint: Use Example 5.10]
Storage Layout for Local Names
• From the type of a name, we can determine the amount of storage that will be
needed for the name at run time
• At compile time, we can use these amounts to assign each name a relative
address
• The type and relative address are saved in the symbol-table entry for the
name
• Data of varying length, such as strings or data whose size cannot be
determined until run time, such as dynamic arrays is handled by reserving a
known fixed amount of storage for a pointer to the data
Storage Layout for Local Names (Cont…)
• Suppose storage comes in blocks of contiguous bytes where byte is the
smallest unit of addressable memory
• Typically a byte is eight bits, and some number of bytes form a machine word
• Multibyte objects are stored in consecutive bytes and given the address of the
first byte
• The width of a type is the number of storage units needed for objects of that
type
Storage Layout for Local Names (Cont…)
• The syntax directed translation scheme (SDT) in figure computes types and
their widths for basic and array types

1) T→ B { t = B.type; w = B.width; }
C { T.type = C.type; T.width = C.width; }
2) B→ int { B.type = integer; B.width = 4; }
3) B→ float { B.type = float; B.width = 8; }
4) C→ ϵ { C.type = t; C.width = w; }
5) C→ [num] C1 { C.type = array(num.value, C1.type);
C.width = num.value X C1.width; }
Computing types and their width
Example 6.9 (Cont…) T

SDT of Array Types for int [2] [3]


B C

int
[ 2 ] C

[ 3 ] C

Parse Tree for int [2] [3]


Example 6.9 (Cont…) T

SDT of Array Types for int [2] [3]


C
B type= integer
width= 4
int [ 2 ]
C

[ 3 ] C
ϵ
Example 6.9 (Cont…) T
t= integer
SDT of Array Types for int [2] [3]
w= 4 C
B type= integer
width= 4
int [ 2 ]
C

[ 3 ] C
ϵ
Example 6.9 (Cont…) T
t= integer
SDT of Array Types for int [2] [3]
w= 4 C
B type= integer
width= 4
int [ 2 ]
C

[ 3 ] C type= integer
width= 4
ϵ
Example 6.9 (Cont…) T
t= integer
SDT of Array Types for int [2] [3]
w= 4 C
B type= integer
width= 4
int [ 2 ] type= array(3, integer)
C width= 12

[ 3 ] C type= integer
width= 4
ϵ
T
Example 6.9 (Cont…)
t= integer
SDT of Array Types for int [2] [3]
w= 4
B type= integer
width= 4
int type= array(2, array(3, integer))
C width= 24
[ 2 ] type= array(3, integer)
C width= 12

[ 3 ] C type= integer
width= 4
ϵ
T
Example 6.9 (Cont…) type= array(2, array(3, integer))
t= integer width= 24
SDT of Array Types for int [2] [3]
w= 4
B type= integer
width= 4
int type= array(2, array(3, integer))
C width= 24
[ 2 ] type= array(3, integer)
C width= 12

[ 3 ] C type= integer
width= 4
ϵ
Syntax-directed translation of array types
Comparison of Example 6.9 and Example 5.13
Sequences of Declarations

• Languages such as C and Java allow all


the declarations in a single procedure
to be processed as a group
• We can use a variable say offset to
keep track of the next available
relative address
• The translation scheme of figure deals
with a sequence of declarations of the
form T id where T generates a type as
in previous figure
Sequences of Declarations (Cont…)

 The initialization of offset is more evident if the first production appears


on one line as:
P→ {offset=0;} D
 Nonterminals generating ϵ, called marker nonterminals can be used to
rewrite productions so that all actions appear at the ends of right sides
 Using a marker nonterminal M the previous equation can be restated as:
P → M D
M → ϵ {offset = 0;}
Translation of Expressions
Three-address code for expressions - SDD
Task-1: Draw
Annotated parse
tree for a= b + -c
and find S.code
Incremental Translation - SDT

Task-2: Draw
Annotated parse
tree for a= b + -c
and output the
three address
code.
Translation of Array References - SDT

Task-3: Draw Annotated parse


tree for C + A[i][j] and Three-
Address code considering A is
an array declaration of 2X3.
Practice

• Use the Translation of Array References for the following assignment to


generate Three-address code.
• X = a[i] + b[j]
• X = a[i][j] + b[i][j]
End

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy