Post on 02-Jun-2018
8/10/2019 Compiler Construction Chapter 6
1/111
Chapter 6: Semantic Analysis
1
8/10/2019 Compiler Construction Chapter 6
2/111
(Static) Semantic Analyzer
==> Semantic Structure
- What is the program supposed to do?
- Semantics analysis can be done during syntax analysis
phase or the final code generation phase.
- typical static semantic features include declarations and
type checking.
- information (attributes) gathered can be either added tothe tree as annotations or entered into the symbol table.
2
8/10/2019 Compiler Construction Chapter 6
3/111
8/10/2019 Compiler Construction Chapter 6
4/111
Output of the semantic analyzer annotated AST
with subscripts from a range
4
8/10/2019 Compiler Construction Chapter 6
5/111
Two Categories of Semantic Analysis
1. The analysis of a program to meet the
definition of the programming language.
2. The analysis of a program to enhance the
efficiency of execution of the translatedprogram.
5
8/10/2019 Compiler Construction Chapter 6
6/111
Semantic Analysis Process
includes formally:
- description of the analyses to perform- implementation of the analysis (translation of
the description) that may use appropriatealgorithms.
6
8/10/2019 Compiler Construction Chapter 6
7/111
Description of Semantic Analysis
1. Identify attributes (properties) of language(syntactic) entities.
2. Write attribute equations (or semantic rules) thatexpress how the computation of such attributesis related to the grammar rules of the language.
Such a set of attributes and equations is called anattribute grammar.
7
8/10/2019 Compiler Construction Chapter 6
8/111
Syntax-directed semantics
-
The semantic content of a program is closelyrelated to its syntax.
- All modern languages have this property.
8
8/10/2019 Compiler Construction Chapter 6
9/111
Attributes
- An attribute is any property of a programming
language construct.- Typical examples of attributes are:
the data type of a variable, the value of anexpression, the location of a variable in memory,
the object code of a procedure, the number ofsignificant digits in a number.
- Attribute corresponds to the name of a field of astructure.
9
8/10/2019 Compiler Construction Chapter 6
10/111
Attribute Grammars
In syntax-directed semantics, attributes areassociated with grammar symbols of thelanguage. That is, if X is a grammar symbol anda is an attribute associated to X, then we writeX.a for the value of a associated to X.
For each grammar rule X0-> X1 X2 Xn thevalues of the attributes Xi.aj of each grammarsymbol Xi are related to the values of theattributes of other grammar symbols in the rule.
10
8/10/2019 Compiler Construction Chapter 6
11/111
That is, each relationship is specified by an
attribute equation or semantic rule of the form:
Xi.aj = fij (X0.a1 ,.., X0.ak ,.., X1.a1 ,.., X1.ak , .., Xn.a1
,.., Xn.a
k )
An attribute grammar for the attributes a1,,ak isthe collection of all such attribute equations
(semantic rules), for all the grammar rules of thelanguage.
11
8/10/2019 Compiler Construction Chapter 6
12/111
number.val must be
computed prior to
factor.val
12
8/10/2019 Compiler Construction Chapter 6
13/111
Attribute grammars may involve severalinterdependent attributes.
13
8/10/2019 Compiler Construction Chapter 6
14/111
e.g. 345o
128d
128o (x)
based-num -> num basecharbasechar -> o | dnum -> num digit | digitdigit -> o | 1 | 2 | 3 | 4 | 5 | 6 | 7 8 | 9
8/10/2019 Compiler Construction Chapter 6
15/111
8/10/2019 Compiler Construction Chapter 6
16/111
Attribute grammars may be defined fordifferent purposes.
16
8/10/2019 Compiler Construction Chapter 6
17/111
17
8/10/2019 Compiler Construction Chapter 6
18/111
*
- 42
334
(34 3) * 42
term1.tree = mkOpNode(*,term2.tree,factor.tree)
factor.tree =
mkNumNode(number.lexval)
8/10/2019 Compiler Construction Chapter 6
19/111
Algorithms for attribute computation
Dependency graph and evaluation order
19
8/10/2019 Compiler Construction Chapter 6
20/111
Attribute grammar for simple C-like variable declarations
Grammar Rules Semantic Rules
decl type var-list var-list.dtype = type.dtype
type int type.dtype = integer
type float type.dtype = real
var-list1 id , var-list2 id.dtype = var-list1.dtypevar-list2.dtype = var-list1.dtype
var-list id id.dtype = var-list.dtype
8/10/2019 Compiler Construction Chapter 6
21/111
decl
type
(dtype = real)
float
var-list(dtype = real)
id , var-list(x)
(dtype = real)(dtype = real)
id(y)
(dtype = real)Parse tree for the stringfloat x , y
8/10/2019 Compiler Construction Chapter 6
22/111
8/10/2019 Compiler Construction Chapter 6
23/111
8/10/2019 Compiler Construction Chapter 6
24/111
decl
type
(dtype = real)
float
var-list(dtype = real)
id , var-list(x)
(dtype = real)(dtype = real)
id(y)
(dtype = real)Parse tree for the stringfloat x , y
trivialdependency
8/10/2019 Compiler Construction Chapter 6
25/111
8/10/2019 Compiler Construction Chapter 6
26/111
26
8/10/2019 Compiler Construction Chapter 6
27/111
27
8/10/2019 Compiler Construction Chapter 6
28/111
8/10/2019 Compiler Construction Chapter 6
29/111
29
8/10/2019 Compiler Construction Chapter 6
30/111
30
8/10/2019 Compiler Construction Chapter 6
31/111
base is computed inpreorder and val inpostorder
8/10/2019 Compiler Construction Chapter 6
32/111
Synthesized Attributes
An attribute a is synthesized if, given a grammar ruleA -> X1 X2 Xn, the only associated attribute equation
with an a on the left-hand side is of the form:A.a = f (X1.a1 ,.., X1.ak ,.., Xn.a1 ,.., Xn.ak)
e.g., E1 -> E2 + E3 {E1.val = E2.val + E3.val; }where E.val represents the attribute (numerical value
obtained) for EAn attribute grammar in which all the attributes aresynthesized is called S-attributed grammar.
32
8/10/2019 Compiler Construction Chapter 6
33/111
S-attributedgrammar
33
8/10/2019 Compiler Construction Chapter 6
34/111
*
- 42
334
(34 3) * 42
term1.tree = mkOpNode(*,term2.tree,factor.tree)
factor.tree =
mkNumNode(number.lexval)
*
-
34 3
42
8/10/2019 Compiler Construction Chapter 6
35/111
8/10/2019 Compiler Construction Chapter 6
36/111
Inherited Attributes
An attribute that is not synthesized is calledan inherited attribute.
36
8/10/2019 Compiler Construction Chapter 6
37/111
Preorder /Preorder & Inordertraversal
8/10/2019 Compiler Construction Chapter 6
38/111
Computation of Attributes During
Parsing
L-attributed grammars
38
8/10/2019 Compiler Construction Chapter 6
39/111
-- LALR(1) parser are primarily suited to
handling synthesized attributes.
-- Two stacks are required.
value stack and parsing stack
Computing Synthesized Attributes During
LR Parsing
39
E : E + E { $$ = $1 + $3} // Yacc specification
8/10/2019 Compiler Construction Chapter 6
40/111
E : E E { $$ $1 $3} // Yacc specification
Parsingstack
Valuestack
40
8/10/2019 Compiler Construction Chapter 6
41/111
41
8/10/2019 Compiler Construction Chapter 6
42/111
Translation (Attribute Computation)
A translation scheme is merely a context-free
grammar in which a program fragment calledsemantic action is associated with eachproduction.
42
8/10/2019 Compiler Construction Chapter 6
43/111
e.g. A -> XYZ { }
In a bottom up parser the semantic actions is taken when XYZ is reduced to A. In a top-down parser the action is taken when A, X,Y, or Z is expanded, whichever is appropriate.
43
8/10/2019 Compiler Construction Chapter 6
44/111
Semantic Action
In addition to those stated before, the semantic
action may also involve:1. the computation of values for variables
belonging to the compiler.
2. the generation of intermediate code.3. the printing of an error diagnostic.
4. the placement of some values in the symboltable.
44
8/10/2019 Compiler Construction Chapter 6
45/111
Bottom-up Translation of S-attributedGrammars
- A bottom-up parser uses a stack to hold information aboutsubtrees that have been parsed. We can use extra fields inthe parser stack to hold the values of synthesized attributes.
e.g. A -> XYZ {A.a = f (X.x, Y.y, Z.z)}
- Before reduction: the value of the attribute Z.z is in val [top],Y.y is in val [top-1], and Z.z is in val [top-2].
After reduction: top is decremented by 2, A.a is put in val[top]
8/10/2019 Compiler Construction Chapter 6
46/111
46
For Special Conditions : Hook
stmt -> IF cond THEN { action to emit appropriate cond.
jump } stmt ELSE { action to emit appropriate uncond.jump } stmt
Or
hook1-> { action to emit appropriate conditional jump }
hook2-> { action to emit appropriate unconditional jump }
stmt -> IF cond THEN hook1 stmt ELSE hook2 stmt
stmt -> IF cond THEN stmt ELSE stmt==>
8/10/2019 Compiler Construction Chapter 6
47/111
47
Symbol Table
consists of the records that associateattributes with various programmer declaredobjects. The main one is its name (a stringof characters, e.g. identifier).
semantic action will put information into
symbol table or take out attribute fromsymbol table.
8/10/2019 Compiler Construction Chapter 6
48/111
48
What kind of objects?
1. variables
2. components of a composition structure (i.e.,field names of structure)
3. labels
4. procedure and function name
5. parameters for procedure and function
6. files
8/10/2019 Compiler Construction Chapter 6
49/111
49
What attr ibutes (attributes of objects)?
1. name
2. type (e.g. int, float, array, struct, a pointer tostruct, etc.)
3. location for variables and entry point
4. value for named constant
5. initial value for variable
6. flag showing if it has been accessed.
8/10/2019 Compiler Construction Chapter 6
50/111
50
How does an attribute be represented?
1. Name strategy:
(a) use a field of n char in the symbol table
record to store the first (up to) n characters ofthe identifier.
(b) use an auxiliary string table and store apointer (e.g. 5) to the 1st char. of the identifier
and the length ( e.g. 4) of the identifier in the"name" field of symbol table record.
8/10/2019 Compiler Construction Chapter 6
51/111
51
Scheme(B) allows arbitrary large name, savesspace and requires more programming. Often
this table is kept for string literals and can be
used with little extra programming.
Scheme(A) is simpler, faster and requireless programming.
8/10/2019 Compiler Construction Chapter 6
52/111
52
Def. The static scope of an occurrence of anidentifier is that portion of the (source) program
in which other occurrence of the sameidentifier represents the same object.
2. type Since type can be arbitrarily complex,
they are best represented by a pointerto alinked data structure that reflects the structureof the type. (type is mainly used to determineif semantics is correct and offset computation.)
8/10/2019 Compiler Construction Chapter 6
53/111
53
e.g. in Pascal, it is the procedure or function inwhich it was declared minus all sub-procedures
and sub-functions in which it is represented.
program P;procedure Q; -----------------------------
var x: real; |
procedure R; ----- |var x: integer; | | scope of x
| minus this |x := ... | |
end; ----- |
|x := x + 1 |
end; ----------------------------end.
8/10/2019 Compiler Construction Chapter 6
54/111
54
Symbol table mechanism ?
1. What should be done when translating adeclaration?
2. What should be done when reference to anidentifier?
3. What should be done when at scope entry?
4. What should be done when at scope exit?
8/10/2019 Compiler Construction Chapter 6
55/111
55
Multiscope symbol table
- descriptor is a record that describing an object.
- its fields are called attributes- its key contains an identifier together with a
context (a context is a block or a declaration,represented by a lexical number).
8/10/2019 Compiler Construction Chapter 6
56/111
56
e.g. float x; -------
struct y{ ----- |int x; | |
int z; | inner context | another context
. | |
} ----- --------
8/10/2019 Compiler Construction Chapter 6
57/111
Each context associated with a #, x will pair with the# to look up at symbol table.
- when we enter a context (compiling time - not runtime) we give it a new # on to the context stack (it isthe current context).
- when we exit a context we pop that # from the stack.
- when resolving a reference to a simple identifier, say
x9, we pair it with the current context and look it up inthe symbol table, if not there try with next context, etc.until found, or we run out the context.
- when declaring an object we allocate a descriptor forit. Put the current context into its context field and the
identifier into its identifier-field. Then fill in other attribute as appropriate. In the case of a recorddeclaration
8/10/2019 Compiler Construction Chapter 6
58/111
58
y has #2 in its context field and x has # 3 in its internalcontext field. Lookup y using context # 2. Look up itsfield x with context # 3.
- when resolving a reference to a qualified identifier (e.g.student.grad) we look up the struct as before uponfinding, we get an attribute that called (that will be a #)internal-context and lookup the field with the context tofind the descriptor for that object.
e.g. float x; ------struct y { ---- |
int x; | |int z; | context #3 | context #2. | |} ---- -------
8/10/2019 Compiler Construction Chapter 6
59/111
Consider the following basic programming-language
constructs for generating intermediate codes:
1. Declarations ()
2. arithmetic assignment operations ()
3. Boolean expressions ()4. flow-of-control statements` if-statement() while ()
5. array references ()
6. procedure calls ()
7. switch statements ()8. structure-type references ()
59
8/10/2019 Compiler Construction Chapter 6
60/111
Semantic Actions for different
language constructs
1. Declarations
e.g. int x,y,z;float w, z, s;
60
8/10/2019 Compiler Construction Chapter 6
61/111
Suggested grammar:(Note: This is a very simple grammar mainly
used for explanation.)
P -> MD;
M ->
/* empty string */D -> D, id
| int id
| float id
P
M D
D , id
int id
;
int x , y ;
1
2
3
4
61
(Syntax directed) Translation
8/10/2019 Compiler Construction Chapter 6
62/111
(Syntax-directed) Translation
P -> MD; {/* do nothing */}
M -> { if offset was not initialized then offset = 0;}
D -> int id { enter (id.name, int, offset);
/* a function entering type int and
particular offset to the entry id.nameof the symbol table */
D.type = int;
offset = offset + 4; /*bytes, width of int*/
D.offset = offset; }
1
2
4
62
8/10/2019 Compiler Construction Chapter 6
63/111
D -> float id { enter (id.name, float, offset);
D.type = float;
offset = offset + 8;/*bytes, width of float*/
D.offset = offset ; }
D - > D(1), id { enter (id.name, D(1).type, D(1).offset);
D.type = D
(1)
.type;If D(1).type == int D.offset = D(1).offset + 4;
else if
D(1).type == float D.offset = D(1).offset+8;
offset = D.offset;}
Note: We can construct a data structure to store the information
(attributes) of D. (i.e., D.type and D.offset)
2
3
A id d
8/10/2019 Compiler Construction Chapter 6
64/111
Avoided grammar:
D -> int namelist ; | float namelist ;
namelist -> id, namelist | id
Why?
When the 'id' is reduced into namelist, we cannotknow the type of 'id' (int or float?) immediately.Therefore, it is troublesome to enter such typeinformation into the corresponding field of the 'id' in
the symbol table. Hence, we must use special codingtechnique (e.g. linked list keeping the ids name(pointers to symbol table) to achieve such a purpose.(* In other words, we need backpatch to chain the
data type.)
D
int namelist ;
id
int x ;
1
2
64
A bl
8/10/2019 Compiler Construction Chapter 6
65/111
Acceptable grammar:
D -> int intlist ; | float floatlist ;
intlist -> id, intlist | id
Advantage: The above-mentioned problem will nothappen. That is, when 'id' is reduced, we canidentify the type of id. (If id is reduced to intlist, thenid is of int type)
Defect: too much production will occur. => too manystates => bad performance
floatlist -> id, floatlist | id
65
8/10/2019 Compiler Construction Chapter 6
66/111
How to handle the following declaration?
x,y,z : float
Two approaches:
(I) decl -> id_list ':' type
id_list -> id_list ',' id | id
type -> int | float
(II) decl -> id ':' type | id , decltype -> int | float
Which one is better for LR parsing? Why?
1
2
3
1
2
66
8/10/2019 Compiler Construction Chapter 6
67/111
Suggested Grammar for the following Declaration:
var x,y,z : real; u,v,t : integer;
declarations : VAR decl_list
| /* empty (no declaration is permitted) */
;decl_list : declaration ';'
| declaration ';' decl_list
;
declaration : ID ':' type| ID ',' declaration
;
type : REAL
| INTEGER
;67
Try to construct a parse tree for the following declaration
8/10/2019 Compiler Construction Chapter 6
68/111
Try to construct a parse tree for the following declaration
and see how to parse it: var x: real; y: integer;
declarations
VAR decl_list
var declaration ; decl_list
ID : type declaration ;
x real ID : type
y integer
8/10/2019 Compiler Construction Chapter 6
69/111
The following grammar for declaration is
difficult for attribute gathering.
declaration : id_list ':' type ;
id_list : ID| id_list ',' ID
type : REAL
| INTEGER
69
8/10/2019 Compiler Construction Chapter 6
70/111
e.g., declaration
id_list : type
id_list , ID REAL
id_list , ID
ID
1
2
34
5
Intermediate Code Generation
8/10/2019 Compiler Construction Chapter 6
71/111
Intermediate Code Generation
Three Address Code (Two Address code => Triples)
Quadruples (a collective data structure, each unit is with 4 fields)Operator Arg1 Arg2 Result=+
=-
=*
=/=%
[]=
=[]
.
Note: The entries of operator column are integers that represent
individual operators. The entries of Arg1 (operand1) Arg2
(operand2) and Result are index (pointer) to the symbol table.
A unit
8/10/2019 Compiler Construction Chapter 6
72/111
Kinds of three-address codes:
1.A = B op(1) C (op is a binary arithmetic or logical operation)
2.A = op(2) B (op is a unary operation, e.g. minus, negation, shiftoperators, conversion operator, identity operator)
3. goto L (unconditional jump, execute the Lth three-
address code)
4. if A relop B goto L (relop denotes relational operators, e.g., , >=, !=, etc.)
5. param A and call P,n (used to implement a procedure call)
6. A = B [i]
7. A[i] = B
8. A = &B9. A = *B
10. *A = B
8/10/2019 Compiler Construction Chapter 6
73/111
In Quadruples:
Operator Arg1 Arg2 Result
1. ==> op(1) B C A
2. ==> op(2) B A
3. ==> goto L4. ==> relopgoto A B L
5. ==> param A
5. ==> call P n
6. ==> =[] B i A7. ==> []= B i A
8. ==> =& B A
9. ==> =* B A
10. ==> *= B A73
E l D A*B C D A B * C
8/10/2019 Compiler Construction Chapter 6
74/111
Example: D = A*B+C
The generated three address code is:
T1 = A * B T1 = B * C
T2 = T1 + C T2 = A + T1
D = T2 D = T2
Operator Arg1 Arg2 Result
=* A B T1
=+ T1 C T2
= T2 D
* T1 and T2 are compiler-generated temporary variables and they
are also saved in the symbol table.
D = A + B * C
Interpretthis
Actually, in implementation the
8/10/2019 Compiler Construction Chapter 6
75/111
Actually, in implementation the
quadruples look as:
Operator Arg1 Arg2 Result
8 6 7 9
15 9 8 11
3 11 10
in symbol table: index identifier attributes0 twa
1 K
.. ..
.. ..
6 A7 B
8 C
9 T1 /* compiler generated temporary variable */
10 D
11 T2 /* compiler generated temporary variable */
Interpretthis
75
8/10/2019 Compiler Construction Chapter 6
76/111
2. Arithmetic Statements
A -> id = E
E -> E(1) + E(2)
E -> E(1) - E(2)
E -> E(1) * E(2)
E -> E(1) / E(2)
E -> - E(1)
E -> (E(1))
E -> id
A
id = E
E + E
id id
x = a + b T1 = a + b
x = T1
1 2
3
4
76
A id E { GEN (id l E l ) }
8/10/2019 Compiler Construction Chapter 6
77/111
A -> id = E { GEN (id.place = E.place); }/* GEN (argument) - a function used to save its argument into the
quadruple. The implementation of E is a data structure with one field
E.place which holds the name that will hold the index value of thesymbol table. */
E -> E(1) + E(2) { T = NEWTEMP();/* NEWTEMP() - a function used to generate a
temporary variable T and save T into symboltable and return the index value of the symbol
table. */
E.place = T;
/* Ts index value in symbol table is assigned to
E.place */GEN(E.place = E(1).place + E(2).place); }
T = a + b
2
3
8/10/2019 Compiler Construction Chapter 6
78/111
E -> E(1) * E(2) { T = NEWTEMP();
E.place = T;
GEN(E.place = E(1).place * E(2).place); }
E -> - E(1) { T = NEWTEMP();
E.place = T;
GEN(E.place = -E(1).place); }
E -> (E(1)) { E.place = E(1).place; }
E -> id { E.place = id.place; }
/*idindexEfield 'place' ; Inimplementation id.place refers to the index value
of id in the symbol table. */
2
2
2
1
Enhanced version for E > E(1) op E(2)
8/10/2019 Compiler Construction Chapter 6
79/111
Enhanced version for E -> E(1) op E(2)
**in this version E (array ofstruct of EEattributes, array indexEvalue stack)
{ T = NEWTEMP();
if E(1).type == int and E(2).type == int then{ GEN (T = E(1).place intop E(2).place);
E.type = int;
}
else if E(1)
.type == float and E(2)
.type == float then{ GEN (T = E(1).place floatop E(2).place);
E.type = float;
8/10/2019 Compiler Construction Chapter 6
80/111
yp ;}
else if E(1).type == int and E(2). type == float then
{ U = NEWTEMP();GEN (U = inttofloat E(1).place);GEN (T = U floatop E(2).place);E. type = float;
}
else /* E(1). type == float and E(2). type == int then{ U = NEWTEMP();GEN (U = inttofloat E(2).place);GEN (T = E(1).place floatop U);
E. type = float;}
}
8/10/2019 Compiler Construction Chapter 6
81/111
3. Boolean Expression
M ->
E - > E o r M E| E and M E
| not E
| ( E )
| id
| id relop id
81
8/10/2019 Compiler Construction Chapter 6
82/111
An example
if p < q || r < s && t < u
x = y + z;k = m n;
For the above boolean expression thecorresponding contents in the quadruplesare:
82
quadruples if p < q || r < s && t < u+
8/10/2019 Compiler Construction Chapter 6
83/111
Location Three-Address Code
.
100 if p < q goto 106
101 goto 102
102 if r < s goto 104
103 goto 108
104 if t < u goto 106
105 goto 108 /*s.next = 105
106 t1 = y + z
107 x = t1
108 t2 = m - n
109 k = t2
... .........
x = y + z;k = m n;
E
E or M E
E and M E
id < id
id < id
id < id
counter = 100
1 2
34
5
7
6
8/10/2019 Compiler Construction Chapter 6
84/111
NEXTQUAD an integer variable used for saving the index (location)value of the next available entry of the quadruples.
E.true an attribute of E that holds a set of indexes (locations) of thequadruples, each indexed quadruple saves the three-address codewith true boolean expression.
E.false an attribute of E that holds a set of indexes of the
quadruples, each indexed quadruple saves the three-address codewith false boolean expression.
GEN(x) a function that translates x (a kind of three-address-code) intoquadruple representation.
So, we need to construct a data structure for E which includes twofields, each field can save an unlimited number of integer.Meanwhile, we need to construct an array of this Es structure tostore several Es attributes to be used in the same period of time .
1. M -> { M.quad = NEXTQUAD; }
/* M d i d t t t i t d ith M */
2
8/10/2019 Compiler Construction Chapter 6
85/111
/* M.quad is a data structure associated with M */
2. E -> E(1) or M E(2)
{
BACKPATCH (E(1).false, M.quad);
E.true = MERGE (E(1).true, E(2).true);
E.false = E(2).false;
}
/* BACKPATCH (p, i) a function that makes each of thequadruple index values on the list pointed to by p take
quadruple i as a target (i.e., goto i).*/
/* MERGE (a, b) a function that takes the lists pointed toby a and b, concatenates them into one list, andreturns a pointer to the concatenated list. */
4
(1) (2)
8/10/2019 Compiler Construction Chapter 6
86/111
3. E -> E(1) and M E(2)
{
BACKPATCH (E(1).true, M.quad);E.true = E(2).true;
E.false = MERGE (E(1).false, E(2).false);
}
4. E -> not E(1)
{ E.true = E(1).false; E.false = E(1).true;}
5. E -> ( E(1) )
{ E.true = E(1).true; E.false = E(1).false;}
3
3
4
6 E -> id1
8/10/2019 Compiler Construction Chapter 6
87/111
6. E -> id
{
E.true = MAKELIST (NEXTQUAD);
E.false = MAKELIST(NEXTQUAD + 1);GEN (if id.place goto _ );
GEN (goto _);
}
/* MAKELIST ( i ) a function that creates a list containing i, anindex into the array of quadruples, and returns a pointer to thelist it has made. */
/* GEN(x) a function that translates x (a kind of three-address-
code) into quadruple representation. */
1
8/10/2019 Compiler Construction Chapter 6
88/111
7. E -> id(1) relop id(2)
{E.true = MAKELIST (NEXTQUAD);E.false = MAKELIST(NEXTQUAD + 1);GEN (if id(1).place relop id(2).place goto _ );
GEN (goto _);}
falseE true
20
if id(1).place relopid(2).place goto _20
21 goto _
.
NEXTQUAD
21
22
1
88
8/10/2019 Compiler Construction Chapter 6
89/111
4. Flow-of-Control statements
A. Conditional Statements
S -> if E then S else S
| if E then S
| A| begin L end
L - > S
| L ; S
/* A denotes a general assignment statement
L denotes statement list
S denotes statement */
89
8/10/2019 Compiler Construction Chapter 6
90/111
1. S -> if E then M(1) S(1) N else M(2) S(2)
{BACKPATCH (E.true, M(1).quad);BACKPATCH (E.false, M(2).quad);S.next = MERGE (S(1).next, N.next, S(2).next);
}
/* S.next is a pointer to a list of all conditional andunconditional jump (goto) to the quadruple following thestatement S in execution order. */
7
90
8/10/2019 Compiler Construction Chapter 6
91/111
2. S -> if E then M S(1)
{ BACKPATCH (E.true, M.quad);S.next = MERGE (E.false, S(1).next)
}
3. M -> { M.quad = NEXTQUAD; }
4. N -> {
N.next = MAKELIST (NEXTQUAD);GEN (goto _);
}
nextN
20NEXTQUAD = 2020 Goto ___
NEXTQUAD
1
2
7
91
8/10/2019 Compiler Construction Chapter 6
92/111
5. S -> A{ S.next = MAKELIST ( ); }
/* initialize S.next to an empty list */
6. L -> S { L.next = S.next; }
7. L -> L(1) ; M S
{BACKPATCH (L(1).next, M.quad); // To resolve all
quadruples with conditional & unconditional unresolvedgoto _
L.next = S.next;}
8. S -> begin L end { S.next = L.next; }
3
4
5
6
92
8/10/2019 Compiler Construction Chapter 6
93/111
B. Iterative Statement
S -> while E do S
9. S -> while M(1) E do M(2) S(1)
{
BACKPATCH (E.true, M(2)
.quad);BACKPATCH (S(1).next, M(1).quad);S.next = E.false;GEN (goto M(1).quad);
}
93
An example:hil (A B) d if (C D) th X Y Z
8/10/2019 Compiler Construction Chapter 6
94/111
while (A
8/10/2019 Compiler Construction Chapter 6
95/111
5. Array References
Addressing Array Elements
one-dimension: A[low..high]
two-dimension: A[low1..high1, low2..high2]
n-dimension: A[low1..high1, low2..high2, ... , lown..highn]
Let: base = address of beginning of A, and
w = width of an array element
ni = the number of array elements in i-th dimension (row)
/* row major */
( e.g. n1 = high1 - low1 + 1; n2 = high2 - low2 + 1;n3 = high3 - low3 + 1; ...)
A[i] has address: base (of A) + (i - low) * w = i * w + (base
8/10/2019 Compiler Construction Chapter 6
96/111
A[i] has address: base (of A) (i low) w i w (base
low * w), where base - low * w is compile-time invariant.
A[i1, i2] has address (row-major): base + ((i1 - low1) * n2 +i2 - low2) * w = (i1 * n2 + i2) * w + base - (low1 * n2 +
low2) * w, where base - (low1 * n2 + low2) * w is compile-
time invariant
A[i1, i2, i3] has address: base + ((i1 - low1) * n2 * n3 + (i2
low2) * n3 + (i3 - low3)) * w = base + (((i1 - low1) * n2 + (i2
- low2)) * n3 + (i3 - low3)) * w = ((i1* n2 + i2) * n3 + i3) * w
+ base - ((low1* n2 + low2) * n3 + low3) * w, where base
((low1* n2 + low2) * n3 + low3) * w is compile-time invariant.
In general, A[i1, i2, ... ,ik] has address: ((..(((i1* n2 + i2) * n3 + i3)
8/10/2019 Compiler Construction Chapter 6
97/111
*n4 + ... ) * nk + ik) * w + base - ((..((low1* n2 + low2) * n3 +
low3)... ) * nk + lowk) * w, where base - ((..((low1* n2 + low2) *
n3 + low3) ... ) * nk + lowk) * w is compile-time invariant.
Therefore, we can compute as follows:
e1 = i1
e2 = e1* n2 + i2
e3 = e2* n3 + i3
.
em = em-1* nm + im
.ek = ek-1* nk + ik
8/10/2019 Compiler Construction Chapter 6
98/111
The address of A[i1, i2, ... ,ik] is: ek * w + compile-
time invariant.
98
Translation Scheme for Addressing Arra Elements
8/10/2019 Compiler Construction Chapter 6
99/111
Translation Scheme for Addressing Array Elements
Assume: (1) for each id there exists id.place which holds
its name,
(2) there is a function limit( ) where
limit(array_name, m) = nm i.e., the # of
elements of array array_name at dimensionm-th,
(3) we can find the width of an array element
from the name of array (i.e. from symbol
table)
// Please read Section 8.3.2 (Array References) of thetextbook.
( ) S
8/10/2019 Compiler Construction Chapter 6
100/111
(1) S -> L = E
{ if L.offset = null then
GEN (L.place = E.place)else
GEN (L.place[L.offset] = E.place); //
}
(2) E - > E 1 + E 2
{ E.place = newtemp(); //generate a temporary variable and
save its symbol table index
GEN (E.place = E1.place+ E2.place);
}
6
7
(3) E > (E (1)) { E l E (1) l }6
8/10/2019 Compiler Construction Chapter 6
101/111
(3) E -> (E (1)) { E.place = E (1).place }
(4) E - > L { if L.offset = null thenE.place = L.place
else
E.place = newtemp();
GEN (E.place = L.place[L.offset]);}
(5) L -> Elist ]
{ L.place = Elist.array_name;
L.offset = newtemp();GEN (L.offset = w * Elist.place); }
/* w is known from declaration of array */
3
5
6
(6) L - > i d { L.place = id.place; L.offset = null }4
8/10/2019 Compiler Construction Chapter 6
102/111
(7) Elist -> Elist (1), E
{ T = newtemp(); m = Elist (1).ndimen + 1;
GEN ( T = Elist (1).place * limit(Elist (1). array_name, m));GEN ( T = T + E.place );
Elist.array_name = Elist (1).array_name;
Elist.place = tj; // tj T
Elist.ndimen = mj; } // mj m
/* note em = em-1* nm + im , where Elist.place = em, Elist (1).place = em-1,limit(Elist (1).array, m) = nm, and E.place = im */
(8) Elist -> id [ E { Elist.place = E.place; Elist.ndimen = 1;
Elist.array_name := id.place; }
// : compile-time invariant id.place
1
2
6 Procedure calls
8/10/2019 Compiler Construction Chapter 6
103/111
6. Procedure calls
1. call -> id (args)
2. args -> args , E3. args -> E
1. call -> id (args)
{ for each item p on QUEUE do
GEN (param p);GEN (call id.place, length of QUEUE); }
/* QUEUE is a data structure for saving the indexes of the symboltable containing the names of the arguments. The length of
QUEUE is the number of elements in QUEUE */
3
2 args > args E2
8/10/2019 Compiler Construction Chapter 6
104/111
2. args -> args , E
{ append E.place to the end of QUEUE; }
3. args -> E
{ initialize QUEUE to contain only
E.place; }
/* Originally, QUEUE is empty and, after the reductionof E to args, QUEUE contains a single pointer to thesymbol table location for the name that denotes thevalue of E. */
1
2
7. Structure Declarations (Read Sec. 8.3.3)
8/10/2019 Compiler Construction Chapter 6
105/111
( )
type -> struct { fieldlist} /*Note: symbols with bold face are
terminals */| ptr
| char
| int
| float
| double
fieldlist -> fieldlist field;
| field;
field -> type id| field [integer/*a token denoting any string of digits*/]
int x
int x [10] [20] [30]field
int x [10] or
struct { int x; //offset 0float y; //offset 2char k[10];//offset 6
} m;
m.width = 16 bytes
8/10/2019 Compiler Construction Chapter 6
106/111
field -> type id
{ field.width = type.width;
field.name = id.name;
W_enter(id.name, type.width);}
| field(1)
[integer]{ field.width = field(1).width * integer.val;
field.name = field(1).name;
D_enter(field(1).name, integer.val);}
2
3
fieldlist -> field; {O_enter (field.name, 0); fieldlist.width = field.width;}
| fieldlist(1) field; { fieldlist width = fieldlist(1) width
3
8/10/2019 Compiler Construction Chapter 6
107/111
| fieldlist(1) field; { fieldlist.width = fieldlist(1).width
+ field.width;
O_enter (field.name, fieldlist(1)
.width);}type -> struct '{' fieldlist '} ' { type.width = fieldlist.width; }
type -> char { type.width = 1; } /* Assume characters take one byte.*/
type -> ptr {type.width = 4; } /*Assume pointers take four bytes.*/
type -> int { type.width = 2; } /* Assume integers take two bytes.*/
.......
5
1
1
1
4
Definitions of functions used
8/10/2019 Compiler Construction Chapter 6
108/111
D_enter(name,size) increases the number of dimensions for
name by one and enters the last dimension as size in thesymbol table entry for name.
W_enter(name,width) enters widthas the width of each
element of name. If name is not an array, then its width isthe number of locations taken by data of names type.
O_enter(name,offset) makes offset the number for which
field name name stands. This information, also, is recordedin the symbol table entry for name.
8/10/2019 Compiler Construction Chapter 6
109/111
8. Switch Statement
Syntax:
switch E
{case V1: S1;
case V2: S2;
.............
.............case Vn-1: Sn-1;
default: Sn;
}10
9
When translated into three-address code:
8/10/2019 Compiler Construction Chapter 6
110/111
100 Code to evaluate E into T
101 If T V1 goto 104
102 Code for S1103 Goto 113
104 If T V2 goto 107
105 Code for S2
106 Goto 113
107 ...108 ...
109 If T Vn-1 goto 112
110 Code for Sn-1
111 Goto 113
112 code for Sn113 .
Temporary variable
8/10/2019 Compiler Construction Chapter 6
111/111
Based on the given translation example, you
can infer how to generate the three-address
codes for switch statement easily !!!