180 likes | 190 Views
Programming languages support the binding of names with complex program fragments through an interface, allowing programmers to focus on the purpose rather than the implementation of the fragment. This includes control abstractions, such as subroutines, and data abstractions, such as data structures.
E N D
Control Abstraction(Section 8.1-8.2) CSCI 431 Programming Languages Fall 2003 A compilation of material developed by Felix Hernandez-Campos and Michael Scott
Abstraction • Programming languages support the binding of names with potentially complex program fragments that can be used through an interface • Programmers only need to know about the purpose of the fragment rather than its implementationAbstraction • A control abstraction performs a well-defined operation • Subroutines • A data abstraction represents information • Data structures • Most data structures include some number of control abstractions
Subroutines • Execute an operation on behalf of a calling program unit • Subroutines can be parameterized • The parameters in the definition of the function are known as formal parameters • The parameters passed in the subroutine call are known as actual parameters or arguments • At the time of the call, actual parameters are mapped to formal parameters • Functions are subroutines that return a value, while procedures are subroutines that do not return a value
Actual Parameters Formal Parameters Subroutine Frames • Each subroutines requires a subroutine frame (a.k.a activation record) to keep track of • Arguments and return values • Local variables and temporaries • Bookkeeping information • When a subroutine returns, its frame is removed 1001: A(3) … 2001: int A(int n) { int m = n * n; return m + A(n-1); }
Call StackRecursive Subroutine A A A A A A
Static chain - composed of static links: • Static link - from a subroutine to the lexically surrounding subroutine • Disadvantage - Stack Layout • In a language with nested subroutines - how can we access non-local objects? • static chain • display to access an object k levels deeper → need to dereference k pointers
Stack Layout • Display: • Element j in display - reference to most recently called subroutine at lexical nesting level j • From a subroutine at lexical level i, to access an object k levels outwards: • follow only one pointer, stored in element i-k in display • constant access time
C Example • Stack pointer sp • Top of the frame stack • Frame pointer fp • Access to arguments and locals via offset of fp • They differ if temporary space is allocated in the stack
C Example • Stack pointer sp • Top of the frame stack • Frame pointer fp • Access to arguments and locals via offset of fp • They differ if temporary space is allocated in the stack
Stack Maintenance • Calling sequence (by caller) and prologue (by callee) are executed in the way into the subroutine: • Pass parameters • Save return address • Change program counter • Change stack pointer to allocate stack space • Save registers (including frame pointer) • Change frame pointer to new frame • Initialization code • Separation of tasks? • As much as possible in the callee (only once in the program)
Stack Maintenance • Epilogue (by callee) is executed in the way out of the subroutine: • Pass return value • Execute finalization code • Deallocate stack frame (restore stack pointer) • Restore registers
C on MIPS Calling sequence by the caller: • Caller saves registers in local variables and temporaries space • 4 scalar arguments in registers • Rest of the arguments at the top of the current frame • Return address in register ra and jump to target address
C on MIPS Prologue by the callee: • Subtract the frame size from the sp • Save registers at the beginning of the new frame using sp as the base for displacement • Copy the sp into the fp
C on MIPS Callee epilogue: • Set the function return value • Copy fp to sp to deallocate any dynamically allocated space • Restore registers including ra (based on sp) • Add frame size to sp • Return (jump to ra) • Caller (after call): • Restores caller-saves registers lazily • over time, as their values are needed
Pascal on 680x0 • Significant differences from MIPS: • all arguments passed on stack (not in registers) • all arguments pushed and popped (not assembled in a build area) • sp and fp are not the same • special subroutine-calling instructions • save and update frame pointers, save registers, jump, allocate space for frame • all in one or two instructions • special push and pop operations • load/store and update sp in one instruction
Pascal on 680 • Calling sequence: • Caller (before call) • creates space for a small return value (or address for a large one) • pushes arguments • pushes the static link • performs a jsr instruction • pushes the return address, updates sp, and jumps to subroutine • Callee (in its prologue) • executes a link instruction • pushes fp on stack • copies sp into fp • allocates space - subtracts a constant from sp • pushes registers on stack • copies large arguments
Pascal on 680 • Calling sequence (cont.): • Callee (in its epilogue) • sets return value • pops saved registers • executes an unlk instruction • reverse of link • returns (executes a rts instruction) • pops return address, and updates sp • Caller (after call) • moves return value from stack • restores caller-saves registers lazily over time, as their values are needed