Beruflich Dokumente
Kultur Dokumente
1. Introduction
2. Lexical analysis
31
3. LL parsing
58
4. LR parsing
110
127
6. Semantic analysis
150
165
185
9. Activation Records
216
Chapter 1: Introduction
Things to do
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this work
for personal or classroom use is granted without fee provided that copies are not made or distributed for
profit or commercial advantage and that copies bear this notice and full citation on the first page. To copy
otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and/or
fee. Request permission to publish from hosking@cs.purdue.edu.
3
Compilers
What is a compiler?
a program that translates an executable program in one language into
an executable program in another language
we expect the program produced by the compiler to be better, in some
way, than the original
What is an interpreter?
a program that reads an executable program and produces the results
of running that program
usually, this involves executing the source program in some fashion
This course deals mainly with compilers
Many of the same issues arise in interpreters
4
Motivation
Interest
Compiler construction is a microcosm of computer science
artificial intelligence
algorithms
theory
systems
architecture
greedy algorithms
learning algorithms
graph algorithms
union-find
dynamic programming
DFAs for scanning
parser generators
lattice theory for analysis
allocation and naming
locality
synchronization
pipeline management
hierarchy management
instruction set use
changes in compilers
Intrinsic Merit
Compiler construction is challenging and fun
interesting problems
primary responsibility for performance
new architectures
(blame)
new challenges
real results
extremely complex interactions
Experience
You have used several compilers
What qualities are important in a compiler?
1. Correct code
2. Output runs fast
3. Compiler runs fast
4. Compile time proportional to program size
5. Support for separate compilation
6. Good diagnostics for syntax errors
7. Works well with the debugger
8. Good diagnostics for flow anomalies
9. Cross language calls
10. Consistent, predictable optimization
Each of these shapes your feelings about the correct contents of this course
9
Abstract view
source
code
compiler
machine
code
errors
Implications:
IR
front
end
back
end
machine
code
errors
Implications:
better code
11
A fallacy
C++
code
CLU
code
Smalltalk
code
Can we build n
front
end
front
end
front
end
front
end
m compilers with n
FORTRAN
code
back
end
target1
back
end
target2
back
end
target3
m components?
Front end
source
code
scanner
tokens
parser
IR
errors
Responsibilities:
Front end
source
code
tokens
scanner
parser
IR
errors
Scanner:
id,
id,
becomes
id,
Front end
source
code
scanner
tokens
parser
IR
errors
Parser:
recognize context-free syntax
guide context-sensitive analysis
construct IR(s)
produce meaningful error messages
attempt error correction
Parser generators mechanize much of the work
15
Front end
::=
sheep noise
sheep noise
This grammar defines the set of noises that a sheep makes under normal
circumstances
SN T P
Formally, a grammar G
Front end
term
::=
term
op
expr
expr
term
::=
::=
goal
expr
::=
op
1
2
3
4
5
6
7
op
term ,
expr ,
, ,
goal ,
N=
T =
goal
S=
P = 1, 2, 3, 4, 5, 6, 7
17
Front end
term
term
op
op
op
op
Prodn. Result
goal
1
expr
2
expr
5
expr
7
expr
2
expr
4
expr
6
expr
3
term
5
Front end
A parse can be represented by a tree called a parse or syntax tree
goal
expr
expr
expr
op
term
term
<num:2>
op
term
<id:y>
<id:x>
Front end
So, compilers often use an abstract syntax tree
<id:y>
+
<id:x>
<num:2>
20
Back end
IR
instruction
selection
register
allocation
machine
code
errors
Responsibilities
Back end
IR
instruction
selection
register
allocation
machine
code
errors
Instruction selection:
produce compact, fast code
use available addressing modes
pattern matching problem
ad hoc techniques
tree pattern matching
string pattern matching
dynamic programming
22
Back end
IR
register
allocation
instruction
selection
machine
code
errors
Register Allocation:
have value in a register when used
limited resources
changes instruction choices
can move loads and stores
optimal allocation is difficult
Modern allocators often use an analogy to graph coloring
23
front
end
IR
middle
end
IR
back
end
machine
code
errors
Code Improvement
24
IR
opt1
IR
...
IR
opt n
IR
errors
Compiler example
Pass 2
Instruction
Selection
Linker
Machine Language
Assem
Canoncalize
IR Trees
Translate
IR Trees
Semantic
Analysis
Pass 4
Pass 3
Tables
Translate
Parsing
Actions
Abstract Syntax
Parse
Reductions
Lex
Tokens
Pass 1
Frame
Pass 7
Code
Emission
Pass 8
Assembly Language
Pass 6
Register
Allocation
Register Assignment
Pass 5
Data
Flow
Analysis
Interference Graph
Control
Flow
Analysis
Flow Graph
Frame
Layout
Assem
Source Program
Environments
Assembler
Pass 9
Pass 10
26
Compiler phases
Lex
Parse
Parsing
Actions
Semantic
Analysis
Frame
Layout
Translate
Canonicalize
Instruction
Selection
Control Flow
Analysis
Data Flow
Analysis
Register
Allocation
Code
Emission
27
Stm ; Stm
: Exp
ExpList
Stm
Stm
Stm
Exp
Exp
Exp
Exp
ExpList
ExpList
Binop
Binop
Binop
Binop
1 10
3;
: 5
e.g.,
CompoundStm
AssignStm
PrintStm
IdExp
NumExp
OpExp
EseqExp
PairExpList
LastExpList
Plus
Minus
Times
Div
prints:
28
1 10
3;
Tree representation
CompoundStm
CompoundStm
AssignStm
OpExp
PrintStm
AssignStm
LastExpList
EseqExp
IdExp
3
OpExp
PrintStm
PairExpList
NumExp
IdExp
LastExpList
OpExp
IdExp
a
Minus
10
Times
IdExp
a
NumExp
1
*
"
"
"
"
"
!
"
*
!
"
"
"
"
"
"
"
"
"
"
"
"
#
1
"
"
"
"
"
#
"
"
1
"
"
!
!
'
"
"
"
"
!
0
/
!
)
"
"
"
'
&
"
&
"
"
30
31
Scanner
source
code
tokens
scanner
parser
IR
errors
id,
id,
becomes
id,
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this work
for personal or classroom use is granted without fee provided that copies are not made or distributed for
profit or commercial advantage and that copies bear this notice and full citation on the first page. To copy
otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and/or
fee. Request permission to publish from hosking@cs.purdue.edu.
32
Specifying patterns
comments
opening and closing delimiters:
ws
ws
white space
ws
::=
33
Specifying patterns
A scanner must recognize various parts of the languages syntax
Other parts are much harder:
identifiers
alphabetic followed by k alphanumerics ( , $, &, . . . )
numbers
integers: 0 or digit from 1-9 followed by digits from 0-9
complex:
real
decimals: integer
real
Definition
s s L or s
L M
Li
i 0
Li
i 1
L and t
st s
LM
Operation
union of L and M
written L M
concatenation of L and M
written LM
Kleene closure of L
written L
positive closure of L
written L
Operations on languages
35
Regular expressions
Patterns are often specified as regular languages
Notations used to describe a regular language (or a regular set) include
both regular expressions and regular grammars
, then a is a RE denoting a
2. if a
Ls
s is a RE denoting L r
r
r is a RE denoting L r
r s is a RE denoting L r L s
is a RE denoting L r
digit
real
real
integer decimal
complex
digit
integer .
decimal
9 digit
1 2 3
letter digit
letter
numbers
integer
real
z A B C
id
a b c
0 1 2 3 4 5 6 7 8 9
digit
identifier
letter
Examples
Description
is commutative
is associative
concatenation is associative
concatenation distributes over
Axiom
rs sr
r st
rs t
rs t r st
r st
rs rt
s t r sr tr
r r
r r
r
r
r
r
38
Examples
Let
ab
1. a b denotes a b
2. a b a b denotes aa ab ba bb
i.e., a b a b
aa ab ba bb
3. a denotes a aa aaa
39
Recognizers
From a regular expression we can construct a
deterministic finite automaton (DFA)
Recognizer for identifier :
letter
digit
letter
other
digit
other
accept
id
Z
z A B C
letter
0 1 2 3 4 5 6 7 8 9
digit
a b c
identifier
letter
error
letter digit
40
(
!
!
41
0
1
3
3
1
1
1
2
0 9 other
digit other
class
letter
digit
other
A Z
letter
value
a z
letter
Automatic construction
Scanner generators automatically construct code from regular expressionlike descriptions
construct a dfa
use state minimization techniques
emit code for the scanner
(table driven or direct code )
Provable fact:
Lg.
The grammars that generate regular sets are called regular grammars
Definition:
2. A
1. A
aA
1
s0
s1
1
1
s2
s3
The RE is 00 11
01 10 00 11
1
01 10 00 11
45
s0
s1
s2
s3
b
s0
s2
s3
s0
s1
s2
a
s0 s1
46
Finite automata
s0
1. a set of states S
2. Any NFA can be converted into a DFA, by simulating sets of simultaneous states:
each DFA state corresponds to a set of NFA states
possible exponential blowup
48
s0
s0 s1
s0 s2
s0 s3
b
s0
s0 s2
s0 s3
s0
s3
a
s0 s1
s0 s1
s0 s1
s0 s1
s2
s1
s0
s0 s2
s0 s3
s0 s1
s0
a
a
49
RE
DFA
NFA
moves
NFA w/ moves
build NFA for each term
connect them with moves
RE
minimized DFA
DFA
merge compatible states
RE
DFA
construct Rkij
k 1 k 1
Rik
Rkk
Rkk j 1
Rikj 1
50
RE to NFA
N a
N(B)
N(A)
N AB
N AB
N(B)
N(A)
N(A)
N A
51
RE to NFA: example
a b abb
2
ab
ab
abb
10
52
NFA N
A DFA D with states Dstates and transitions Dtrans
LN
such that L D
Let s be a state in N and T be a set of states,
and using the following operations:
Input:
Output:
Method:
Definition
set of NFA states reachable from NFA state s on -transitions alone
set of NFA states reachable from some NFA state s in T on transitions alone
set of NFA states to which there is a transition on input symbol a
from some NFA state s in T
Operation
-closure s
-closure T
move T a
10
1245679
1 2 4 5 6 7 10
D
E
01247
1234678
124567
A
B
C
A
B
C
D
E
a
B
B
B
B
B
b
C
D
C
E
C
54
p k qk
wcwr w
alternating 0s and 1s
1 01 0
55
So what is hard?
Language features that can cause problems:
reserved words
PL/I had no reserved words
significant blanks
FORTRAN and Algol68 ignore blanks
string constants
special characters in strings
,
,
,
finite closures
some languages limit identifier lengths
adds states to count length
FORTRAN 66
6 characters
These can be swept under the rug in the language design
56
.
"
57
Chapter 3: LL Parsing
58
scanner
tokens
parser
IR
errors
Parser
performs context-free syntax analysis
guides context-sensitive analysis
constructs an intermediate representation
produces meaningful error messages
attempts error correction
Syntax analysis
The set V
60
Vt
abc
U VW
V
Vn
ABC
then A
Vt
If A
uvw
Similarly,
denote derivations of
0 and
1 steps
L G is called a sentence of G
w ,w
Note, L G
Vt
LG
If S
and
Vt
61
Syntax analysis
Grammars are often written in Backus-Naur form (BNF).
expr
expr op expr
::
::
::
op
goal
expr
1
2
3
4
5
6
7
8
Example:
62
0
op
::
expr ::
term ::
term op term
...
...
...
brackets:
Derivations
We can view the productions of a CFG as rewriting rules.
expr
expr op expr
expr op expr op expr
id, op expr op expr
id,
expr op expr
id,
num, op expr
id,
num,
expr
id,
num,
id,
goal
Derivations
At each step, we chose a non-terminal to replace.
This choice can lead to different derivations.
Two are of particular interest:
leftmost derivation
the leftmost non-terminal is replaced at each step
rightmost derivation
the rightmost non-terminal is replaced at each step
Rightmost derivation
:
id,
id,
id,
id,
op expr
op id,
id,
op expr
op num,
num,
num,
Again, goal
expr
expr
expr
expr
expr
expr
expr
id,
goal
66
Precedence
goal
expr
expr
expr
<id,x>
<num,2>
<id,y>
Should be
expr
op
expr
op
67
Precedence
These two derivations point out a problem with the grammar.
It has no notion of precedence, or implied order of evaluation.
::
term
expr
expr
term
expr
term
term
term
factor
term factor
factor
::
::
goal
expr
::
factor
1
2
3
4
5
6
7
8
9
Precedence
:
Again, goal
term
term
factor
term
id,
factor
id,
num,
id,
num,
id,
num,
id,
num,
id,
expr
expr
expr
expr
expr
expr
term
factor
id,
goal
69
Precedence
goal
expr
term
term
term
factor
factor
<id,x>
<num,2>
factor
<id,y>
expr
70
Ambiguity
stmt
stmt
stmt
expr
expr
Example:
stmt ::=
If a grammar has more than one derivation for a single sentential form,
then it is ambiguous
S1
E2
E1
71
Ambiguity
stmt
matched
expr
expr
::=
unmatched
unmatched
match each
This generates the same language as the ambiguous grammar, but applies
the common sense rule:
Ambiguity
Ambiguity is often due to confusion in the context-free specification.
Context-sensitive confusions can arise from overloading.
Example:
tokens
grammar
parser
generator
parser
code
IR
75
Top-down parsing
A top-down parser starts with the root of the parse tree, labelled with the
start or goal symbol of the grammar.
To build a parse, it repeats the following steps until the fringe of the parse
tree matches the input string
and construct the
2. When a terminal is added to the fringe that doesnt match the input
string, backtrack
3. Find the next node to be expanded (must have a label in Vn)
factor
factor
::
factor
term
term
::
term
expr
expr
expr
term
term
term
factor
::
::
goal
expr
1
2
3
4
5
6
7
8
9
77
factor
factor
factor
factor
factor
term
term
factor
Sentential form
goal
expr
expr
term
term
term
factor
term
term
term
expr
expr
term
term
term
factor
term
term
term
term
factor
Prodn
1
2
4
7
9
3
4
7
9
7
8
5
7
8
Example
Input
78
Example
Input
term
goal
1
expr
2
expr
term
2
expr
term
2
expr
term
2
expr
term
2
Left-recursion
Top-down parsers cannot handle left-recursion in a grammar
Vn such that A
Eliminating left-recursion
To remove left-recursion, we can transform the grammar
foo
::
foo
bar
bar
::
::
foo
bar
Example
::
term
expr
term
expr
term
term
term
factor
term factor
factor
::
expr
term expr
term expr
term expr
factor term
factor term
factor term
::
::
term
term
::
::
expr
expr
Example
expr
expr
term
term
::
term
expr
term
term
term
factor
factor
factor
::
::
goal
expr
::
factor
1
2
3
4
5
6
7
8
9
It is
right-recursive
free of productions
Example
::
::
term
term
expr
term expr
term expr
term expr
factor term
factor term
factor term
::
::
::
goal
expr
expr
::
factor
1
2
3
4
5
6
7
8
9
10
11
Fortunately
large subclasses of CFGs can be parsed with limited lookahead
most programming language constructs can be expressed in a grammar that falls in these subclasses
Among the interesting subclasses are:
LL(1): left to right scan, left-most derivation, 1-token lookahead; and
LR(1): left to right scan, right-most derivation, 1-token lookahead
85
Predictive parsing
Basic idea:
FIRST
FIRST
and A
Key property:
Whenever two productions A
we would like
For some RHS G, define FIRST as the set of tokens that appear
first in some string derived from
w.
That is, for some w Vt , w FIRST iff.
This would allow the parser to make a correct choice with a lookahead of
only one symbol!
The example grammar has this property!
86
Left factoring
What if a grammar does not have this property?
Sometimes, we can transform a grammar to have this property.
For each non-terminal A find the longest prefix
common to two or more of its alternatives.
Example
term
term
expr
expr
::
FIRST
FIRST
FIRST
To choose between productions 2, 3, & 4, the parser must see past the
or
and look at the , , , or .
factor
::
term
expr
term
term
term
factor
factor
factor
::
::
goal
expr
1
2
3
4
5
6
7
8
9
Example
expr
expr
term
term
factor
factor
factor
::
term
term
term
term
::
expr
term expr
expr
expr
factor term
term
term
::
::
term
term
::
::
expr
expr
89
Example
expr
term expr
expr
expr
factor term
term
term
::
::
term
term
::
::
::
goal
expr
expr
::
factor
1
2
3
4
5
6
7
8
9
10
11
Example
Input
1
2
6
11
9
4
2
6
10
6
11
9
5
Sentential form
goal
expr
term expr
factor term expr
term expr
term expr
expr
expr
expr
term expr
factor term expr
term expr
term expr
term expr
term expr
factor term expr
term expr
term expr
expr
with
A NA
N
A
A
where N and A are new productions.
Repeat until there are no left-recursive productions.
92
Generality
Question:
By left factoring and eliminating left-recursion, can we transform
an arbitrary context-free grammar to a form where it can be predictively parsed with a single token lookahead?
Answer:
Given a context-free grammar that doesnt meet our conditions,
it is undecidable whether an equivalent grammar exists that does
meet our conditions.
an1b2n n
an0bn n
93
Now, we can produce a simple recursive descent parser from the (rightassociative) grammar.
94
95
To build an abstract syntax tree, we can simply insert code at the appropriate points:
96
97
source
code
scanner
tokens
table-driven
parser
IR
parsing
tables
Table-driven parsers
A parser generator system often looks like:
stack
source
code
grammar
scanner
parser
generator
tokens
table-driven
parser
IR
parsing
tables
This is true for both top-down (LL) and bottom-up (LR) parsers
99
Yk Yk 1
Yk
X is a non-terminal
M
X Y1Y2
Start Symbol
Y1
100
goal
expr
expr
term
term
factor
::
::
term
term
expr
term expr
expr
expr
factor term
term
term
::
::
::
1
2
11
1
2
10
7 8
::
'
we use $ to represent
factor
"
goal
expr
expr
1
2
3
4
5
6
7
8
9
10
11
101
FIRST
FIRST
then
FIRST
If
Vt then FIRST X is X
Yk :
Y1Y2
3. If X
2. If X
1. If X
To build FIRST X :
FIRST
Y1
FIRST
(c) If
102
FOLLOW
For a non-terminal A, define FOLLOW A as
the set of terminals that can appear immediately to the right of A
in some sentential form
Thus, a non-terminals FOLLOW set specifies the tokens that can legally
appear after it.
To build FOLLOW A :
B:
103
(i.e.,
FIRST
(b) If (i.e., A B) or
in FOLLOW B
in FOLLOW B
2. If A
LL(1) grammars
1 2
Revised definition
A grammar G is LL(1) iff. for each set of productions A
?
What if A
Previous definition
A grammar G is LL(1) iff. for all non-terminals A, each distinct pair of pro.
ductions A and A satisfy the condition FIRST FIRST
n :
1. FIRST 1 FIRST 2
FIRST n are all pairwise disjoint
2. If i
then FIRST j FOLLOW A
1 j n i j.
If G is -free, condition 1 is sufficient.
104
LL(1) grammars
Provable facts about LL(1) grammars:
1. No left-recursive grammar is LL(1)
2. No ambiguous grammar is LL(1)
3. Some languages have no LL(1) grammar
4. A free grammar where each alternative expansion for A begins with
a distinct terminal is a simple LL(1) grammar.
Example
S aS a
FIRST a
is not LL(1) because FIRST aS
S aS
S
aS
accepts the same language and is LL(1)
105
:
to M A $
A then add A
FOLLOW
to M A b
A , add A
FOLLOW
ii. If $
i.
FIRST
(b) If
to M A a
, add A
FIRST
(a)
productions A
1.
Vt , so a b
Note: recall a b
106
Example
TT
107
TT
E
E
EE
FT
T
FT T
E
TE
E
E S
TE E
S S
E E
E
T T
T
F F
$
$
FT
T
T
T
E F
$
$
$
S
E
E
T
T
F
E
TE
E
FOLLOW
FIRST
S
E
E
stmt
stmt
stmt
expr
expr
::
stmt
stmt
stmt
and
stmt
stmt
::
::
stmt
On seeing
expr
stmt
::
::
stmt
stmt
Left-factored:
stmt to associate
::
with clos-
The fix:
108
Error recovery
Key notion:
SYNCH
A
FOLLOW
1. a
Building SYNCH:
Vt
(i.e., SYNCH a
Chapter 4: LR Parsing
110
Some definitions
is
If
Recall
Bottom-up parsing
Goal:
Given an input string w and a grammar G, construct a parse tree by
starting at the leaves and working to the root.
The parser repeatedly matches a right-sentential form from the language
against the trees upper frontier.
At each match, it applies a reduction to build on the frontier:
each reduction matches an upper frontier of the partially built tree to
the RHS of some production
each reduction adds a node on top of the frontier
The final result is a rightmost derivation, in reverse.
112
Example
AB
A
1 S
2 A
3
4 B
S
The trick appears to be scanning the input and finding valid sentential
forms.
113
Handles
What are we trying to find?
A substring of the trees upper frontier that
i.e., if S rm Aw
handle of w
rm w then A
Handles
The handle A
Handles
Theorem:
If G is unambiguous then every right-sentential form has a unique handle.
Proof: (by definition)
rightmost derivation is unique
applied to take i 1 to i
3.
4.
a unique handle A
a unique production A
2.
1. G is unambiguous
is applied
116
Example
117
Sentential Form
goal
expr
expr
term
expr
term
factor
expr
term
expr
factor
expr
term
factor
Prodn.
1
3
5
9
7
8
4
7
9
::
factor
::
term
expr
expr
term
expr
term
term
term
factor
term factor
factor
::
::
goal
expr
1
2
3
4
5
6
7
8
9
Handle-pruning
The process to construct a bottom-up parse is called handle-pruning.
n 1
i
Ai
i
Ai
2.
1.
i 1
118
Stack implementation
One scheme to implement a handle-pruning, bottom-up parser is called a
shift-reduce parser.
Shift-reduce parsers use a stack and an input buffer
1. initialize stack with $
2. Repeat until the top of the stack is the goal symbol and the input token
is $
Example: back to
Input
factor
factor
term
term
term
term
term
factor ::
::
term
expr
expr
term
expr
term
term
term
factor
term factor
factor
::
::
goal
expr
1
2
3
4
5
6
7
8
9
Stack
$
$
$ factor
$ term
$ expr
$ expr
$ expr
$ expr
$ expr
$ expr
$ expr
$ expr
$ expr
$ expr
$ goal
Action
shift
reduce 9
reduce 7
reduce 4
shift
shift
reduce 8
reduce 7
shift
shift
reduce 9
reduce 5
reduce 3
reduce 1
accept
Shift-reduce parsing
Shift-reduce parsers are simple to understand
A shift-reduce parser has just four canonical actions:
1. shift next input symbol is shifted onto the top of the stack
2. reduce right end of handle is on top of stack;
locate left end of handle within the stack;
pop handle off stack and push appropriate non-terminal LHS
3. accept terminate parsing and signal success
4. error call an error recovery routine
The key problem: to recognize handles (not covered in this course).
121
LR k grammars
122
LR k grammars
Formally, a grammar G is LR k iff.:
Ay
1. S rm Aw rm w, and
2. S rm Bx rm y, and
3. FIRST k w
FIRST k y
Bx
Thus Ay
But, the common prefix means y also reduces to Ay, for the same result.
Bx.
123
Parsing review
Recursive descent
LL k
LR k
An LR k parser must be able to recognize the occurrence of the right
hand side of a production after having seen all that is derived from that
right hand side with k symbols of lookahead.
b or B
LR dilemma: pick A
b or A
LL dilemma: pick A
The dilemmas:
c ?
b ?
126
127
The JavaCC grammar can have embedded action code written in Java,
just like a Yacc grammar can have embedded action code written in C.
header
token specifications for lexical analysis
grammar
129
Example of a production:
130
131
Sneak Preview
When using the Visitor pattern,
133
134
and
to
135
136
-object
Insert an
method in each class. Each accept method takes a
Visitor as argument.
A Visitor contains a
method for each class (overloading!) A
method for a class C takes an argument of type C.
138
139
Notice: The
methods describe both
1) actions, and 2) access of subobjects.
140
Comparison
The Visitor pattern combines the advantages of the two other approaches.
Frequent
Frequent
type casts? recompilation?
Yes
No
No
Yes
No
No
Visitors: Summary
Syntax-tree-node
classes
Java Compiler
Compiler
JavaCC grammar
with embedded
Java code
JTB
JavaCC
grammar
Program
Parser
Syntax tree
with accept methods
Default visitor
144
145
Using JTB
Example (simplified)
JTB produces:
146
for
Notice the
method; it invokes the method
the default visitor.
Example (simplified)
:
147
in
Notice the body of the method which visits each of the three subtrees of
the
node.
Example (simplified)
148
Example (simplified)
When this visitor is passed to the root of the syntax tree, the depth-first
traversal will begin, and when
nodes are reached, the method
in
is executed.
. It is a visitor which pretty prints Java
JTB is bootstrapped.
149
150
Semantic Analysis
The compilation process is driven by the syntactic structure of the program
as discovered by the parser
Semantic routines:
interpret meaning of the program based on its syntactic structure
two purposes:
finish analysis by deriving context-sensitive information
begin synthesis by generating the IR or target code
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this work
for personal or classroom use is granted without fee provided that copies are not made or distributed for
profit or commercial advantage and that copies bear this notice and full citation on the first page. To copy
otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and/or
fee. Request permission to publish from hosking@cs.purdue.edu.
151
Context-sensitive analysis
What context-sensitive questions might the compiler ask?
1. Is
2. Is
5. Is an expression type-consistent?
6. Does the dimension of a reference match the declaration?
8. Does
9. Is
7. Where can
12. Can
be implemented as a memo-function?
Context-sensitive analysis
Why is context-sensitive analysis hard?
answers depend on values, not syntax
questions and answers involve non-local information
answers may involve computation
Several alternatives:
abstract syntax tree specify non-local computations
(attribute grammars) automatic evaluators
symbol tables central store for facts
express checking code
language design simplify language
avoid problems
153
Symbol tables
For compile-time efficiency, compilers often use a symbol table:
associates lexical names (symbols) with their attributes
What items should be entered?
variable names
defined constants
procedure and function names
literal constants and strings
source text labels
compiler-generated temporaries
Separate table for structure layouts (types)
(for aggregates)
declaring procedure
lexical level of declaration
storage class
(base address)
offset in storage
if record, pointer to structure table
if parameter, by-reference or by-value?
can it be aliased? to what other names?
number and type of arguments to functions
155
Attribute information
Attributes are internal representation of declarations
Symbol table associates names with attributes
Names may have different attributes depending on their meaning:
variables: type, procedure level, frame offset
types: type descriptor, data size/alignment
constants: type, value
procedures: formals (names/types), result type, block information (local decls.), frame size
157
Type expressions
Type expressions are a textual representation for types:
1. basic types: boolean, char, integer, real, etc.
2. type names
(b) T1
158
Type descriptors
char
pointer
char
pointer integer
integer
char
e.g., char
or
char
pointer
integer
159
Type compatibility
Type checking needs to determine type equivalence
Two approaches:
Name equivalence: each type name is a distinct type
Structural equivalence: two types are equivalent iff. they have the same
structure (after substituting type expressions for type names)
t1
s2
t1 and s2
pointer t iff. s
pointer s
s1
t2 iff. s1
t1
s2
s1
array t1 t2 iff. s1
t1 and s2
t2
t2
array s1 s2
t2 iff. s1
t1 and s2
t2
160
Consider:
and
and
and
and
Ada/Pascal/Modula-2 are somewhat confusing: they treat distinct type definitions as distinct types, so
161
Type expressions are equivalent if they are represented by the same node
in the graph
162
Consider:
record
pointer
integer
Eliminating name
163
record
integer
pointer
164
165
IR trees: Expressions
CONST
Integer constant i
i
NAME
Symbolic constant n
n
TEMP
Temporary t
t
BINOP
[a code label]
[one of any number of registers]
o e 1 e2
MEM
e
CALL
en
f e1
en
ESEQ
se
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this work
for personal or classroom use is granted without fee provided that copies are not made or distributed for
profit or commercial advantage and that copies bear this notice and full citation on the first page. To copy
otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and/or
fee. Request permission to publish from hosking@cs.purdue.edu.
166
IR trees: Statements
MOVE
Evaluate e into temporary t
TEMP
t
MOVE
Evaluate e1 yielding address a, e2 into word at a
e2
MEM
e1
EXP
e
JUMP
l1
ln
CJUMP
o e 1 e2 t f
SEQ
s1 s2
LABEL
n
Kinds of expressions
Expression kinds indicate how expression might be used
Ex(exp) expressions that compute a value
Nx(stm) statements: expressions that compute no value
Cx conditionals (jump to true and false destinations)
RelCx(op, left, right)
IfThenElseExp expression/statement depending on use
Conversion operators allow use of one form in context of another:
unEx convert to tree expression that computes value of inner tree
unNx convert to tree statement that computes inner tree but returns no
value
unCx(t, f) convert to statement that evaluates inner tree and branches to
true destination if non-zero, false destination otherwise
168
Translating
Simple variables: fetch with a MEM:
Ex(MEM( (TEMP fp, CONST k)))
MEM
BINOP
Ex(MEM( (e.unEx,
Translating
(
Record variables: Suppose records are pointers to record base, so fetch like other variables. For e. :
*
e2
Record creation:
f 1 e1 f 2
the space then initialize it:
fn
e1
Array creation:
Control structures
Basic blocks:
a sequence of straight-line code
if one instruction executes then they all execute
a maximal sequence of instructions without branches
a label starts a new basic block
Overview of control structure translation:
control flow links up the basic blocks
ideas are simple
implementation requires bookkeeping
some care is needed for good code
171
while loops
while c do s:
1. evaluate c
2. if false jump to next statement after loop
3. if true fall into loop body
4. branch to top of loop
e.g.,
test:
if not(c) jump done
s
jump test
done:
Nx( SEQ(SEQ(SEQ(LABEL test, c.unCx(body, done)),
SEQ(SEQ(LABEL body, s.unNx), JUMP(NAME test))),
LABEL done))
repeat e1 until e2
for loops
:= e1 to e2 do s
evaluate lower bound into index variable
evaluate upper bound into limit variable
if index limit jump to next statement after loop
fall through to loop body
increment index
if index limit jump to top of loop body
t1 e 1
t2 e 2
if t1 t2 jump done
body : s
t1 t1 1
if t1 t2 jump body
done:
for
1.
2.
3.
4.
5.
6.
f e1
Function calls
en :
174
Comparisons
Translate a op b as:
Conditionals
5 then a
b turns into if x
5&a
e.g., x
5 then a
Applying unCx t f to if x
Conditionals: Example
b else 0:
177
2w,
translates to:
(CONST w, e.unEx))))
178
Multidimensional arrays
Array allocation:
constant bounds
allocate in static area, stack, or heap
no run-time descriptor is needed
dynamic arrays: bounds fixed at run-time
allocate in stack or heap
descriptor is needed
dynamic arrays: bounds can change at run-time
allocate in heap
descriptor is needed
179
Multidimensional arrays
Array layout:
Contiguous:
1. Row major
Rightmost subscript varies most quickly:
Used in FORTRAN
By vectors
Contiguous vector of pointers to (non-contiguous) subarrays
180
Lj
Uj
in :
i1
position of
Dj
Ln
in
L n 1 Dn
L n 2 Dn Dn 1
L 1 Dn
i1
in 1
in 2
D2
Ln
variable part
i 1 D2 Dn i 2 D3 Dn
i n 1 Dn i n
L 1 D2 Dn L 2 D3 Dn
L n 1 Dn
constant part
address of i1
in :
address( ) + ((variable part
constant part)
element size)
181
case statements
case E of V1: S1 . . . Vn : Sn end
1. evaluate the expression
2. find value in case list equal to value of expression
3. execute statement associated with value found
4. jump to next statement after case
Key issue: finding the right case
182
case statements
case E of V1: S1 . . . Vn : Sn end
Simplification
Goal 1: No SEQ or ESEQ.
Goal 2: CALL can only be subtree of EXP(. . . ) or MOVE(TEMP t,. . . ).
Transformations:
CJUMP(op,
e1, ESEQ(s, e2 ), l1, l2)
MOVE(ESEQ(s, e1), e2)
CALL( f , a)
CJUMP(op,
ESEQ(s, e1), e2, l1, l2)
BINOP(op, e1, ESEQ(s, e2 ))
JUMP(ESEQ(s, e1))
MEM(ESEQ(s, e1))
185
Register allocation
IR
register
allocation
instruction
selection
machine
code
errors
Register allocation:
have value in a register when used
limited resources
changes instruction choices
can move loads and stores
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this
work for personal or classroom use is granted without fee provided that copies are not made or distributed
for profit or commercial advantage and that copies bear this notice and full citation on the first page. To
copy otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission
and/or fee. Request permission to publish from hosking@cs.purdue.edu.
186
Liveness analysis
Problem:
IR contains an unbounded number of temporaries
machine has bounded number of registers
Approach:
temporaries with disjoint live ranges can map to same register
if not enough registers then spill some temporaries
(i.e., keep them in memory)
The compiler must perform liveness analysis for each temporary:
It is live if it holds a value that may be needed in future
187
Example:
a 0
L1 : b a 1
c c b
a b 2
if a N goto L1
return c
188
Liveness analysis
Gathering liveness information is a form of data flow analysis operating
over the CFG:
def v
def n
use v
use n
v live-in at n
v live-in at n
pred n
v live-out at n v
v live-out at all m
def n
v live-in at n
189
Liveness analysis
Define:
in n : variables live-in at n
in n : variables live-out at n
Then:
in s
out n
out n
succ n
s succ n
Note:
in n
out n
def n
in n
use n
def n
out n
out n
use n
use n or v
Thus, in n
in n iff. v
Now, v
def n
190
foreach n in n
; out n
repeat
foreach n
in n
in n ;
out n
out n ;
in n
use n
out n de f n
out n
in s
out n
out n
in n
until in n
s succ n
Notes:
should order computation of inner loop to follow the flow
liveness flows backward along control-flow arcs, from out to in
nodes can just as easily be basic blocks to reduce CFG size
could do one variable at a time, from uses back to defs, noting liveness
along the way
191
N nodes in CFG
N variables
N elements per in/out
O N time per set-union
worst-case complexity of O N 4
192
193
Register allocation
IR
register
allocation
instruction
selection
machine
code
errors
Register allocation:
have value in a register when used
limited resources
changes instruction choices
can move loads and stores
Copyright c 2000 by Antony L. Hosking. Permission to make digital or hard copies of part or all of this
work for personal or classroom use is granted without fee provided that copies are not made or distributed
for profit or commercial advantage and that copies bear this notice and full citation on the first page. To
copy otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission
and/or fee. Request permission to publish from hosking@cs.purdue.edu.
194
195
196
Coalescing
Can delete a move instruction when source s and destination d do not
interfere:
coalesce them into a new node whose edges are the union of those
of s and d
In principle, any pair of non-interfering nodes can be coalesced
unfortunately, the union is more constrained and new graph may
no longer be K-colorable
overly aggressive
197
done
build
any
coa
lesc
aggressive
coalesce
done
simplify
spil
spill
any
select
198
Conservative coalescing
Apply tests for coalescing that preserve colorability.
199
build
simplify
conservative
coalesce
freeze
potential
spill
done
select
spills
actual
spill
y
an
201
Spilling
Spills require repeating build and simplify on the whole program
To avoid increasing number of spills in future rounds of build can simply discard coalescences
Alternatively, preserve coalescences from before first potential spill,
discard those after that point
Move-related spilled temporaries can be aggressively coalesced, since
(unlike registers) there is no limit on the number of stack-frame locations
202
Precolored nodes
Precolored nodes correspond to machine registers (e.g., stack pointer, arguments, return address, return value)
select and coalesce can give an ordinary temporary the same color as
a precolored register, if they dont interfere
e.g., argument registers can be reused inside procedures for a temporary
simplify, freeze and spill cannot be performed on them
also, precolored nodes interfere with other precolored nodes
So, treat precolored nodes as having infinite degree
This also avoids needing to store large adjacency lists for precolored nodes;
coalescing can use the George criterion
203
204
205
Temporaries are , , , ,
Assume target machine with K 3 registers: , (caller-save/argument/resul
(callee-save)
The code generator has already made arrangements to save
explicitly by copying into temporary and back again
Example
206
Example (cont.)
Interference graph:
priority
K significant-
0.50
2.75
0.33
5.50
10.30
207
r2
Example (cont.)
Interference graph with
ae
r1
removed:
208
with
):
and
(or coalesce
and
with
Coalescing
Example (cont.)
):
209
Example (cont.)
Cannot coalesce
with because the move is constrained: the
nodes interfere. Must simplify :
Graph now has only precolored nodes, so pop nodes from stack coloring along the way
210
Example (cont.)
211
Example (cont.)
r3c1c2
r2b
with , then
with
ae
with
As before, coalesce
, then
with
Coalesce
r1
212
and simplify :
with
As before, coalesce
Example (cont.)
213
Example (cont.)
Rewrite the program with this assignment:
214
Example (cont.)
215
216
procedure Q
prologue
prologue
precall
call
postcall
epilogue
epilogue
Procedure linkages
argument n
.
.
.
argument 2
argument 1
frame
pointer
previous frame
incoming
arguments
higher addresses
local
variables
return address
outgoing
arguments
saved registers
argument m
.
.
.
argument 2
argument 1
next frame
stack
pointer
current frame
temporaries
lower addresses
219
Procedure linkages
The linkage divides responsibility between caller and callee
Caller
Call
pre-call
1.
2.
3.
4.
Return
post-call
1. copy return value
2. deallocate basic frame
3. restore parameters
(if copy out)
Callee
prologue
1.
2.
3.
4.
5.
epilogue
1.
2.
3.
4.
5.
(link time)
Data space
fixed-sized data may be statically allocated
variable-sized data must be dynamically allocated
some data is dynamically allocated in code
Control stack
dynamic slice of activation tree
return addresses
may be implemented in hardware
221
free memory
heap
static data
code
low address
Storage classes
Each variable must be assigned a storage class
(base address)
Static variables:
addresses compiled into code
(relocatable)
Global variables:
almost identical to static variables
layout may be important
(exposed)
224
225
Lexical nesting
view variables as (level,offset) pairs
(compile-time)
(at run-time)
226
displays
227
local value
l cannot occur
calling level k
(static links )
1 procedure
1 and pass it
228
The display
To improve run-time access costs, use a display :
table of access links for lower levels
lookup is index from known offset
takes slight amount of time at call
a single display or one per frame
1 slots
l
find slot as
l o)
229
Call/return
Assuming callee saves:
1. caller pushes space for return value
2. caller pushes SP
3. caller pushes space for:
return address, static chain, saved registers
4. caller evaluates and pushes actuals onto stack
5. caller sets return address, callees static chain, performs call
6. callee saves registers in register-save area
7. callee copies by-value arrays/records using addresses passed as actuals
8. callee allocates dynamic arrays as needed
9. on return, callee restores saved registers
10. jumps to return address
Caller must allocate much of stack frame, because it computes the actual
parameters
Alternative is to put actuals below callees stack frame in callers: common
when hardware supports stack management (e.g., VAX)
231
at
v0, v1
a0a3
t0t7
1623
24, 25
s0s7
t8, t9
26, 27
28
29
30
31
k0, k1
gp
sp
s8 (fp)
ra
Name
Number
0
1
2, 3
47
815
Usage
Constant 0
Reserved for assembler
Expression evaluation, scalar function results
first 4 scalar arguments
Temporaries, caller-saved; caller must save to preserve across calls
Callee-saved; must be preserved across calls
Temporaries, caller-saved; caller must save to preserve across calls
Reserved for OS kernel
Pointer to global area
Stack pointer
Callee-saved; must be preserved across calls
Expression evaluation, pass return address in calls
232
233
framesize
frame offset
low memory
234
3. Execute a
instruction: jumps to target address (callees first instruction), saves return address in register ra
235
local variables
saved registers
sufficient space for arguments to routines called by this routine
and
where
time constants
4. Clean up stack
5. Return
237