![Nested Functions Activation Trees Let Type Intarray = Array of Int Main Var a := Intarray [9] of 0 Function Readarray () =](https://data.docslib.org/img/3a60ab92a6e30910dab9bd827208bcff-1.webp)
CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Tiger Runtime Environments Typical Runtime Layout • Compile-time environments are just symbol tables; they are used to assist static semantic analysis, code generation and code optimization. STACK (activation records) parameters and program returned values • Run-time environments are about how to map each runtime value into the counter memory? more specifically, here are the main issues links and saved status code how to implement procedure (or function) call ? --- stack frames temporaries (activation records, access to non-local variables, parameter passing,...) and local data Activation Record what are the data representations ? (primitive data type, records, arrays, dynamic data structure, ...) HEAP (dynamic data) what are the memory layout (i.e., storage organization) ? (where to put the static data, code segments, stack, heap?) REGISTERS STATIC garbage (code and globals) collector how to do the memory allocation and de-allocation ? (malloc-free package, garbage collection, ...) Memory Layout Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 1 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 2 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Example: Nested Functions Activation Trees let type intArray = array of int main var a := intArray [9] of 0 function readarray () = ... function writearray () = ... function exchange(x : int, y : int) = readarray q(0,8) writearray let var z := a[x] in a[x] := a[y]; a[y] := z end function quicksort(m : int, n : int) = let function partition(y : int, z : int) : int = p(0,8) q(0,3) q(5,8) let var i := y var j := z + 1 in (while (i < j) do (i := i+1; while a[i] < a[y] do i := i+1; j := j-1; while a[j] > a[y] do j := j-1; e(1,8) e(2,7) e(4,5) e(0,4) if i < j then exchange(i,j)); exchange(y,j); j) p(0,3) q(0,2) q(4,3) p(5,8) q(5,7) q(9,8) end in if n > m then (let var i := partition(m,n) input: 10, 32, e(0,3) p(0,2) q(0,0) q(2,2) e(6,9) in quicksort(m, i-1); 567, -1, 789, quicksort(i+1, n) 3, 18, 0, -51 p(5,7) q(5,5) q(8,8) end) input: 10, 32, e(0,1) end 567, -1, 789, p -> partition in readarray(); quicksort(0,8); writearray() 3, 18, 0, -51 q -> quicksort e(5,6) end e -> exchange Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 3 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 4 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Activations Activation Record • Each function (or procedure) declaration associates a name with a function •An activation record is constructed when a function (or a procedure) is called body --------- this binding is done at compile time. (activated); it is destroyed when the function returns; the interim is the lifetime of the activation. •An activation is created during runtime execution when the function (or procedure) is invoked. The lifetime of an activation is the time between • The activation record often contains the following: execution of the 1st operation of the body and through the last operation. relevant machine state (saved registers, return address) • Activations are either nested or non-overlapping. If two activations are nested, space for local data, including temporaries then one must be the descendant of another. If two activations are non- space for return value overlapping, then they must be the siblings. space for outgoing arguments • A function f is recursive if more than 2 activations of f is nested. control link: pointer to caller’s activation record (optional) static link: pointer to activation for accessing non-local data • Program execution is just depth-first traversal of activation tree ! • Main problem: how to layout the activation record so that the caller and callee How to implement depth-first traversal ? can communicate properly ? Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 5 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 6 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Stack Frames Stack Frames (cont’d) • The most common (and standard) way is to allocate activation records on a • Frame Pointer (FP) is a pointer that points to the start of the current frame; sequential stack --- using the following standard frame layout. Stack Pointer (SP) --- referring to the top of the stack ---- points to the end of the current frame. argument a previous function f (..)= incoming n ... frame f ...g(a ,...,a )... offset parameters 1 n -4n-4 argument a previous argument a2 n caller ... ... frame f argument a1 static link frame pointer FP for g -12 argument a2 caller -8 argument a1 local variables -4 static link frame pointer FP for g callee 0 return address 4 local variables callee temporaries .... return address saved registers current function g(..)= current temporaries frame g frame g ...h(b1,...,bm)... saved registers argument bm ... outgoing argument b ......................... stack pointer SP for g parameters 2 argument b1 static link stack pointer SP for g All ’s arguments and local variables are accessed through FP ! next frame h g Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 7 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 8 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Typical Calling Sequence Typical Calling Sequence (cont’d) • Question: Suppose function f calls function g(a1,...,an), what will • 3. Return sequence ( the callee g exits and returns back to f ) happen at runtime ? how f and g communicate ? Assuming FP and SP are put the return result into a designated register in two registers. (optional: restore calleesave registers if any) fetch the return address to a register (if in register, do nothing) • 1. Call sequence (done by the caller f before entering g ) fetch the saved FP of f back to the FP register f puts arguments a1,...,an onto the stack (or in registers) increment SP by the frame size of g (pop off the activation of g) f puts function g’s static link onto the stack (or in a register) Return back to f f puts the return address of this call to g onto the stack (or in a register) • Tiger Specifics (also true for many other modern compilers) f puts current FP onto the stack (i.e., control link, optional) Jump to g’s code return address is put in a designated register • 2. Entry sequence (the first thing done after entring the callee g ) only maintain SP at runtime (FP is a “virtual” reg. = SP - framesize) (when implementing Tiger, frame-size of each function is a compile-time constant) move SP to FP • Must maintain a separate FP and SP if (1) the frame size of a function may decrement SP by the frame size of g (stack grows downwards!!!) vary (2) the frames are not always contiguous (e.g., linked list) (optional: save callee-save registers if any) Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 9 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 10 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS A Snapshot of Running Quicksort Non-Local Variables • Remaining questions: how to find the 1let type intArray = array of int main() var a := intArray [9] of 0 a value of local variables and non-local 2 function readarray () = ... m=0,n=8 function writearray () = ... variables ? 2 function exchange(x : int, y : int) = q(0,8) 2 let var z := a[x] in a[x] := a[y]; a[y] := z end i=4 • Local variables are allocated in the m=0,n=3 2 function quicksort(m : int, n : int) = current stack frame --- we can access let function partition(y : int, z : int) : int = q(0,3) 3 let var i := y var j := z + 1 i=3 them through the Frame Pointer (notice, in (while (i < j) do y=0,z=3 the actual value of FP is unknown until (i := i+1; while a[i] < a[y] do i := i+1; nesting j := j-1; while a[j] > a[y] do j := j-1; p(0,3) runtime, but the each local-variable’s depth if i < j then exchange(i,j)); i=4,j=3 exchange(y,j); j) x=0,y=3 offset to FP is known at compile time) end FP e(0,3) in if n > m then (let var i := partition(m,n) z • Non-local variables must be accessed in quicksort(m, i-1); through the static link, or by using some quicksort(i+1, n) SP end) input: 10, 32, other tricks ...... end 567, -1, 789, in readarray(); quicksort(0,8); writearray() 3, 18, 0, -51 end Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 11 of 24 Copyright 1994 - 2015 Zhong Shao, Yale University Runtime Environments: Page 12 of 24 CS421 COMPILERS AND INTERPRETERS CS421 COMPILERS AND INTERPRETERS Static Link Static Link (cont’d) • Static link (also called access link) is used main() • Suppose function q at depth nq calls function p at depth np . The question is how a to implement lexical scoping. to access non-local variables once we are inside p ? or what is the static link m=0,n=8 inside p’s activation. q(0,8) • If function p is nested immediately within i=4 q in the source code, then the static link in m=0,n=3 •If nq < np , then nq = np -1, p is nested within q; the static link in p’s activation activation of p is a point to the most = q’s activation; e.g., calls .
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages6 Page
-
File Size-