Procedure Calls and Intermediate Code - PowerPoint PPT Presentation

1 / 44
About This Presentation
Title:

Procedure Calls and Intermediate Code

Description:

Heap: 0: stack pointer. 1: 1. 2: 2. 3: 3. Code: 0 a: 1 2 t1 ... Heap: 0: stack pointer. 1: 3. 2: 4. Push x then y on the stack. Room for return value and call ... – PowerPoint PPT presentation

Number of Views:27
Avg rating:3.0/5.0
Slides: 45
Provided by: cbo4
Category:

less

Transcript and Presenter's Notes

Title: Procedure Calls and Intermediate Code


1
Procedure Calls and Intermediate Code
  • A simple functional language
  • Creating a function
  • Calling a function

Token Stream
Parser
Memory
Intermediate Code
Making It Real
This is very closely related to Project 3!
2
Miniature functional language
  • I wanted to create the most simple functional
    language I could think of.

a 1 b 2 3
a 1 3 b a 4 c x y x y d c a 1
  • Im calling this language miniature

3
Basics
a 1 3 b a 4 c x y x y d c a 1
  • Every statement is a function definition
  • a 1 3
  • Creates a function that computes 1 3 and
    returns the value

a 1 3
There are no variables, everything is a function,
just like in Haskell
4
The functional program
Available on the class web site.
5
Our intermediate code
New operations at the bottom!
6
My memory layout
0 Stack pointer
1 Constants
1 Temporaries
Free Memory
Location 0 is our stack pointer. Constants start
at location 1. Temporary values start at location
t1. (internally, I used negative numbers for
temporary values). Memory locations are words
(floats or ints)
Stack
7
Temporaries
Stack pointer
Constants
Temporaries
Temporaries are our substitute for registers. A
real function will save off all used registers
when it starts and restore when done. Well just
assume that is done (you can make your emulator
do that easily). It makes no sense to create a
lot of pushes for the many intermediate values we
create when we dont know what our register
allocation will look like in the final code.
This strategy works very well for our simple
functional language.
8
Temporaries
  • call
  • Creates a new bank of temporary variables and
    pushes onto a stack
  • return
  • Pops the back of temporary variables off the stack

9
My stack model
Parameter 1
SP 4
Parameter 2
SP 3
Return value
SP 2
Return address
SP 1
Stack pointer
I use the model of push as store/decrement. You
could just as easily do decrement/store. The
results are almost identical.
10
miniature
x 3 6 Defines a function x that computes 3
6. All function definitions end with a
semicolon. y x 9 Functions can be used as
arguments. x a b a b Defines a function
that accepts two arguments a and b. Arguments can
be used in the function. How can it tell a
parameter from a function? z x 7 8 We pass
parameters just like Haskell does. Does not allow
unary minus on any parameter, though z x 7
-8 is not valid (why?) To use unary minus, use
parens z x 7 (-8)
miniature uses only floating point numbers (only
one type).
11
What code should this generate
a 1
TT
12
What code should this generate
a 1
Return value
SP 2
Return address
SP 1
Stack pointer
miniature 1.0! Heap 0 stack pointer 1
1 Code 0 a addi 0 2 t1 1
() 1 0 t1 2
ret 0 0 0
Location of the constant 1
13
A bit fancier
Return value
SP 2
Return address
a 1 2
SP 1
Stack pointer
TT
14
A bit fancier
Return value
SP 2
Return address
a 1 2
SP 1
Stack pointer
miniature 1.0! Heap 0 stack pointer 1 1 2
2 Code 0 a 1 2
t1 1 addi 0 2 t2 2
() t1 0 t2 3
ret 0 0 0
15
And more...
a 1 2 3
Return value
SP 2
Return address
SP 1
Stack pointer
miniature 1.0! Heap 0 stack pointer 1 1 2
2 3 3 Code 0 a 1 2
t1 1 t1 3
t2 2 addi 0 2
t3 3 () t2 0
t3 4 ret 0 0 0
16
How to call
a 1 b a
Return value
SP 1
Return address
Stack pointer
After the return
Code 0 a addi 0 2
t1 1 () 1 0
t1 2 ret 0 0
0 3 b subi 0 1 0 4
call 0 0 0 5
addi 0 1 0 6
() 0 0 t1 7
addi 0 2 t2 8 ()
t1 0 t2 9 ret
0 0 0
Leave space for return value
sp now points at return value
t1 now contains return value
returns bs result
TT
17
Parameters
x
SP 4
y
SP 3
a x y x y b a 3 4
Return value
SP 2
Return address
SP 1
Stack pointer
0 a addi 0 4 t1 1
() t1 0 t1 2
addi 0 3 t2 3
() t2 0 t2 4
t1 t2 t3 5 addi
0 2 t4 6 () t3
0 t4 7 ret 0
0 0
SP 3 is x, x goes into t1
SP 4 is y, y goes into t2
SP 2 is the return value
Heres the function implementation
18
Parameters
x
SP 4
y
SP 3
a x y x y b a 3 4
Return value
SP 2
Return address
SP 1
Stack pointer
Given the expected stack frame above, how would
be implement function b?
TT
19
Parameters
x
SP 4
Heap 0 stack pointer 1 3 2 4
y
SP 3
a x y x y b a 3 4
Return value
SP 2
Return address
SP 1
Stack pointer
8 b param 1 0 0 9
param 2 0 0 10
subi 0 1 0 11 call
0 0 0 12 addi 0
1 0 13 () 0 0
t1 14 addi 0 2
0 15 addi 0 2 t2 16
() t1 0 t2 17
ret 0 0 0
Push x then y on the stack
Room for return value and call
Get result and restore stack
Normal return
Heres the function call
20
Our Grammar
program stmts stmts stmts stmt stmts
stmt stmt SYM parms '' E '' parms
parms SYM parms E E '' T E E '-'
T E T T T '' F T T '/' F T
F F '(' E ')' F '-' F F
FLOAT_VALUE F SYM parms1 parms1 parms1
SYM parms1 parms1 FLOAT_VALUE parms1 parms1
'(' E ')' parms1
0 or more parameters c x y x y
a 1 3 b a 4 c x y x y d c a 1
Expressions
Function calls b a 4
0 or more parameters on the call d c a 1 e c
(a a) (b d)
21
A function
stmt SYM func parms '' E '' int t
NewTemp() Statement("addi", 0, 2, t)
Statement("()", 5, 0, t) Statement("ret",
0, 0, 0)
Creates a new temp location
func FunctionBegin(ltsvalgt0)
free(ltsvalgt0)
15 addi 0 2 t2 16
() t1 0 t2 17
ret 0 0 0
Generated code example
22
FunctionBegin...
struct Function stdstring name int addr
int parmCnt stdmapltstdstring,
intgt parms
void CCompileFunctionBegin(const char
name) // The function address is the current
address Function f f.addr Addr() f.name
name f.parmCnt 0 m_functionsname
f m_functionsByAddrf.addr
name m_currentFunction (m_functionsname)
// Start the temporaries again m_temp -1
Keeps track of current function we are defining
Temporaries are allocated as -1, -2, etc. We
start over for every function. How could you
execute code like that?
23
Parameters
stmt SYM parms '' E ''
struct Function stdstring name int addr
int parmCnt stdmapltstdstring,
intgt parms
parms parms SYM FunctionParameter(2)
free(2) parms
void CCompileFunctionParameter(const char
name) m_currentFunction-gtparmsname
m_currentFunction-gtparmCnt
We just number our parameters starting at zero.
24
Parameters
x
SP 4
y
SP 3
Return value
SP 2
Return address
SP 1
Stack pointer
parms parms SYM FunctionParameter(2)
free(2) parms
void CCompileFunctionParameter(const char
name) m_currentFunction-gtparmsname
m_currentFunction-gtparmCnt
struct Function stdstring name int addr
int parmCnt stdmapltstdstring,
intgt parms
TT
25
Youll recognize all of this...
E E '' T int t NewTemp() Statement("",
1, 3, t) t E E '-' T int t
NewTemp() Statement("-", 1, 3, t)
t E T 1 T T '' F int t
NewTemp() Statement("", 1, 3, t)
t T T '/' F int t NewTemp()
Statement("/", 1, 3, t) t T F
1 F '(' E ') 2 F '-' F int t
NewTemp() Statement("neg", 2, 0, t)
t F FLOAT_VALUE CreateConstant(1)
Okay, neg is new, but pretty obvious...
26
What about F SYM?
F SYM
What did this do before?
27
Actually, it may be what?
F SYM ???
a x y x y b a 3
28
Actually, it may be what?
F SYM ???
Parameter
a x y x y b a 3
Function call
How do you tell them apart?
29
x
F SYM parms1 int t int a tNewTemp()
t / A symbol can be a function or a
parameter / a FunctionParameterAddress(1) i
f(a gt 0) / This is a parameter
/ Statement("addi", 0, a 3,
t) Statement("()", t, 0, t) else
/ This is a function call / Statement("subi",
0, 1, 0) Statement("call", 0, 0,
FunctionAddress(1)) Statement("addi", 0,
1, 0) Statement("()", 0, 0, t) if(2 gt
0) Statement("addi", 0, 2,
0) free(1)
SP 4
y
SP 3
Return value
SP 2
Return address
SP 1
Stack pointer
Get the parameter
Call the function
TT
30
x
F SYM parms1 int t int a tNewTemp()
t / A symbol can be a function or a
parameter / a FunctionParameterAddress(1) i
f(a gt 0) / This is a parameter
/ Statement("addi", 0, a 3,
t) Statement("()", t, 0, t) else
/ This is a function call / Statement("subi",
0, 1, 0) Statement("call", 0, 0,
FunctionAddress(1)) Statement("addi", 0,
1, 0) Statement("()", 0, 0, t) if(2 gt
0) Statement("addi", 0, 2,
0) free(1)
SP 4
y
SP 3
Return value
SP 2
Return address
Stack pointer
Get the parameter
0 a addi 0 4 t1 1
() t1 0 t1 2
addi 0 3 t2 3
() t2 0 t2 4
t1 t2 t3 5 addi
0 2 t4 6 () t3
0 t4 7 ret 0
0 0
SP 3 is x, x goes into t1
SP 4 is y, y goes into t2
SP 2 is the return value
31
int CCompileFunctionParameterAddress(const char
name) mapltstring, intgtiterator a
m_currentFunction-gtparms.find(name) if(a
m_currentFunction-gtparms.end()) return
-1 return (m_currentFunction-gtparmCnt -
a-gtsecond - 1)
Why all of this?
32
F SYM parms1 int t int a tNewTemp()
t / A symbol can be a function or a
parameter / a FunctionParameterAddress(1) i
f(a gt 0) / This is a parameter
/ Statement("addi", 0, a 3,
t) Statement("()", t, 0, t) else
/ This is a function call / Statement("subi",
0, 1, 0) Statement("call", 0, 0,
FunctionAddress(1)) Statement("addi", 0,
1, 0) Statement("()", 0, 0, t) if(2 gt
0) Statement("addi", 0, 2,
0) free(1)
3 b subi 0 1 0 4
call 0 0 0 5
addi 0 1 0 6
() 0 0 t1 7
addi 0 2 t2 8 ()
t1 0 t2 9 ret
0 0 0
Skip over any parameters
33
What about passing parameters?
8 b param 1 0 0 9
param 2 0 0 10
subi 0 1 0 11 call
0 0 0
parms1 parms1 FLOAT_VALUE int t
CreateConstant(2) Statement("param", t, 0,
0) 1 1 parms1 parms1 '(' E
') Statement("param", 3, 0, 0) 1
1 parms1 0
What is the value of parms1 doing?
TT
34
Other issues?
  • Types?

b Float a Float, Float -gt Float b a 3
4 a x y x y
Ideas? Better start thinking about it!
TT
35
More issues?
Passing a function to a function (Why would we
want to do this?)
a Float -gt Float b (Float -gt Float) -gt
Float a x x - 13 b p p 5 2
TT
36
Haskell types
module Main where a Float a 7 b Float
-gt Float b x x x c (Float -gt Float) -gt
Float c x (x 7) main c b
37
Forward References
module Main where a Float b Float -gt
Float c (Float -gt Float) -gt Float main c
b a 7 b x x x c x (x 7)
Haskell is actually quite forgiving. It will let
you forward reference without a formal type
declaration, but were going to require the
formal type declaration in our project (why?)
38
An emulator (interpreter)
void Push(float val) m_heap(int)m_heap0
val m_heap0 m_heap0 - 1
void CCompileInterpreter(const stdstring
name) // Set program counter to point to the
function m_PC FunctionAddress(name.c_str())
// Turn the heap into a memory with a stack //
and set the stack pointer to the last location
// in the heap m_heap.resize(m_heap.size()
StackSize) m_heap0 (float)m_heap.size() -
1 // // Create a location for a return value.
Then, // push a negative return address so
we'll know when we are done. // int retAddr
(int)m_heap0 Push(0) Push(-1) // Create
an initial set of temporaries m_tempStack.push_b
ack(vectorltfloatgt())
39
Instruction processing
struct TAC stdstring name int a1 int
a2 int a3
while(m_PC gt 0) const TAC tac
m_codem_PC m_PC const string inst
tac.name if(inst "") SetValueAt(tac.
a3, GetValueAt(tac.a1) GetValueAt(tac.a2))
else if(inst "-") SetValueAt(tac.a3,
GetValueAt(tac.a1) - GetValueAt(tac.a2)) ..
.
40
Get/SetValueAt
void CCompileSetValueAt(int addr, float
val) if(addr lt 0) // Location is in the
temporaries if((float)m_tempStack.back().size()
lt -addr) m_tempStack.back().resize(-addr
1) m_tempStack.back()-addr
val else m_heapaddr val
float CCompileGetValueAt(int addr) if(addr lt
0) // Location is in the temporaries if((fl
oat)m_tempStack.back().size() lt
-addr) m_tempStack.back().resize(-addr
1) return m_tempStack.back()-addr e
lse return m_heapaddr
41
Indirect functions
else if(inst "()") int dest
(int)GetValueAt(tac.a3) SetValueAt(dest,
GetValueAt(tac.a1)) else if(inst
"()") int src (int)GetValueAt(tac.a1)
SetValueAt(tac.a3, GetValueAt(src))
42
Call/Return
else if(inst "call") if(tac.a3 lt
0) // This is a library
function LibraryFunction(tac.a3) else
// Create a new temporaries
frame m_tempStack.push_back(vectorltfloatgt())
Push(m_PC) // Push return address onto
stack m_PC tac.a3 else if(inst
"ret") // Pop the most recent
temporaries frame m_tempStack.pop_back() P
op() m_PC (int)m_heap(int)m_heap0
else if(inst "param") float val
GetValueAt(tac.a1) Push(val)
43
Call/Return
else if(inst "call") if(tac.a3 lt
0) // This is a library
function LibraryFunction(tac.a3) else
// Create a new temporaries
frame m_tempStack.push_back(vectorltfloatgt())
Push(m_PC) // Push return address onto
stack m_PC tac.a3 else if(inst
"ret") // Pop the most recent
temporaries frame m_tempStack.pop_back() P
op() m_PC (int)m_heap(int)m_heap0
else if(inst "param") float val
GetValueAt(tac.a1) Push(val)
44
Library functions
void CCompileLibraryFunction(int id) // What
is the name of the function? const string name
m_functionsByAddrid // Get a frame
pointer // This points to the return address
location int sp (int)m_heap0 1 if(name
"print") cout ltlt m_heapsp 1 ltlt
endl m_heapsp 0
Library functions are done by the emulator itself
and then we just advance to the next instruction.
Whats the criteria for a reasonable library
function?
Write a Comment
User Comments (0)
About PowerShow.com