SlideShare a Scribd company logo
Three-Address Code IR
Announcements
● Programming Project 3 due Monday at
11:59PM.
● OH today after lecture.
● Ask questions on Piazzza!
● Ask questions via email!
● Checkpoint feedback will be returned
soon.
Where We Are
Lexical Analysis
Semantic Analysis
Syntax Analysis
IR Generation
IR Optimization
Code Generation
Optimization
Source
Code
Machine
Code
Overview for Today
● The Final Assignment
● Introduction to TAC:
● TAC for simple expressions.
● TAC for functions and function calls.
● TAC for objects.
● TAC for arrays.
● Generating TAC.
● A few low-level details.
The Final Assignment
● Goal: Generate TAC IR for Decaf programs.
● We provide a code generator to produce MIPS assembly.
● You can run your programs using spim, the MIPS simulator.
● You must also take care of some low-level details:
● Assign all parameters, local variables, and temporaries positions
in a stack frame.
● Assign all global variables positions in the global memory
segment.
● Assign all fields in a class an offset from the base of the object.
● You should not need to know MIPS to do this; all details
will be covered in lecture.
● If you have any questions on MIPS, please feel to ask!
An Important Detail
● When generating IR at this level, you do
not need to worry about optimizing it.
● It's okay to generate IR that has lots of
unnecessary assignments, redundant
computations, etc.
● We'll see how to optimize IR code later
this week and at the start of next week.
● It's tricky, but extremely cool!
Three-Address Code
● Or “TAC”
● The IR that you will be using for the final
programming project.
● High-level assembly where each
operation has at most three operands.
● Uses explicit runtime stack for function
calls.
● Uses vtables for dynamic dispatch.
Sample TAC Code
int x;
int y;
int x2 = x * x;
int y2 = y * y;
int r2 = x2 + y2;
Sample TAC Code
int x;
int y;
int x2 = x * x;
int y2 = y * y;
int r2 = x2 + y2;
x2 = x * x;
y2 = y * y;
r2 = x2 + y2;
Sample TAC Code
int a;
int b;
int c;
int d;
a = b + c + d;
b = a * a + b * b;
Sample TAC Code
int a;
int b;
int c;
int d;
a = b + c + d;
b = a * a + b * b;
_t0 = b + c;
a = _t0 + d;
_t1 = a * a;
_t2 = b * b;
b = _t1 + _t2;
Sample TAC Code
int a;
int b;
int c;
int d;
a = b + c + d;
b = a * a + b * b;
_t0 = b + c;
a = _t0 + d;
_t1 = a * a;
_t2 = b * b;
b = _t1 + _t2;
Temporary Variables
● The “three” in “three-address code”
refers to the number of operands in any
instruction.
● Evaluating an expression with more than
three subexpressions requires the
introduction of temporary variables.
● This is actually a lot easier than you
might think; we'll see how to do it later
on.
Sample TAC Code
int a;
int b;
a = 5 + 2 * b;
Sample TAC Code
int a;
int b;
a = 5 + 2 * b;
_t0 = 5;
_t1 = 2 * b;
a = _t0 + _t1;
Sample TAC Code
int a;
int b;
a = 5 + 2 * b;
_t0 = 5;
_t1 = 2 * b;
a = _t0 + _t1;
TAC allows for
instructions with two
operands.
Simple TAC Instructions
● Variable assignment allows assignments of the
form
● var = constant;
● var1
= var2
;
● var1
= var2
op var3
;
● var1
= constant op var2
;
● var1
= var2
op constant;
● var = constant1
op constant2
;
● Permitted operators are +, -, *, /, %.
● How would you compile y = -x; ?
Simple TAC Instructions
● Variable assignment allows assignments of the
form
● var = constant;
● var1
= var2
;
● var1
= var2
op var3
;
● var1
= constant op var2
;
● var1
= var2
op constant;
● var = constant1
op constant2
;
● Permitted operators are +, -, *, /, %.
● How would you compile y = -x; ?
y = 0 – x; y = -1 * x;
One More with bools
int x;
int y;
bool b1;
bool b2;
bool b3;
b1 = x + x < y
b2 = x + x == y
b3 = x + x > y
One More with bools
int x;
int y;
bool b1;
bool b2;
bool b3;
b1 = x + x < y
b2 = x + x == y
b3 = x + x > y
_t0 = x + x;
_t1 = y;
b1 = _t0 < _t1;
_t2 = x + x;
_t3 = y;
b2 = _t2 == _t3;
_t4 = x + x;
_t5 = y;
b3 = _t5 < _t4;
TAC with bools
● Boolean variables are represented as
integers that have zero or nonzero
values.
● In addition to the arithmetic operator,
TAC supports <, ==, ||, and &&.
● How might you compile b = (x <= y) ?
TAC with bools
● Boolean variables are represented as
integers that have zero or nonzero
values.
● In addition to the arithmetic operator,
TAC supports <, ==, ||, and &&.
● How might you compile b = (x <= y) ?
_t0 = x < y;
_t1 = x == y;
b = _t0 || _t1;
Control Flow Statements
int x;
int y;
int z;
if (x < y)
z = x;
else
z = y;
z = z * z;
Control Flow Statements
int x;
int y;
int z;
if (x < y)
z = x;
else
z = y;
z = z * z;
_t0 = x < y;
IfZ _t0 Goto _L0;
z = x;
Goto _L1;
_L0:
z = y;
_L1:
z = z * z;
Control Flow Statements
int x;
int y;
int z;
if (x < y)
z = x;
else
z = y;
z = z * z;
_t0 = x < y;
IfZ _t0 Goto _L0;
z = x;
Goto _L1;
_L0:
z = y;
_L1:
z = z * z;
Control Flow Statements
int x;
int y;
int z;
if (x < y)
z = x;
else
z = y;
z = z * z;
_t0 = x < y;
IfZ _t0 Goto _L0;
z = x;
Goto _L1;
_L0:
z = y;
_L1:
z = z * z;
Labels
● TAC allows for named labels indicating
particular points in the code that can be
jumped to.
● There are two control flow instructions:
● Goto label;
● IfZ value Goto label;
● Note that IfZ is always paired with Goto.
Control Flow Statements
int x;
int y;
while (x < y) {
x = x * 2;
}
y = x;
Control Flow Statements
int x;
int y;
while (x < y) {
x = x * 2;
}
y = x;
_L0:
_t0 = x < y;
IfZ _t0 Goto _L1;
x = x * 2;
Goto _L0;
_L1:
y = x;
A Complete Decaf Program
void main() {
int x, y;
int m2 = x * x + y * y;
while (m2 > 5) {
m2 = m2 – x;
}
}
A Complete Decaf Program
void main() {
int x, y;
int m2 = x * x + y * y;
while (m2 > 5) {
m2 = m2 – x;
}
}
main:
BeginFunc 24;
_t0 = x * x;
_t1 = y * y;
m2 = _t0 + _t1;
_L0:
_t2 = 5 < m2;
IfZ _t2 Goto _L1;
m2 = m2 – x;
Goto _L0;
_L1:
EndFunc;
A Complete Decaf Program
void main() {
int x, y;
int m2 = x * x + y * y;
while (m2 > 5) {
m2 = m2 – x;
}
}
main:
BeginFunc 24;
_t0 = x * x;
_t1 = y * y;
m2 = _t0 + _t1;
_L0:
_t2 = 5 < m2;
IfZ _t2 Goto _L1;
m2 = m2 – x;
Goto _L0;
_L1:
EndFunc;
A Complete Decaf Program
void main() {
int x, y;
int m2 = x * x + y * y;
while (m2 > 5) {
m2 = m2 – x;
}
}
main:
BeginFunc 24;
_t0 = x * x;
_t1 = y * y;
m2 = _t0 + _t1;
_L0:
_t2 = 5 < m2;
IfZ _t2 Goto _L1;
m2 = m2 – x;
Goto _L0;
_L1:
EndFunc;
A Complete Decaf Program
void main() {
int x, y;
int m2 = x * x + y * y;
while (m2 > 5) {
m2 = m2 – x;
}
}
main:
BeginFunc 24;
_t0 = x * x;
_t1 = y * y;
m2 = _t0 + _t1;
_L0:
_t2 = 5 < m2;
IfZ _t2 Goto _L1;
m2 = m2 – x;
Goto _L0;
_L1:
EndFunc;
Compiling Functions
● Decaf functions consist of four pieces:
● A label identifying the start of the function.
– (Why?)
● A BeginFunc N; instruction reserving N
bytes of space for locals and temporaries.
● The body of the function.
● An EndFunc; instruction marking the end of
the function.
– When reached, cleans up stack frame and
returns.
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
g(a, …, m)
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
main:
BeginFunc 4;
_t0 = 137;
PushParam _t0;
LCall _SimpleFn;
PopParams 4;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
main:
BeginFunc 4;
_t0 = 137;
PushParam _t0;
LCall _SimpleFn;
PopParams 4;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
main:
BeginFunc 4;
_t0 = 137;
PushParam _t0;
LCall _SimpleFn;
PopParams 4;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
main:
BeginFunc 4;
_t0 = 137;
PushParam _t0;
LCall _SimpleFn;
PopParams 4;
EndFunc;
Compiling Function Calls
void SimpleFn(int z) {
int x, y;
x = x * y * z;
}
void main() {
SimpleFunction(137);
}
_SimpleFn:
BeginFunc 16;
_t0 = x * y;
_t1 = _t0 * z;
x = _t1;
EndFunc;
main:
BeginFunc 4;
_t0 = 137;
PushParam _t0;
LCall _SimpleFn;
PopParams 4;
EndFunc;
Stack Management in TAC
● The BeginFunc N; instruction only needs to
reserve room for local variables and
temporaries.
● The EndFunc; instruction reclaims the room
allocated with BeginFunc N;
● A single parameter is pushed onto the stack by
the caller using the PushParam var instruction.
● Space for parameters is reclaimed by the caller
using the PopParams N; instruction.
● N is measured in bytes, not number of arguments.
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M PushParam var;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
PushParam var;
PushParam var;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
PushParam var;
PushParam var;
PushParam var;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
PushParam var;
PushParam var;
PushParam var;
BeginFunc N;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
g(a, …, m)
PushParam var;
PushParam var;
PushParam var;
BeginFunc N;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
Storage for
Locals and
Temporaries
EndFunc;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Param M
…
Param 1
PopParams N;
A Logical Decaf Stack Frame
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Stack
frame for
function
f(a, …, n)
Storage Allocation
● As described so far, TAC does not specify
where variables and temporaries are
stored.
● For the final programming project, you
will need to tell the code generator where
each variable should be stored.
● This normally would be handled during
code generation, but Just For Fun we
thought you should have some experience
handling this. ☺
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
Param M
…
Param 1
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
Param M
…
Param 1
Storage for
Locals and
Temporaries
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
Param M
…
Param 1
Storage for
Locals and
Temporaries
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
Param M
…
Param 1
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
The Frame Pointer
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Frame
Pointer
Logical vs Physical Stack Frames
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Logical vs Physical Stack Frames
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Logical vs Physical Stack Frames
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
Param N
Param N – 1
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
fp of caller
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
fp of caller
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
fp of caller
Storage for
Locals and
Temporaries
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
fp of caller
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
fp of caller
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
Param N
...
Param 1
(Mostly) Physical Stack Frames
Param N
...
Param 1
Storage for
Locals and
Temporaries
fp of caller
Frame
Pointer
The Stored Return Address
● Internally, the processor has a special register
called the program counter (PC) that stores the
address of the next instruction to execute.
● Whenever a function returns, it needs to restore
the PC so that the calling function resumes
execution where it left off.
● The address of where to return is stored in MIPS
in a special register called ra (“return address.”)
● To allow MIPS functions to call one another, each
function needs to store the previous value of ra
somewhere.
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Param N
...
Param 1
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Param N
...
Param 1
fp of caller
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Param N
...
Param 1
fp of caller
ra of caller
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Param N
...
Param 1
fp of caller
ra of caller
Physical Stack Frames
Param N
...
Param 1
Locals and
Temporaries
fp of caller
Frame
Pointer
ra of caller
Param N
...
Param 1
fp of caller
ra of caller
Locals and
Temporaries
So What?
● In your code generator, you must assign each
local variable, parameter, and temporary
variable its own location.
● These locations occur in a particular stack
frame and are called fp-relative.
Param N
...
Param 1
Local 0
fp of caller
ra of caller
fp
● Parameters begin at address
fp + 4 and grow upward.
● Locals and temporaries begin
at address fp – 8 and grow
downward
...
Local M
fp + 0
fp + 4
...
fp + 4N
fp - 4
fp - 8
...
fp - 4 - 4M
From Your Perspective
Location* location =
new Location(fpRelative, +4, locName);
From Your Perspective
Location* location =
new Location(fpRelative, +4, locName);
From Your Perspective
Location* location =
new Location(fpRelative, +4, locName);
What variable does
this refer to?
And One More Thing...
int globalVariable;
int main() {
globalVariable = 137;
}
And One More Thing...
int globalVariable;
int main() {
globalVariable = 137;
}
And One More Thing...
int globalVariable;
int main() {
globalVariable = 137;
}
Where is this
stored?
The Global Pointer
● MIPS also has a register called the
global pointer (gp) that points to
globally accessible storage.
● Memory pointed at by the global pointer
is treated as an array of values that
grows upward.
● You must choose an offset into this array
for each global variable.
Global Variable 0
Global Variable 1
...
Global Variable N
gp gp + 0
gp + 4
...
gp + 4N
From Your Perspective
Location* global =
new Location(gpRelative, +8, locName);
From Your Perspective
Location* global =
new Location(gpRelative, +8, locName);
Summary of Memory Layout
● Most details abstracted away by IR
format.
● Remember:
● Parameters start at fp + 4 and grow upward.
● Locals start at fp – 8 and grow downward.
● Globals start at gp + 0 and grow upward.
● You will need to write code to assign
variables to these locations.
TAC for Objects, Part I
class A {
void fn(int x) {
int y;
y = x;
}
}
int main() {
A a;
a.fn(137);
}
TAC for Objects, Part I
class A {
void fn(int x) {
int y;
y = x;
}
}
int main() {
A a;
a.fn(137);
}
_A.fn:
BeginFunc 4;
y = x;
EndFunc;
main:
BeginFunc 8;
_t0 = 137;
PushParam _t0;
PushParam a;
LCall _A.fn;
PopParams 8;
EndFunc;
TAC for Objects, Part I
class A {
void fn(int x) {
int y;
y = x;
}
}
int main() {
A a;
a.fn(137);
}
_A.fn:
BeginFunc 4;
y = x;
EndFunc;
main:
BeginFunc 8;
_t0 = 137;
PushParam _t0;
PushParam a;
LCall _A.fn;
PopParams 8;
EndFunc;
A Reminder: Object Layout
Method 0
Field 0
Vtable*
Vtable*
...
Field N
Field 0
...
Field N
Field 0
...
Field M
Method 1
...
Method K
Method 0
Method 1
...
Method K
Method 0
...
Method L
TAC for Objects, Part II
class A {
int y;
int z;
void fn(int x) {
y = x;
x = z;
}
}
int main() {
A a;
a.fn(137);
}
TAC for Objects, Part II
class A {
int y;
int z;
void fn(int x) {
y = x;
x = z;
}
}
int main() {
A a;
a.fn(137);
}
_A.fn:
BeginFunc 4;
*(this + 4) = x;
x = *(this + 8);
EndFunc;
main:
BeginFunc 8;
_t0 = 137;
PushParam _t0;
PushParam a;
LCall _A.fn;
PopParams 8;
EndFunc;
TAC for Objects, Part II
class A {
int y;
int z;
void fn(int x) {
y = x;
x = z;
}
}
int main() {
A a;
a.fn(137);
}
_A.fn:
BeginFunc 4;
*(this + 4) = x;
x = *(this + 8);
EndFunc;
main:
BeginFunc 8;
_t0 = 137;
PushParam _t0;
PushParam a;
LCall _A.fn;
PopParams 8;
EndFunc;
TAC for Objects, Part II
class A {
int y;
int z;
void fn(int x) {
y = x;
x = z;
}
}
int main() {
A a;
a.fn(137);
}
_A.fn:
BeginFunc 4;
*(this + 4) = x;
x = *(this + 8);
EndFunc;
main:
BeginFunc 8;
_t0 = 137;
PushParam _t0;
PushParam a;
LCall _A.fn;
PopParams 8;
EndFunc;
Memory Access in TAC
● Extend our simple assignments with
memory accesses:
● var1
= *var2
● var1
= *(var2
+ constant)
● *var1
= var2
● *(var1
+ constant) = var2
● You will need to translate field accesses
into relative memory accesses.
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
_Base.hi:
BeginFunc 4;
_t0 = "Base";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Base = _Base.hi,
;
_Derived.hi:
BeginFunc 4;
_t0 = "Derived";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Derived = _Derived.hi,
;
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
_Base.hi:
BeginFunc 4;
_t0 = "Base";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Base = _Base.hi,
;
_Derived.hi:
BeginFunc 4;
_t0 = "Derived";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Derived = _Derived.hi,
;
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
_Base.hi:
BeginFunc 4;
_t0 = "Base";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Base = _Base.hi,
;
_Derived.hi:
BeginFunc 4;
_t0 = "Derived";
PushParam _t0;
LCall _PrintString;
PopParams 4;
EndFunc;
Vtable Derived = _Derived.hi,
;
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
TAC for Objects, Part III
class Base {
void hi() {
Print("Base");
}
}
class Derived extends Base{
void hi() {
Print("Derived");
}
}
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
What's going
on here?
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
hi
Derived Vtable
Code for
Derived.hi
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Param 1
4
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Param 1
4
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Param 1
4
(raw memory)
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
Param 1
4
(raw memory)
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
(raw memory)
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Allocate
Object
Set
Vtable
Load
Function
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable* Load
Function
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Param 1
Load
Function
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Param 1
Load
Function
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable*
Param 1
Load
Function
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable* Load
Function
Allocate
Object
Set
Vtable
Dissecting TAC
int main() {
Base b;
b = new Derived;
b.hi();
}
main:
BeginFunc 20;
_t0 = 4;
PushParam _t0;
b = LCall _Alloc;
PopParams 4;
_t1 = Derived;
*b = _t1;
_t2 = *b;
_t3 = *_t2;
PushParam b;
ACall _t3;
PopParams 4;
EndFunc;
fp of caller
ra of caller
hi
Derived Vtable
Code for
Derived.hi
_t0
_t1
_t2
_t3
b
4
VTable* Load
Function
Allocate
Object
Set
Vtable
OOP in TAC
● The address of an object's vtable can be
referenced via the name assigned to the vtable
(usually the object name).
● e.g. _t0 = Base;
● When creating objects, you must remember to
set the object's vtable pointer or any method
call will cause a crash at runtime.
● The ACall instruction can be used to call a
method given a pointer to the first instruction.
Generating TAC
TAC Generation
● At this stage in compilation, we have
● an AST,
● annotated with scope information,
● and annotated with type information.
● To generate TAC for the program, we do
(yet another) recursive tree traversal!
● Generate TAC for any subexpressions or
substatements.
● Using the result, generate TAC for the overall
expression.
TAC Generation for Expressions
● Define a function cgen(expr) that generates
TAC that computes an expression, stores it in a
temporary variable, then hands back the name
of that temporary.
●
Define cgen directly for atomic expressions
(constants, this, identifiers, etc.).
●
Define cgen recursively for compound
expressions (binary operators, function calls,
etc.)
cgen for Basic Expressions
cgen for Basic Expressions
cgen(k) = { // k is a constant
Choose a new temporary t
Emit( t = k );
Return t
}
cgen for Basic Expressions
cgen(k) = { // k is a constant
Choose a new temporary t
Emit( t = k );
Return t
}
cgen(id) = { // id is an identifier
Choose a new temporary t
Emit( t = id )
Return t
}
cgen for Binary Operators
cgen for Binary Operators
cgen(e1
+ e2
) = {
Choose a new temporary t
Let t1
= cgen(e1
)
Let t2
= cgen(e2
)
Emit( t = t1
+ t2
)
Return t
}
An Example
cgen(5 + x) = {
Choose a new temporary t
Let t1
= cgen(5)
Let t2
= cgen(x)
Emit (t = t1
+ t2
)
Return t
}
An Example
cgen(5 + x) = {
Choose a new temporary t
Let t1
= {
Choose a new temporary t
Emit( t = 5 )
return t
}
Let t2
= cgen(x)
Emit (t = t1
+ t2
)
Return t
}
An Example
cgen(5 + x) = {
Choose a new temporary t
Let t1
= {
Choose a new temporary t
Emit( t = 5 )
return t
}
Let t2
= {
Choose a new temporary t
Emit( t = x )
return t
}
Emit (t = t1
+ t2
)
Return t
}
An Example
cgen(5 + x) = {
Choose a new temporary t
Let t1
= {
Choose a new temporary t
Emit( t = 5 )
return t
}
Let t2
= {
Choose a new temporary t
Emit( t = x )
return t
}
Emit (t = t1
+ t2
)
Return t
}
_t0 = 5
_t1 = x
_t2 = _t0 + _t1
cgen for Statements
● We can extend the cgen function to
operate over statements as well.
● Unlike cgen for expressions, cgen for
statements does not return the name of a
temporary holding a value.
● (Why?)
cgen for Simple Statements
cgen for Simple Statements
cgen(expr;) = {
cgen(expr)
}
cgen for while loops
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
cgen for while loops
cgen(while (expr) stmt) = {
Let Lbefore
be a new label.
Let Lafter
be a new label.
Emit( Lbefore
:)
Let t = cgen(expr)
Emit( IfZ t Goto Lafter
)
cgen(stmt)
Emit( Goto Lbefore
)
Emit( Lafter
: )
}
Next Time
● Intro to IR Optimization
● Basic Blocks
● Control-Flow Graphs
● Local Optimizations

More Related Content

PPTX
Detecting Bugs in Binaries Using Decompilation and Data Flow Analysis
PDF
Intermediate code generation
PPT
Intermediate code generation
PPTX
Compiler Design_Code generation techniques.pptx
PPT
Compiler-Design-Intermediate-code-generation.ppt
PPT
458237.-Compiler-Design-Intermediate-code-generation.ppt
PPTX
Principal Sources of Optimization in compiler design
DOC
optimization process on compiler
Detecting Bugs in Binaries Using Decompilation and Data Flow Analysis
Intermediate code generation
Intermediate code generation
Compiler Design_Code generation techniques.pptx
Compiler-Design-Intermediate-code-generation.ppt
458237.-Compiler-Design-Intermediate-code-generation.ppt
Principal Sources of Optimization in compiler design
optimization process on compiler

Similar to Slides13.pdf (20)

PPTX
20101017 program analysis_for_security_livshits_lecture02_compilers
PPT
457418.-Compiler-Design-Code-optimization.ppt
PDF
Project presentation PPT.pdf this is help for student who doing this complier...
PDF
Code tuning techniques
PDF
Chapter 11 - Intermediate Code Generation.pdf
PDF
Compiler Construction | Lecture 11 | Monotone Frameworks
PPTX
Three address code In Compiler Design
PPT
Compiler Design Unit 5
PDF
Presentation1.pdf
PDF
reductio [ad absurdum]
PPTX
Lecture 12 intermediate code generation
PDF
ARM procedure calling conventions and recursion
PDF
12IRGeneration.pdf
PDF
Stale pointers are the new black
DOC
PCD ?s(MCA)
DOC
Pcd(Mca)
DOC
Pcd(Mca)
DOC
Principles of Compiler Design
PPT
Chapter 6 Intermediate Code Generation
20101017 program analysis_for_security_livshits_lecture02_compilers
457418.-Compiler-Design-Code-optimization.ppt
Project presentation PPT.pdf this is help for student who doing this complier...
Code tuning techniques
Chapter 11 - Intermediate Code Generation.pdf
Compiler Construction | Lecture 11 | Monotone Frameworks
Three address code In Compiler Design
Compiler Design Unit 5
Presentation1.pdf
reductio [ad absurdum]
Lecture 12 intermediate code generation
ARM procedure calling conventions and recursion
12IRGeneration.pdf
Stale pointers are the new black
PCD ?s(MCA)
Pcd(Mca)
Pcd(Mca)
Principles of Compiler Design
Chapter 6 Intermediate Code Generation
Ad

Recently uploaded (20)

PDF
Classroom Observation Tools for Teachers
PPTX
Lesson notes of climatology university.
PDF
ChatGPT for Dummies - Pam Baker Ccesa007.pdf
PPTX
A powerpoint presentation on the Revised K-10 Science Shaping Paper
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
Empowerment Technology for Senior High School Guide
PPTX
UV-Visible spectroscopy..pptx UV-Visible Spectroscopy – Electronic Transition...
PDF
SOIL: Factor, Horizon, Process, Classification, Degradation, Conservation
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
Complications of Minimal Access Surgery at WLH
PDF
IGGE1 Understanding the Self1234567891011
PPTX
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
PDF
Weekly quiz Compilation Jan -July 25.pdf
PDF
Trump Administration's workforce development strategy
PPTX
UNIT III MENTAL HEALTH NURSING ASSESSMENT
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
Onco Emergencies - Spinal cord compression Superior vena cava syndrome Febr...
PDF
medical_surgical_nursing_10th_edition_ignatavicius_TEST_BANK_pdf.pdf
PDF
Hazard Identification & Risk Assessment .pdf
PPTX
Tissue processing ( HISTOPATHOLOGICAL TECHNIQUE
Classroom Observation Tools for Teachers
Lesson notes of climatology university.
ChatGPT for Dummies - Pam Baker Ccesa007.pdf
A powerpoint presentation on the Revised K-10 Science Shaping Paper
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
Empowerment Technology for Senior High School Guide
UV-Visible spectroscopy..pptx UV-Visible Spectroscopy – Electronic Transition...
SOIL: Factor, Horizon, Process, Classification, Degradation, Conservation
Final Presentation General Medicine 03-08-2024.pptx
Complications of Minimal Access Surgery at WLH
IGGE1 Understanding the Self1234567891011
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
Weekly quiz Compilation Jan -July 25.pdf
Trump Administration's workforce development strategy
UNIT III MENTAL HEALTH NURSING ASSESSMENT
Supply Chain Operations Speaking Notes -ICLT Program
Onco Emergencies - Spinal cord compression Superior vena cava syndrome Febr...
medical_surgical_nursing_10th_edition_ignatavicius_TEST_BANK_pdf.pdf
Hazard Identification & Risk Assessment .pdf
Tissue processing ( HISTOPATHOLOGICAL TECHNIQUE
Ad

Slides13.pdf

  • 2. Announcements ● Programming Project 3 due Monday at 11:59PM. ● OH today after lecture. ● Ask questions on Piazzza! ● Ask questions via email! ● Checkpoint feedback will be returned soon.
  • 3. Where We Are Lexical Analysis Semantic Analysis Syntax Analysis IR Generation IR Optimization Code Generation Optimization Source Code Machine Code
  • 4. Overview for Today ● The Final Assignment ● Introduction to TAC: ● TAC for simple expressions. ● TAC for functions and function calls. ● TAC for objects. ● TAC for arrays. ● Generating TAC. ● A few low-level details.
  • 5. The Final Assignment ● Goal: Generate TAC IR for Decaf programs. ● We provide a code generator to produce MIPS assembly. ● You can run your programs using spim, the MIPS simulator. ● You must also take care of some low-level details: ● Assign all parameters, local variables, and temporaries positions in a stack frame. ● Assign all global variables positions in the global memory segment. ● Assign all fields in a class an offset from the base of the object. ● You should not need to know MIPS to do this; all details will be covered in lecture. ● If you have any questions on MIPS, please feel to ask!
  • 6. An Important Detail ● When generating IR at this level, you do not need to worry about optimizing it. ● It's okay to generate IR that has lots of unnecessary assignments, redundant computations, etc. ● We'll see how to optimize IR code later this week and at the start of next week. ● It's tricky, but extremely cool!
  • 7. Three-Address Code ● Or “TAC” ● The IR that you will be using for the final programming project. ● High-level assembly where each operation has at most three operands. ● Uses explicit runtime stack for function calls. ● Uses vtables for dynamic dispatch.
  • 8. Sample TAC Code int x; int y; int x2 = x * x; int y2 = y * y; int r2 = x2 + y2;
  • 9. Sample TAC Code int x; int y; int x2 = x * x; int y2 = y * y; int r2 = x2 + y2; x2 = x * x; y2 = y * y; r2 = x2 + y2;
  • 10. Sample TAC Code int a; int b; int c; int d; a = b + c + d; b = a * a + b * b;
  • 11. Sample TAC Code int a; int b; int c; int d; a = b + c + d; b = a * a + b * b; _t0 = b + c; a = _t0 + d; _t1 = a * a; _t2 = b * b; b = _t1 + _t2;
  • 12. Sample TAC Code int a; int b; int c; int d; a = b + c + d; b = a * a + b * b; _t0 = b + c; a = _t0 + d; _t1 = a * a; _t2 = b * b; b = _t1 + _t2;
  • 13. Temporary Variables ● The “three” in “three-address code” refers to the number of operands in any instruction. ● Evaluating an expression with more than three subexpressions requires the introduction of temporary variables. ● This is actually a lot easier than you might think; we'll see how to do it later on.
  • 14. Sample TAC Code int a; int b; a = 5 + 2 * b;
  • 15. Sample TAC Code int a; int b; a = 5 + 2 * b; _t0 = 5; _t1 = 2 * b; a = _t0 + _t1;
  • 16. Sample TAC Code int a; int b; a = 5 + 2 * b; _t0 = 5; _t1 = 2 * b; a = _t0 + _t1; TAC allows for instructions with two operands.
  • 17. Simple TAC Instructions ● Variable assignment allows assignments of the form ● var = constant; ● var1 = var2 ; ● var1 = var2 op var3 ; ● var1 = constant op var2 ; ● var1 = var2 op constant; ● var = constant1 op constant2 ; ● Permitted operators are +, -, *, /, %. ● How would you compile y = -x; ?
  • 18. Simple TAC Instructions ● Variable assignment allows assignments of the form ● var = constant; ● var1 = var2 ; ● var1 = var2 op var3 ; ● var1 = constant op var2 ; ● var1 = var2 op constant; ● var = constant1 op constant2 ; ● Permitted operators are +, -, *, /, %. ● How would you compile y = -x; ? y = 0 – x; y = -1 * x;
  • 19. One More with bools int x; int y; bool b1; bool b2; bool b3; b1 = x + x < y b2 = x + x == y b3 = x + x > y
  • 20. One More with bools int x; int y; bool b1; bool b2; bool b3; b1 = x + x < y b2 = x + x == y b3 = x + x > y _t0 = x + x; _t1 = y; b1 = _t0 < _t1; _t2 = x + x; _t3 = y; b2 = _t2 == _t3; _t4 = x + x; _t5 = y; b3 = _t5 < _t4;
  • 21. TAC with bools ● Boolean variables are represented as integers that have zero or nonzero values. ● In addition to the arithmetic operator, TAC supports <, ==, ||, and &&. ● How might you compile b = (x <= y) ?
  • 22. TAC with bools ● Boolean variables are represented as integers that have zero or nonzero values. ● In addition to the arithmetic operator, TAC supports <, ==, ||, and &&. ● How might you compile b = (x <= y) ? _t0 = x < y; _t1 = x == y; b = _t0 || _t1;
  • 23. Control Flow Statements int x; int y; int z; if (x < y) z = x; else z = y; z = z * z;
  • 24. Control Flow Statements int x; int y; int z; if (x < y) z = x; else z = y; z = z * z; _t0 = x < y; IfZ _t0 Goto _L0; z = x; Goto _L1; _L0: z = y; _L1: z = z * z;
  • 25. Control Flow Statements int x; int y; int z; if (x < y) z = x; else z = y; z = z * z; _t0 = x < y; IfZ _t0 Goto _L0; z = x; Goto _L1; _L0: z = y; _L1: z = z * z;
  • 26. Control Flow Statements int x; int y; int z; if (x < y) z = x; else z = y; z = z * z; _t0 = x < y; IfZ _t0 Goto _L0; z = x; Goto _L1; _L0: z = y; _L1: z = z * z;
  • 27. Labels ● TAC allows for named labels indicating particular points in the code that can be jumped to. ● There are two control flow instructions: ● Goto label; ● IfZ value Goto label; ● Note that IfZ is always paired with Goto.
  • 28. Control Flow Statements int x; int y; while (x < y) { x = x * 2; } y = x;
  • 29. Control Flow Statements int x; int y; while (x < y) { x = x * 2; } y = x; _L0: _t0 = x < y; IfZ _t0 Goto _L1; x = x * 2; Goto _L0; _L1: y = x;
  • 30. A Complete Decaf Program void main() { int x, y; int m2 = x * x + y * y; while (m2 > 5) { m2 = m2 – x; } }
  • 31. A Complete Decaf Program void main() { int x, y; int m2 = x * x + y * y; while (m2 > 5) { m2 = m2 – x; } } main: BeginFunc 24; _t0 = x * x; _t1 = y * y; m2 = _t0 + _t1; _L0: _t2 = 5 < m2; IfZ _t2 Goto _L1; m2 = m2 – x; Goto _L0; _L1: EndFunc;
  • 32. A Complete Decaf Program void main() { int x, y; int m2 = x * x + y * y; while (m2 > 5) { m2 = m2 – x; } } main: BeginFunc 24; _t0 = x * x; _t1 = y * y; m2 = _t0 + _t1; _L0: _t2 = 5 < m2; IfZ _t2 Goto _L1; m2 = m2 – x; Goto _L0; _L1: EndFunc;
  • 33. A Complete Decaf Program void main() { int x, y; int m2 = x * x + y * y; while (m2 > 5) { m2 = m2 – x; } } main: BeginFunc 24; _t0 = x * x; _t1 = y * y; m2 = _t0 + _t1; _L0: _t2 = 5 < m2; IfZ _t2 Goto _L1; m2 = m2 – x; Goto _L0; _L1: EndFunc;
  • 34. A Complete Decaf Program void main() { int x, y; int m2 = x * x + y * y; while (m2 > 5) { m2 = m2 – x; } } main: BeginFunc 24; _t0 = x * x; _t1 = y * y; m2 = _t0 + _t1; _L0: _t2 = 5 < m2; IfZ _t2 Goto _L1; m2 = m2 – x; Goto _L0; _L1: EndFunc;
  • 35. Compiling Functions ● Decaf functions consist of four pieces: ● A label identifying the start of the function. – (Why?) ● A BeginFunc N; instruction reserving N bytes of space for locals and temporaries. ● The body of the function. ● An EndFunc; instruction marking the end of the function. – When reached, cleans up stack frame and returns.
  • 36. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n)
  • 37. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M
  • 38. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M …
  • 39. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1
  • 40. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries
  • 41. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries Stack frame for function g(a, …, m)
  • 42. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries
  • 43. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1
  • 44. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n)
  • 45. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); }
  • 46. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc;
  • 47. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc;
  • 48. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc;
  • 49. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc; main: BeginFunc 4; _t0 = 137; PushParam _t0; LCall _SimpleFn; PopParams 4; EndFunc;
  • 50. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc; main: BeginFunc 4; _t0 = 137; PushParam _t0; LCall _SimpleFn; PopParams 4; EndFunc;
  • 51. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc; main: BeginFunc 4; _t0 = 137; PushParam _t0; LCall _SimpleFn; PopParams 4; EndFunc;
  • 52. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc; main: BeginFunc 4; _t0 = 137; PushParam _t0; LCall _SimpleFn; PopParams 4; EndFunc;
  • 53. Compiling Function Calls void SimpleFn(int z) { int x, y; x = x * y * z; } void main() { SimpleFunction(137); } _SimpleFn: BeginFunc 16; _t0 = x * y; _t1 = _t0 * z; x = _t1; EndFunc; main: BeginFunc 4; _t0 = 137; PushParam _t0; LCall _SimpleFn; PopParams 4; EndFunc;
  • 54. Stack Management in TAC ● The BeginFunc N; instruction only needs to reserve room for local variables and temporaries. ● The EndFunc; instruction reclaims the room allocated with BeginFunc N; ● A single parameter is pushed onto the stack by the caller using the PushParam var instruction. ● Space for parameters is reclaimed by the caller using the PopParams N; instruction. ● N is measured in bytes, not number of arguments.
  • 55. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n)
  • 56. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M PushParam var;
  • 57. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … PushParam var; PushParam var;
  • 58. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 PushParam var; PushParam var; PushParam var;
  • 59. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries PushParam var; PushParam var; PushParam var; BeginFunc N;
  • 60. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries Stack frame for function g(a, …, m) PushParam var; PushParam var; PushParam var; BeginFunc N;
  • 61. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries
  • 62. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 Storage for Locals and Temporaries EndFunc;
  • 63. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1
  • 64. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n) Param M … Param 1 PopParams N;
  • 65. A Logical Decaf Stack Frame Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Stack frame for function f(a, …, n)
  • 66. Storage Allocation ● As described so far, TAC does not specify where variables and temporaries are stored. ● For the final programming project, you will need to tell the code generator where each variable should be stored. ● This normally would be handled during code generation, but Just For Fun we thought you should have some experience handling this. ☺
  • 67. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries
  • 68. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer
  • 69. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer Param M … Param 1
  • 70. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer Param M … Param 1 Storage for Locals and Temporaries
  • 71. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer Param M … Param 1 Storage for Locals and Temporaries
  • 72. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer Param M … Param 1
  • 73. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer
  • 74. The Frame Pointer Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Frame Pointer
  • 75. Logical vs Physical Stack Frames Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries
  • 76. Logical vs Physical Stack Frames Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries fp of caller
  • 77. Logical vs Physical Stack Frames Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries Param N Param N – 1 ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer
  • 78. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer
  • 79. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1
  • 80. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1 fp of caller
  • 81. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1 fp of caller
  • 82. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1 fp of caller Storage for Locals and Temporaries
  • 83. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1 fp of caller
  • 84. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1 fp of caller
  • 85. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer Param N ... Param 1
  • 86. (Mostly) Physical Stack Frames Param N ... Param 1 Storage for Locals and Temporaries fp of caller Frame Pointer
  • 87. The Stored Return Address ● Internally, the processor has a special register called the program counter (PC) that stores the address of the next instruction to execute. ● Whenever a function returns, it needs to restore the PC so that the calling function resumes execution where it left off. ● The address of where to return is stored in MIPS in a special register called ra (“return address.”) ● To allow MIPS functions to call one another, each function needs to store the previous value of ra somewhere.
  • 88. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller
  • 89. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller Param N ... Param 1
  • 90. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller Param N ... Param 1 fp of caller
  • 91. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller Param N ... Param 1 fp of caller ra of caller
  • 92. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller Param N ... Param 1 fp of caller ra of caller
  • 93. Physical Stack Frames Param N ... Param 1 Locals and Temporaries fp of caller Frame Pointer ra of caller Param N ... Param 1 fp of caller ra of caller Locals and Temporaries
  • 94. So What? ● In your code generator, you must assign each local variable, parameter, and temporary variable its own location. ● These locations occur in a particular stack frame and are called fp-relative. Param N ... Param 1 Local 0 fp of caller ra of caller fp ● Parameters begin at address fp + 4 and grow upward. ● Locals and temporaries begin at address fp – 8 and grow downward ... Local M fp + 0 fp + 4 ... fp + 4N fp - 4 fp - 8 ... fp - 4 - 4M
  • 95. From Your Perspective Location* location = new Location(fpRelative, +4, locName);
  • 96. From Your Perspective Location* location = new Location(fpRelative, +4, locName);
  • 97. From Your Perspective Location* location = new Location(fpRelative, +4, locName); What variable does this refer to?
  • 98. And One More Thing... int globalVariable; int main() { globalVariable = 137; }
  • 99. And One More Thing... int globalVariable; int main() { globalVariable = 137; }
  • 100. And One More Thing... int globalVariable; int main() { globalVariable = 137; } Where is this stored?
  • 101. The Global Pointer ● MIPS also has a register called the global pointer (gp) that points to globally accessible storage. ● Memory pointed at by the global pointer is treated as an array of values that grows upward. ● You must choose an offset into this array for each global variable. Global Variable 0 Global Variable 1 ... Global Variable N gp gp + 0 gp + 4 ... gp + 4N
  • 102. From Your Perspective Location* global = new Location(gpRelative, +8, locName);
  • 103. From Your Perspective Location* global = new Location(gpRelative, +8, locName);
  • 104. Summary of Memory Layout ● Most details abstracted away by IR format. ● Remember: ● Parameters start at fp + 4 and grow upward. ● Locals start at fp – 8 and grow downward. ● Globals start at gp + 0 and grow upward. ● You will need to write code to assign variables to these locations.
  • 105. TAC for Objects, Part I class A { void fn(int x) { int y; y = x; } } int main() { A a; a.fn(137); }
  • 106. TAC for Objects, Part I class A { void fn(int x) { int y; y = x; } } int main() { A a; a.fn(137); } _A.fn: BeginFunc 4; y = x; EndFunc; main: BeginFunc 8; _t0 = 137; PushParam _t0; PushParam a; LCall _A.fn; PopParams 8; EndFunc;
  • 107. TAC for Objects, Part I class A { void fn(int x) { int y; y = x; } } int main() { A a; a.fn(137); } _A.fn: BeginFunc 4; y = x; EndFunc; main: BeginFunc 8; _t0 = 137; PushParam _t0; PushParam a; LCall _A.fn; PopParams 8; EndFunc;
  • 108. A Reminder: Object Layout Method 0 Field 0 Vtable* Vtable* ... Field N Field 0 ... Field N Field 0 ... Field M Method 1 ... Method K Method 0 Method 1 ... Method K Method 0 ... Method L
  • 109. TAC for Objects, Part II class A { int y; int z; void fn(int x) { y = x; x = z; } } int main() { A a; a.fn(137); }
  • 110. TAC for Objects, Part II class A { int y; int z; void fn(int x) { y = x; x = z; } } int main() { A a; a.fn(137); } _A.fn: BeginFunc 4; *(this + 4) = x; x = *(this + 8); EndFunc; main: BeginFunc 8; _t0 = 137; PushParam _t0; PushParam a; LCall _A.fn; PopParams 8; EndFunc;
  • 111. TAC for Objects, Part II class A { int y; int z; void fn(int x) { y = x; x = z; } } int main() { A a; a.fn(137); } _A.fn: BeginFunc 4; *(this + 4) = x; x = *(this + 8); EndFunc; main: BeginFunc 8; _t0 = 137; PushParam _t0; PushParam a; LCall _A.fn; PopParams 8; EndFunc;
  • 112. TAC for Objects, Part II class A { int y; int z; void fn(int x) { y = x; x = z; } } int main() { A a; a.fn(137); } _A.fn: BeginFunc 4; *(this + 4) = x; x = *(this + 8); EndFunc; main: BeginFunc 8; _t0 = 137; PushParam _t0; PushParam a; LCall _A.fn; PopParams 8; EndFunc;
  • 113. Memory Access in TAC ● Extend our simple assignments with memory accesses: ● var1 = *var2 ● var1 = *(var2 + constant) ● *var1 = var2 ● *(var1 + constant) = var2 ● You will need to translate field accesses into relative memory accesses.
  • 114. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); }
  • 115. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); }
  • 116. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); } _Base.hi: BeginFunc 4; _t0 = "Base"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Base = _Base.hi, ; _Derived.hi: BeginFunc 4; _t0 = "Derived"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Derived = _Derived.hi, ;
  • 117. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); } _Base.hi: BeginFunc 4; _t0 = "Base"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Base = _Base.hi, ; _Derived.hi: BeginFunc 4; _t0 = "Derived"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Derived = _Derived.hi, ;
  • 118. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); } _Base.hi: BeginFunc 4; _t0 = "Base"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Base = _Base.hi, ; _Derived.hi: BeginFunc 4; _t0 = "Derived"; PushParam _t0; LCall _PrintString; PopParams 4; EndFunc; Vtable Derived = _Derived.hi, ;
  • 119. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc;
  • 120. TAC for Objects, Part III class Base { void hi() { Print("Base"); } } class Derived extends Base{ void hi() { Print("Derived"); } } int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; What's going on here?
  • 121. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc;
  • 122. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; hi Derived Vtable Code for Derived.hi
  • 123. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi
  • 124. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi
  • 125. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b
  • 126. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b
  • 127. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4
  • 128. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4
  • 129. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 Param 1 4
  • 130. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 Param 1 4
  • 131. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 Param 1 4 (raw memory)
  • 132. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 Param 1 4 (raw memory)
  • 133. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory)
  • 134. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory)
  • 135. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory) Allocate Object
  • 136. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory) Allocate Object
  • 137. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory) Allocate Object
  • 138. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 (raw memory) Allocate Object
  • 139. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object
  • 140. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object
  • 141. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 142. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 143. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 144. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 145. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 146. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable
  • 147. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Allocate Object Set Vtable Load Function
  • 148. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Load Function Allocate Object Set Vtable
  • 149. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Param 1 Load Function Allocate Object Set Vtable
  • 150. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Param 1 Load Function Allocate Object Set Vtable
  • 151. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Param 1 Load Function Allocate Object Set Vtable
  • 152. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Load Function Allocate Object Set Vtable
  • 153. Dissecting TAC int main() { Base b; b = new Derived; b.hi(); } main: BeginFunc 20; _t0 = 4; PushParam _t0; b = LCall _Alloc; PopParams 4; _t1 = Derived; *b = _t1; _t2 = *b; _t3 = *_t2; PushParam b; ACall _t3; PopParams 4; EndFunc; fp of caller ra of caller hi Derived Vtable Code for Derived.hi _t0 _t1 _t2 _t3 b 4 VTable* Load Function Allocate Object Set Vtable
  • 154. OOP in TAC ● The address of an object's vtable can be referenced via the name assigned to the vtable (usually the object name). ● e.g. _t0 = Base; ● When creating objects, you must remember to set the object's vtable pointer or any method call will cause a crash at runtime. ● The ACall instruction can be used to call a method given a pointer to the first instruction.
  • 156. TAC Generation ● At this stage in compilation, we have ● an AST, ● annotated with scope information, ● and annotated with type information. ● To generate TAC for the program, we do (yet another) recursive tree traversal! ● Generate TAC for any subexpressions or substatements. ● Using the result, generate TAC for the overall expression.
  • 157. TAC Generation for Expressions ● Define a function cgen(expr) that generates TAC that computes an expression, stores it in a temporary variable, then hands back the name of that temporary. ● Define cgen directly for atomic expressions (constants, this, identifiers, etc.). ● Define cgen recursively for compound expressions (binary operators, function calls, etc.)
  • 158. cgen for Basic Expressions
  • 159. cgen for Basic Expressions cgen(k) = { // k is a constant Choose a new temporary t Emit( t = k ); Return t }
  • 160. cgen for Basic Expressions cgen(k) = { // k is a constant Choose a new temporary t Emit( t = k ); Return t } cgen(id) = { // id is an identifier Choose a new temporary t Emit( t = id ) Return t }
  • 161. cgen for Binary Operators
  • 162. cgen for Binary Operators cgen(e1 + e2 ) = { Choose a new temporary t Let t1 = cgen(e1 ) Let t2 = cgen(e2 ) Emit( t = t1 + t2 ) Return t }
  • 163. An Example cgen(5 + x) = { Choose a new temporary t Let t1 = cgen(5) Let t2 = cgen(x) Emit (t = t1 + t2 ) Return t }
  • 164. An Example cgen(5 + x) = { Choose a new temporary t Let t1 = { Choose a new temporary t Emit( t = 5 ) return t } Let t2 = cgen(x) Emit (t = t1 + t2 ) Return t }
  • 165. An Example cgen(5 + x) = { Choose a new temporary t Let t1 = { Choose a new temporary t Emit( t = 5 ) return t } Let t2 = { Choose a new temporary t Emit( t = x ) return t } Emit (t = t1 + t2 ) Return t }
  • 166. An Example cgen(5 + x) = { Choose a new temporary t Let t1 = { Choose a new temporary t Emit( t = 5 ) return t } Let t2 = { Choose a new temporary t Emit( t = x ) return t } Emit (t = t1 + t2 ) Return t } _t0 = 5 _t1 = x _t2 = _t0 + _t1
  • 167. cgen for Statements ● We can extend the cgen function to operate over statements as well. ● Unlike cgen for expressions, cgen for statements does not return the name of a temporary holding a value. ● (Why?)
  • 168. cgen for Simple Statements
  • 169. cgen for Simple Statements cgen(expr;) = { cgen(expr) }
  • 170. cgen for while loops
  • 171. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 172. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 173. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 174. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 175. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 176. cgen for while loops cgen(while (expr) stmt) = { Let Lbefore be a new label. Let Lafter be a new label. Emit( Lbefore :) Let t = cgen(expr) Emit( IfZ t Goto Lafter ) cgen(stmt) Emit( Goto Lbefore ) Emit( Lafter : ) }
  • 177. Next Time ● Intro to IR Optimization ● Basic Blocks ● Control-Flow Graphs ● Local Optimizations