Compilation 2016
Activation Records
Aslan Askarov aslan@cs.au.dk Revised from slides by E. Ernst
Activation Records Aslan Askarov aslan@cs.au.dk Revised from slides - - PowerPoint PPT Presentation
Compilation 2016 Activation Records Aslan Askarov aslan@cs.au.dk Revised from slides by E. Ernst (Abstract) computer organization Program memory } code segment contains program text size fixed prior to runtime data
Aslan Askarov aslan@cs.au.dk Revised from slides by E. Ernst
data (globals)
registers/memory
size fixed prior to runtime
size changes at runtime
Higher addresses in memory Low addresses in memory contiguous region in memory that the program can use the stack grows from higher memory addresses to low
depending on architecture) Purpose of the stack:
stack limit – set by OS
Higher addresses in memory Low addresses in memory contiguous region in memory that the program can use the stack grows from higher memory addresses to low
depending on architecture) Purpose of the stack:
stack limit – set by OS
Q: what happens if we push past beyond stack limit?
Function 1 Function 1 Function 1 Function 2 Function 2 Function 2 Function 2 Function 2 Function 3 Function 3 Function 3 Function 3
Function 1 calls Function 2 that calls Function 3 active functions, because they haven’t returned yet
stack manipulations by each of the functions
Idea: the maximum amount of memory that each function needs for its locals, temps, etc can be (usually) pre- computed by the compiler Let’s increase the stack by that much at once instead
Call the region of the stack corresponding to each active function that function’s stack frame (also called activation record)
Function 1 Function 1 Function 1 Function 2 Function 2 Function 2 Function 2 Function 2 Function 3 Function 3 Function 3 Function 3
Function 1 calls Function 2 that calls Function 3 active functions, because they haven’t returned yet
stack manipulations by each of the functions
activation record (or stack frame) for Function 1 stack frame for Function 2 stack frame for Function 3
activation record for Function 1 activation record for Function 2
Not allocated: garbage
FP SP Stack pointer (SP): points to the “top”
Frame pointer (FP): the value of SP at the time the frame got activated
important: using libraries
standard: ‘calling convention’
register usage, routine entry, exit code
argument 2 argument 1 returnAddr localvar1 localvar2 … storedR1 … temp1 …
Not allocated: garbage
FP SP
MIPS) well
are all known at compile time?
fixed
(prev. frame) arg_k … arg_1 staticLink localVar_1 … localVar_m returnAddr temp_1 … temp_p saved_R1 … saved_Rt …
(args for next)
FP SP
usage strategy
automatically by call instruction
arguments pushed
(prev. frame) arg_k … arg_1 staticLink saved_FP localVar_1 … localVar_m returnAddr temp_1 … temp_p
FP
nextArg_k nextArg_2 nextArg_1
SP SP SP
saved_FP localVar_1 ... localVar_m temp_1 ... temp_p ... (args for next)
FP
SP
(prev.frame) ... arg_k ... arg_1 staticLink returnAddr
SP SP SP
Memory[FP] Memory[FP-8*1] Memory[FP-who_cares] Memory[FP+8] Memory[saved_FP], Memory[FP+16] Memory[FP+8*(2+1)] Memory[FP+8*(2+k)] Memory[FP-8*m] Memory[FP-8*(m+1)] Memory[FP-8*(m+p)] Memory[staticLink]?
Top of frame: known early Bottom: known later
SP - frameSize (‘virtual’ FP)
(prev.frame) ...
SP FP
, RBX, and R12–R15 are callee-save registers, i.e., preserved across function calls
localVar_1 ... localVar_m returnAddr ... saved_a1 ... staticLink (prev.frame) ... saved_Ri ... staticLink
f frame localVar_1 ... g frame
is lexically scoped
argument (static link)
frame at all nesting levels
type tree = {key: string, left: tree, right: tree} function prettyprint(tree: tree): string = let var output := " " function write(s: string) =
function show(n: int, t: tree) = let function indent(s: string) = ( for i:=1 to n do write(" ") ; output := concat(output,s) ; write("\n")) in if t=nil then indent(".") else ( indent(t.key) ; show(n+1, t.left) ; show(n+1, t.right)) end in show(0,tree);
[write] [indent] [show] [prettyprint] [show]
wanted saved FP
⋮
type tree = {key: string, left: tree, right: tree} function prettyprint(tree: tree): string = let var output := " " function write(s: string) =
function show(n: int, t: tree) = let function indent(s: string) = ( for i:=1 to n do write(" ") ; output := concat(output,s) ; write("\n")) in if t=nil then indent(".") else ( indent(t.key) ; show(n+1, t.left) ; show(n+1, t.right)) end in show(0,tree);
[write] [indent] [show] [prettyprint] [show]
wanted saved FP
⋮
static link
type tree = {key: string, left: tree, right: tree} function prettyprint(tree: tree): string = let var output := " " function write(s: string) =
function show(n: int, t: tree) = let function indent(s: string) = ( for i:=1 to n do write(" ") ; output := concat(output,s) ; write("\n")) in if t=nil then indent(".") else ( indent(t.key) ; show(n+1, t.left) ; show(n+1, t.right)) end in show(0,tree);
SL = FP Case “call nested”: Static link for show from prettyprint is the frame of prettyprint itself, etc. SL = FP
type tree = {key: string, left: tree, right: tree} function prettyprint(tree: tree): string = let var output := " " function write(s: string) =
function show(n: int, t: tree) = let function indent(s: string) = ( for i:=1 to n do write(" ") ; output := concat(output,s) ; write("\n")) in if t=nil then indent(".") else ( indent(t.key) ; show(n+1, t.left) ; show(n+1, t.right)) end in show(0,tree);
Case “call same”: Static link for show from show is the given static link SL = SL
type tree = {key: string, left: tree, right: tree} function prettyprint(tree: tree): string = let var output := " " function write(s: string) =
function show(n: int, t: tree) = let function indent(s: string) = ( for i:=1 to n do write(" ") ; output := concat(output,s) ; write("\n")) in if t=nil then indent(".") else ( indent(t.key) ; show(n+1, t.left) ; show(n+1, t.right)) end in show(0,tree);
Case “call outer”: Static link for write from indent is found by following the static link twice SL = SL.SL
registers and addresses, environment update