Lecture 15-16: Intermediate Code-Generation
Dr Kieran T. Herley
Department of Computer Science
University College Cork
2016/17
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
1/1
Overview
Simple Two-Pass Tiny Compiler
Will sketch simple two-pass compiler for Tiny
Pass 1: Parse source and build parse tree (modified TinyParser)
Pass 2: Walk tree and generate code (TinyCompiler2)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
2/1
Overview
Simple Two-Pass Tiny Compiler
Will sketch simple two-pass compiler for Tiny
Pass 1: Parse source and build parse tree (modified TinyParser)
Pass 2: Walk tree and generate code (TinyCompiler2)
Variations:
Could use simpler syntax tree instead of parse tree
Could use jjtree/javacc to generate trees automatically
Could use one-pass, parse-and-generate also possible (TinyCompiler1)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
2/1
Overview
Overview of Tiny Compiler
TinyScanner Serves up source to parser, token by token
TinyParser2 Modification to recursive descent parser that builds
complete parse tree explicitly 1
TinyCompiler2 Recursive tree walk to generate three-address code
1
Can also use jjtree.javacc to generate tree. See TinyParser3
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
3/1
Overview
Parse Tree
Parse tree nodes encode the following:
Node type (TinyTreeNode)
public enum NodeKind
{ PROGRAM,
STMTSEQUENCE,
STATEMENT,
IFSTMT,
. . .
}
Children Accessible using getChild(n) and getChildren() (returns
iterator)
Other info.
value (NUM leaves only)
varName (Relevant nodes only)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
4/1
Overview
Notes on TinyParser2
TinyParser2 augments recursive descent TinyParser by adding
tree-building code
/∗ <Program> ::= <StmtSequence> ∗/
private TinyTreeNode buildProgram()
{ . . .
TinyTreeNode child = buildStmtSequence(); // builds PT for statement seq.
return new TinyTreeNode( TinyTreeNode.NodeKind.PROGRAM, child);
}
Notes:
Parsing methods named
buildProgram,
buildStmtSequence etc.
Method returns root of
associated parse (sub)tree
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
5/1
Overview
Notes on TinyParser2 cont’d
Another example:
/∗ <RepeatStmt> ::= repeat <StmtSequence> until <Exp> ∗/
private TinyTreeNode buildRepeatStmt()
{ . . .
match(TinyToken.TokenKind.RW REPEAT);
c1 = buildStmtSequence();
// builds PT for loop body
match(TinyToken.TokenKind.RW UNTIL);
c2 = buildExp();
// builds PT for loop condition
return new TinyTreeNode(TinyTreeNode.NodeKind.REPEATSTMT, c1, c2);
// new node with c1 and c2 as its children
}
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
6/1
Overview
Using jjtree/javacc to Generate Parse/Syntax Tree
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
7/1
Intermediate Code Generation
Simple Code Generation Framework
TinyCompiler incorporates recursive methode codegen
Performs traversal of parse tree, generating code as it goes
Node label encodes type of construct represented by subtree rooted at
that node
Can generate code according to fixed “pattern” for that construct
Can call codegen on childr3en to generate code for subconstructs
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
8/1
Intermediate Code Generation
Parse Tree
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
9/1
Intermediate Code Generation
Intermediate Code
Reminder of TAC
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
10 / 1
Intermediate Code Generation
Aside cont’d
TAC is Universal/Portable
Low-level but not architecture-specific
TAC-to-X 2 translations more straightforward than Tiny-to-X
Can use TAC to facilitate compiler adaptations to various instruction
sets
TAC as Intermediate representation
Quality of code generated critical to success of compiler
Intermediate representation such as TAC used as framework for code
optimization
2
Your favourite instruction set here
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
11 / 1
Intermediate Code Generation
Tree Traversal and Code Generation
Method codegen traverses parse tree to generate code
private String codegen(TinyTreeNode node)
{
Iterator <TinyTreeNode> children = node.getChildren();
switch (node.getKind())
{ case PROGRAM:
. . .
case IFSTMT:
. . .
case SIMPLEEXP:
. . .
}
}
Notes:
switch identifies node type and selects appropriate case
most cases call codegen on each child recursively
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
12 / 1
Control Flow Statements
Template for StmtSeq
hstmtseq i → hstatement i
; hstatement i
Template:
stmtseq
Generate code for first
statement (rec. call, first child)
Generate code for second
stateseq2 (rec. call, second
child)
ETC.
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
13 / 1
Control Flow Constructs
Repeat Statements
hrepeatstmt i → repeat hstmtseq i until hexp i
Generate top-of-loop label
Generate code for stmtseq
Generate code for exp
Generate conditional jump to
top-of-loop (jump if false)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
14 / 1
Control Flow Constructs
Repeat Statement Example
Example repeat x := x + 1 until x = 10
Template
l0:
) top label
t0 := x;
t1 := 1;
t0 := t0 + t1;
x := t0;
) code to execute loop body (StmtSequence)
)
)
)
t2 := x;
t3 := 10;
t4 := t2 == t3;
) code to evaluate condition (Exp)
)
)
if (t4 == 0 ) goto l0; ) jump to top if condition false
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
15 / 1
Control Flow Constructs
Some Code-Generating Code
Template:
l0:
) top label
t0 := x;
t1 := 1;
t0 := t0 + t1;
x := t0;
) code to execute loop body
)
)
)
t2 := x;
t3 := 10;
t4 := t2 == t3;
) code to evaluate condition
)
)
1
Generate top-of-loop label
(fresh label)
2
Call codegen on first child to
generate code for loop body
(recursion)
3
Call codegen on second child
to generate code for loop
condition (recursion)
4
Generate conditional jump to
top-of-loop label (if condition
false)
if (t4 == 0 ) goto l0; ) jump to top if condition false
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
16 / 1
Control Flow Constructs
More
REPEATSTMT case in codegen
String topLabel = newLabel();
generateLabel(topLabel );
// Generate top–of-loop label
codegen(children . next ());
// Generate code for loop body
varName = codegen(children.next());
// Generate code for loop condition
generateJumpFalse(varName, topLabel);
// Generate jump-back-if-false
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
17 / 1
Control Flow Constructs
More
REPEATSTMT case in codegen
String topLabel = newLabel();
generateLabel(topLabel );
// Generate top–of-loop label
codegen(children . next ());
// Generate code for loop body
varName = codegen(children.next());
// Generate code for loop condition
generateJumpFalse(varName, topLabel);
// Generate jump-back-if-false
Note on helper methods:
newLabel– generate sequence of labels (L1, L2, . . .)
generateLabel– emits TAC label instruction
generateJumpFalse generate TAC instruction of form
if (X == 0 ) goto L;
where X and L are the specified variable and label
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
17 / 1
Control Flow Constructs
If Statements
Example if x < 10 then write 17 end
Template
TAC
===
Template
========
t1 := 10;
t0 := x < t1;
)
)
code to evaluate condition
(Exp)
if (t0 == 0 ) goto l0;
)
jump to bottom if condition false
t2 := 17;
t3 := t2;
write t3;
)
)
)
code to execute then clause (StmtSeque
l0:
)
bottom label
Note: Distinguish if-then from if-then-else by number of children
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
18 / 1
Control Flow Constructs
If-then-else Statements
Example if x < 10 then write 17 else write 3 end
Template
t0 := x;
t1 := 10;
t2 := t0 < t1;
) code to evaluate condition
)
)
if (t2 == 0 ) goto l0; ) jump to else label of condition false
t3 := 17;
write t3;
) code to execute then clause
)
goto l1;
l0:
) jump to bottom label
) else label
t4 := 3;
write t4;
) code to execute else clause
)
l1:
) bottom label
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
19 / 1
Expressions
Expressions in Tiny
hsimplexp i → hterm
i haddop i hterm i
haddop i → + -
hterm i → hfactor
i
hmulop
i
hfactor
i
hmulop i → * /
hfactor i → ( hexp i ) num id
Expressions composed of subexpressions; exploit this structure to
generate code
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
20 / 1
Expressions
Code Generation For Expressions
Each hsimplexpi is a sequence of htermis
hsimplexp i → hterm i haddop i hterm i
Idea:
Generate code for each term (and return name of variable that
“houses” term value at runtime)
Embed term code-blocks with code to accmulate “sum” in some
variable
For simplicity, we generate fresh temporary variable (t1, t2, etc) to hold
each subexpression result
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
21 / 1
Expressions
Example 1 + 2 ∗ 3
1 + 2|{z}
∗3
|{z}
first second
t1 := 1;
) Code for first term
t2 := 2;
t3 := 3;
t4 := t2 * t3;
) Code for second term
)
)
t0 := t1 + t4;
) Code to combine the two
Each code for subexpressions has unique tempprray variable (here t1 and
t4) to “house” results (at run time)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
22 / 1
Expressions
Expressions in Tiny
hsimplexp i → hterm
i haddop i hterm i
haddop i → + -
hterm i → hfactor
i
hmulop
i
hfactor
i
hmulop i → * /
hfactor i → ( hexp i ) num id
simplexp
Generate code for each constituent term
Use fresh temp. variable to accumulate “sum” 3
term
Generate code for each constituent factor
Use fresh temp. variable to accumulate “product” 4
factor
id, num Generate instruction to store value in fresh temporary var.
exp Generate code for exp
3
Word
to encompass
both
additions
subtractions
KH “sum”
(10/11/16)
Lecture
15-16:
Intermediateand
Code-Generation
2016/17
23 / 1
Expressions
Example
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
24 / 1
Expressions
Key
black shows parse tree for 1 + 2 ∗ 3 ∗ 4 + (17)
blue shows TAC instructions generates
“inorder” traversal gives sequencing:
t2 := 1; t1:= t2; t0:= t1; t4 := 2; t3 := t4;
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
. . .
2016/17
25 / 1
Expressions
Generating Code for SIMPLEXP Nodes
case SIMPLEEXP:
String sumVar = newVar();
tempVar = codegen(children.next ()); // Term
generateSimple(sumVar, tempVar);
while ( children .hasNext())
{ TinyTreeNode child = children .next ();
String op =
( child .getKind() ==
TinyTreeNode.NodeKind.ADDOP PLUS? ”+”: ”−”);
tempVar = codegen(children.next ()); // Term
generateSimple(sumVar, sumVar, op, tempVar);
}
return sumVar;
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
26 / 1
Expressions
Generating Code for SIMPLEXP Nodes
case SIMPLEEXP:
String sumVar = newVar();
. . .
return sumVar;
Goal Generate code that (at run time) will compute the value of the
simplexp and return name of variable housing result
Notes
Children of node represent terms that make up this simplexp
Can call codegen on each of children to generate code for constituent
terms
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
27 / 1
Expressions
Generating Code for SIMPLEXP Nodes
case SIMPLEEXP:
String sumVar = newVar();
. . .
codegen(children .next ()); // Term
. . .
while ( children .hasNext())
{ . . .
codegen(children .next ()); // Term
}
. . .
return sumVar;
Need to intersperse extra code to “stitch together” results of
individual terms into single result
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
28 / 1
Expressions
Generating Code for SIMPLEXP Nodes
case SIMPLEEXP:
String sumVar = newVar();
tempVar = codegen(children.next ()); // Term
generateSimple(sumVar, tempVar);
while ( children .hasNext())
{ TinyTreeNode child = children .next ();
String op =
( child .getKind() ==
TinyTreeNode.NodeKind.ADDOP PLUS? ”+”: ”−”);
tempVar = codegen(children.next ()); // Term
generateSimple(sumVar, sumVar, op, tempVar);
}
return sumVar;
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
29 / 1
Expressions
A More Extensive Example
read(x);
t0 = 0;
t1 = x;
t2 = t0 < t1;
if (t2 != 1) goto l0;
t3 = 1;
fact = t3;
l1:
t4 = fact;
t5 = x;
t4 = t4 * t5;
fact = t4;
t6 = x;
t7 = 1;
t6 = t6 - t7;
x = t6;
t8 = x;
t9 = 0;
t10 = t8 = t9;
if (t10 != 1) goto l1;
t11 = fact;
write(t11);
l0:
KH (10/11/16)
# read x;
# if 0 < x then
#
fact := 1;
#
#
repeat
fact := fact * x;
#
#
x := x - 1
until x = 0;
#
write fact
# end
Lecture 15-16: Intermediate Code-Generation
2016/17
30 / 1
One-Pass Tiny Compiler
One-Pass Tiny Compiler
Can merge parsing and code generation phases into single pass over
source
No explicit parse tree (implicit in structure of recursion)
Parsing and code generation code interleaved
See TinyCompiler1
Pros and Cons
One-pass more efficient
More difficult to understand (and develop)
Some issues more difficult to tackle in one-pass framework (e.g. code
optimization)
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
31 / 1
One-Pass Tiny Compiler
TinyCompiler1
TinyParser Parses source: Reads through it and reconciles it with Tiny
grammar rules
TinyCompiler1
Parses and translates source
“Syntax-driven” process–built on top of TinyParser “chassis”
Generates three-address code
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
32 / 1
One-Pass Tiny Compiler
How TinyCompiler Works cont’d
Code-generating additions to parseAssignStmt (renamed
translateAssignStmt)
Structure of parse
encodes detail of
structure of source
program: its
/∗
constituent
∗/
stataments, their
private void translateAssignStmt ()
sequencing and nesting
{ . . .
and so on
match(TinyToken.TokenKind.ID);
match(TinyToken.TokenKind.SYM ASSIGN);
. . .
translateExp ();
. . .
}
Interleave
code-generating code
with parsing code so
TinyCompiler
translates as it parses
Parse-directed
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
33 / 1
One-Pass Tiny Compiler
How TinyCompiler Works cont’d
Code-generating additions to parseAssignStmt (renamed
translateAssignStmt)
1 Record name of LHS
variable (say `)
2
translateExp
private void translateAssignStmt ()
{ TinyToken lhs = current;
String lhsVar = lhs. getSpelling ();
// (1)
generates code to
evaluate RHS
expression
returns name of
temp. variable with
expr. value (say
tRHS )
match(TinyToken.TokenKind.ID);
match(TinyToken.TokenKind.SYM ASSIGN);
String rhsVar = translateExp ();
// (2)
emit(lhsVar+” = ”+rhsVar+”;”);
// (3)
}
3
Note: emit is essentially System.out.println
KH (10/11/16)
Generate code
` = tRHS
Lecture 15-16: Intermediate Code-Generation
2016/17
34 / 1
One-Pass Tiny Compiler
How TinyParser Works cont’d
private void translateRepeatStmt()
{ String topLabel = newLabel();
emit(topLabel+”:”);
match(TinyToken.TokenKind.RW REPEAT);
translateStmtSequence();
match(TinyToken.TokenKind.RW UNTIL);
String varName = translateExp();
// *** gen. top of loop label
// (gen. loop body code)
// *** gen. condit. eval. code
emit(” if (”+varName+”!= 1) goto ”, topLabel); // *** gen. jumpback on false
}
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
35 / 1
One-Pass Tiny Compiler
Factorial Example Revisited
read(x);
t0 = 0;
t1 = x;
t2 = t0 < t1;
if (t2 != 1) goto l0;
t3 = 1;
fact = t3;
l1:
t4 = fact;
t5 = x;
t4 = t4 * t5;
fact = t4;
t6 = x;
t7 = 1;
t6 = t6 - t7;
x = t6;
t8 = x;
t9 = 0;
t10 = t8 = t9;
if (t10 != 1) goto l1;
t11 = fact;
write(t11);
l0:
KH (10/11/16)
# read x;
# if 0 < x then
#
fact := 1;
#
#
repeat
fact := fact * x;
#
#
#
#
#
<- *** top-of-loop target
x := x - 1
until x = 0;
#
write fact
# end
<<<<-
Lecture 15-16: Intermediate Code-Generation
*** condition evaluation
***
***
*** jump back if false
2016/17
36 / 1
One-Pass Tiny Compiler
Aside
Code optimization– producing “best” code from source– is vitally
important aspect of production compilers
We ignore this completely: no attempt to minimize number of
instructions or labels
TAC often used as platform for code optimization
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
37 / 1
One-Pass Tiny Compiler
Aside
Code optimization– producing “best” code from source– is vitally
important aspect of production compilers
We ignore this completely: no attempt to minimize number of
instructions or labels
TAC often used as platform for code optimization
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
38 / 1
Other Bits and Pieces
TAC Engine
TacEngine can execute three-address codegen
Exercise: how to develop same?
KH (10/11/16)
Lecture 15-16: Intermediate Code-Generation
2016/17
39 / 1
© Copyright 2026 Paperzz