Ting Zhang Iowa State University Computer Science Department Lecture Note 16 October 26, 2010 Control Abstraction: Subroutines 1 / 26
Outline 1 Subroutines 2 Parameter Passing 3 Generic Subroutines 2 / 26
Stack Layout Typical stack layout with subroutine nesting: Given the calling sequence A, E, B, D, C, in that order, frames will be allocated on the stack as shown at right, with the indicated static and dynamic links. 3 / 26
Stack Frame A typical stack frame: Arguments are accessed at positive offsets from the fp. Local variables and temporaries are accessed at negative offsets from the fp. Arguments to be passed to called routines are assembled at the top of the frame, using positive offsets from the sp. 4 / 26
Static Chain Maintainence In languages with nested subroutines, the maintenance of the static chain must be performed by the caller, rather than the callee The callee is nested (directly) inside the caller. The caller therefore passes its own frame pointer as the callee s static link. 5 / 26
Static Chain Maintainence In languages with nested subroutines, the maintenance of the static chain must be performed by the caller, rather than the callee The callee is nested (directly) inside the caller. The caller therefore passes its own frame pointer as the callee s static link. The callee is k 0 scopes outward -closer to the outer level of lexical nesting. The caller dereferences its own static link k times and passes the result as the callee s static link. 5 / 26
Typical Calling Sequence Caller s task before the call: saves any caller-saves registers 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument jump to the subroutine, simultaneously passing the return address on the stack or in a register 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument jump to the subroutine, simultaneously passing the return address on the stack or in a register 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument jump to the subroutine, simultaneously passing the return address on the stack or in a register Callee s task before the execution: allocates a frame by subtracting an appropriate constant from the sp 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument jump to the subroutine, simultaneously passing the return address on the stack or in a register Callee s task before the execution: allocates a frame by subtracting an appropriate constant from the sp saves the old frame pointer into the stack, and assigns it an appropriate new value 6 / 26
Caller s task before the call: Typical Calling Sequence saves any caller-saves registers computes the values of arguments and moves them into the stack or registers computes the static link (if needed) and passes it as an extra, hidden argument jump to the subroutine, simultaneously passing the return address on the stack or in a register Callee s task before the execution: allocates a frame by subtracting an appropriate constant from the sp saves the old frame pointer into the stack, and assigns it an appropriate new value saves any callee-saves registers that may be overwritten by the current routine 6 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed restores the fp and the sp 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed restores the fp and the sp jumps back to the return address 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed restores the fp and the sp jumps back to the return address 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed restores the fp and the sp jumps back to the return address Caller s task after the call: moves the return value to wherever it is needed 7 / 26
Typical Calling Sequence Callee s after the execution: moves the return value (if any) into a register or a reserved location in the stack restores callee-saves registers if needed restores the fp and the sp jumps back to the return address Caller s task after the call: moves the return value to wherever it is needed restores caller-saves registers if needed 7 / 26
Frame Allocation A stack-frame is created merely by moving the stack pointer up by d locations at the start of a subroutine 8 / 26
Frame Growth 9 / 26
Outline 1 Subroutines 2 Parameter Passing 3 Generic Subroutines 10 / 26
Parameter Passing Parameter passing modes: 11 / 26
Parameter Passing Parameter passing modes: In 11 / 26
Parameter Passing Parameter passing modes: In Out 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) Call by reference (in+out) 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) Call by reference (in+out) Call by result (out) 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) Call by reference (in+out) Call by result (out) Call by value/result (in+out) 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) Call by reference (in+out) Call by result (out) Call by value/result (in+out) Call by name (in+out) 11 / 26
Parameter Passing Parameter passing modes: In Out In/Out Parameter passing mechanisms: Call by value (in) Call by reference (in+out) Call by result (out) Call by value/result (in+out) Call by name (in+out) Call by need (in+out) 11 / 26
Call by Value Representative language: C 12 / 26
Call by Value Representative language: C Actual parameters are evaluated and their values are assigned to the formal parameters 12 / 26
Call by Value Representative language: C Actual parameters are evaluated and their values are assigned to the formal parameters Actual parameters are not affected by the change to the formal parameters 12 / 26
Call by Value Representative language: C Actual parameters are evaluated and their values are assigned to the formal parameters Actual parameters are not affected by the change to the formal parameters Data can only be modified by passing pointers to the data swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } 12 / 26
Call by Reference Representative language: Fortran SUBROUTINE SWAP(A,B) INTEGER A, B, C C=A A=B B=C END 13 / 26
Call by Reference Representative language: Fortran SUBROUTINE SWAP(A,B) INTEGER A, B, C C=A A=B B=C END If an R-value appears as an argument, a temporary variable is created to hold the value, and this variable is passed by reference SWAP(A,2) is equivalent to A = 2 13 / 26
Call by Value/Reference Provides call-by-value as well as call-by-reference Representative language: Pascal, C++ 14 / 26
Call by Value/Reference Provides call-by-value as well as call-by-reference Representative language: Pascal, C++ Call by value is similar to C 14 / 26
Call by Value/Reference Provides call-by-value as well as call-by-reference Representative language: Pascal, C++ Call by value is similar to C Call by reference is indicated by additional qualifiers In Pascal: procedure swap(var a:integer, var b:integer) var t; begin t := a; a := b; b := t end In C++: void swap(int& a, int& b) int t; begin t := a; a := b; b := t end 14 / 26
Call by Sharing Acts as call-by-value for the immutable objects and call-by-reference for mutable objects. Also called call-by-object Representative language: Python, Java, C# 15 / 26
Call by Sharing Acts as call-by-value for the immutable objects and call-by-reference for mutable objects. Also called call-by-object Representative language: Python, Java, C# Behaves like call-by-value for immutable objects in assignments 15 / 26
Call by Sharing Acts as call-by-value for the immutable objects and call-by-reference for mutable objects. Also called call-by-object Representative language: Python, Java, C# Behaves like call-by-value for immutable objects in assignments Behaves like call-by-reference for mutable objects Immutable objects in Python: Mutable objects in Python: str = "cannot be changed" lst = ["can", "be", "changed"] def change(par): par = "change" change(str) def change(par): par.append("sure") change(lst) 15 / 26
Representative language: Ada Call by Result 16 / 26
Representative language: Ada Call by Result The value of the formal parameter is copied into the actual parameter when the subroutine returns x : integer procedure foo(y : out integer) y := 3 print x... x := 2 foo(x) print x If y is passed by reference the program will print 3 twice. If y is passed by value/result, it will print 2 and then 3 16 / 26
Call by Name Representative language: Algol 60 17 / 26
Call by Name Representative language: Algol 60 The actual arguments are not evaluated at all; they are substituted into the function body directly integer i; real procedure sum (i, lo, hi, term); value lo, hi; integer i, lo, hi; real term; begin real temp; temp := 0; for i := lo step 1 until hi do temp := temp + term; sum := temp end; print (sum (i, 1, 100, 1/i)) It computes the 100th harmonic number by the formula H 100 = 100 1 i i=1 17 / 26
Call by Need Representative language: Haskell 18 / 26
Call by Need Representative language: Haskell A memorized version of call-by-name; if the function argument is evaluated, that value is stored for subsequent uses Call by name: 3 evaluations doub x = x + x Call by need: 2 evaluations doub x = x + x doub (doub 8) = doub 8 + doub 8 = 8 + 8 + 8 + 8 = 32 doub (doub 8) = doub 8 + doub 8 = 8 + 8 + doub 8 = 16 + 16 = 32 18 / 26
Closures as Parameters A closure (a reference to a subroutine, together with its referencing environment) can be passed as a parameter In Standard Pascal: A : array [low..high : integer] of integer; procedure apply_to_a(function f(n : integer) : integer); var i : integer; begin for i := low to high do A[i] := f(a[i]); end; 19 / 26
Closures as Parameters A closure (a reference to a subroutine, together with its referencing environment) can be passed as a parameter In Standard Pascal: A : array [low..high : integer] of integer; procedure apply_to_a(function f(n : integer) : integer); var i : integer; begin for i := low to high do A[i] := f(a[i]); end; In C and C++: int A[50]; void apply_to_a(int (*f)(int)) { int i; for (i = 0; i < sizeof(a); i++) A[i] = f(a[i]); } 19 / 26
Conformant Arrays A formal array parameter whose shape is finalized at run time Languages that support conformant arrays include : Ada, Pascal 20 / 26
Conformant Arrays A formal array parameter whose shape is finalized at run time Languages that support conformant arrays include : Ada, Pascal In Standard Pascal: procedure apply_to_a(function f(n : integer) : integer; A : array [low..high : integer] of integer); var i : integer; begin for i := low to high do A[i] := f(a[i]); end; 20 / 26
Conformant Arrays A formal array parameter whose shape is finalized at run time Languages that support conformant arrays include : Ada, Pascal In Standard Pascal: procedure apply_to_a(function f(n : integer) : integer; A : array [low..high : integer] of integer); var i : integer; begin for i := low to high do A[i] := f(a[i]); end; C passes only pointers to arrays to functions and array size has to be determined using some other means (e.g. as another parameter) void apply_to_a(int (*f)(int), int A[], int size_of_a) { int i; for (i = 0; i < size_of_a; i++) A[i] = f(a[i]); } 20 / 26
Conformant Arrays A formal array parameter whose shape is finalized at run time Languages that support conformant arrays include : Ada, Pascal In Standard Pascal: procedure apply_to_a(function f(n : integer) : integer; A : array [low..high : integer] of integer); var i : integer; begin for i := low to high do A[i] := f(a[i]); end; C passes only pointers to arrays to functions and array size has to be determined using some other means (e.g. as another parameter) void apply_to_a(int (*f)(int), int A[], int size_of_a) { int i; for (i = 0; i < size_of_a; i++) A[i] = f(a[i]); } What is made harder in a language with non-conformant arrays? 20 / 26
Default Parameters A default parameter is one that need not necessarily be provided by the caller Languages that support default parameters include : Ada, C++, Common Lisp, Python 21 / 26
Default Parameters A default parameter is one that need not necessarily be provided by the caller Languages that support default parameters include : Ada, C++, Common Lisp, Python When an actual parameter is missing, a preestablished default value will be used instead 21 / 26
Default Parameters A default parameter is one that need not necessarily be provided by the caller Languages that support default parameters include : Ada, C++, Common Lisp, Python When an actual parameter is missing, a preestablished default value will be used instead Example in C++: void print_num(int n, int base = 10)... 21 / 26
Default Parameters A default parameter is one that need not necessarily be provided by the caller Languages that support default parameters include : Ada, C++, Common Lisp, Python When an actual parameter is missing, a preestablished default value will be used instead Example in C++: void print_num(int n, int base = 10)... Example in Python: def function(data=[]): data.append(1) return data 21 / 26
Named Parameters Named parameter (aka keyword parameter) explicitly binds the actual parameter to the formal parameter Languages that support named parameters include : Ada, Modula-3, Common Lisp, and Python 22 / 26
Named Parameters Named parameter (aka keyword parameter) explicitly binds the actual parameter to the formal parameter Languages that support named parameters include : Ada, Modula-3, Common Lisp, and Python Good for documentation of the purpose of parameters format_page(columns => 2,window_height => 400, window_width => 200, header_font => Helvetica,..., background_color => white); 22 / 26
Named Parameters Named parameter (aka keyword parameter) explicitly binds the actual parameter to the formal parameter Languages that support named parameters include : Ada, Modula-3, Common Lisp, and Python Good for documentation of the purpose of parameters format_page(columns => 2,window_height => 400, window_width => 200, header_font => Helvetica,..., background_color => white); Allows default parameters anywhere in formal parameter list format_page(window_width => 200); 22 / 26
Variable-length Arguments Languages that support variable-length arguments include : C,C++,Java,C#, Python 23 / 26
Variable-length Arguments Languages that support variable-length arguments include : C,C++,Java,C#, Python Variable number of arguments in C and C++ is not type safe int printf(char *format,...) 23 / 26
Variable-length Arguments Languages that support variable-length arguments include : C,C++,Java,C#, Python Variable number of arguments in C and C++ is not type safe int printf(char *format,...) Java supports typed variable argument lists via the <type-name>... syntax static void print_lines(string foo, String... lines) 23 / 26
Variable-length Arguments Languages that support variable-length arguments include : C,C++,Java,C#, Python Variable number of arguments in C and C++ is not type safe int printf(char *format,...) Java supports typed variable argument lists via the <type-name>... syntax static void print_lines(string foo, String... lines) C# allows typed variable argument lists via the params keyword static void print_lines(string foo, params String[] lines) 23 / 26
Variable-length Arguments Languages that support variable-length arguments include : C,C++,Java,C#, Python Variable number of arguments in C and C++ is not type safe int printf(char *format,...) Java supports typed variable argument lists via the <type-name>... syntax static void print_lines(string foo, String... lines) C# allows typed variable argument lists via the params keyword static void print_lines(string foo, params String[] lines) Python takes variable argument lists via the asterisk operator (*) def foo(*args): print("number of arguments:", len(args)) print("arguments are: ", args) 23 / 26
Outline 1 Subroutines 2 Parameter Passing 3 Generic Subroutines 24 / 26
Generic Subroutines and Modules Generic Parameters Options: 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types Ada and C++ allow values of ordinary (nongeneric) types, including subroutines and classes 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types Ada and C++ allow values of ordinary (nongeneric) types, including subroutines and classes Implementation Options: 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types Ada and C++ allow values of ordinary (nongeneric) types, including subroutines and classes Implementation Options: Ada and C++ use a purely static mechanism: the compiler creates a separate copy of the code for every instance 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types Ada and C++ allow values of ordinary (nongeneric) types, including subroutines and classes Implementation Options: Ada and C++ use a purely static mechanism: the compiler creates a separate copy of the code for every instance Java guarantees that all instances of a given generic will share the same code at run time 25 / 26
Generic Subroutines and Modules Generic Parameters Options: Java and C# pass only types Ada and C++ allow values of ordinary (nongeneric) types, including subroutines and classes Implementation Options: Ada and C++ use a purely static mechanism: the compiler creates a separate copy of the code for every instance Java guarantees that all instances of a given generic will share the same code at run time C# uses different implementations for different built-in or value types while maintaining type safety 25 / 26
Generic Parameter Constraints In Java one requires that a generic parameter support a particular set of methods public static <T extends Comparable<T>> void sort(t A[]) {... if (A[i].compareTo(A[j]) >= 0)...... } 26 / 26
Generic Parameter Constraints In Java one requires that a generic parameter support a particular set of methods public static <T extends Comparable<T>> void sort(t A[]) {... if (A[i].compareTo(A[j]) >= 0)...... } Same in C# in a different syntax static void sort<t>(t[] A) where T : IComparable {... if (A[i].CompareTo(A[j]) >= 0)...... } 26 / 26
Generic Parameter Constraints In Java one requires that a generic parameter support a particular set of methods public static <T extends Comparable<T>> void sort(t A[]) {... if (A[i].compareTo(A[j]) >= 0)...... } Same in C# in a different syntax static void sort<t>(t[] A) where T : IComparable {... if (A[i].CompareTo(A[j]) >= 0)...... } C++ does not impose explicit constraints 26 / 26