Subprogram and its implementation PLLab NTHU Cs 2403
Subprogram and its implementation PLLab, NTHU, Cs 2403 Programming Languages
Fundamentals • Two fundamental abstractions in PL – Process abstraction (subprogram) – Data abstraction (chap 11) • Subprogram characteristics – Single entry point – Caller is suspended during callee execution – Control returns to caller when callee execution terminates PLLab, NTHU, Cs 2403 Programming Languages
Definitions • Subprogram definition describes the interface to and the actions of the subprogram abstraction – Header: 1 st part of the definition (name, return type, parameters…) – Parameter profile: describes the number, order and type of its formal parameters – Declaration: providing type information PLLab, NTHU, Cs 2403 Programming Languages
Parameters • Two ways for subprogram to gain access to the data it is to process: – Direct access to nonlocal variables – Parameter passing PLLab, NTHU, Cs 2403 Programming Languages
Parameters (cont. ) • Formal parameters: defined in the subprogram header – Bound to storage when subprogram is called through some other variables – e. g. void sumer(int num 1, real num 2); • Actual parameters: parameters used in the subprogram call – Bound to formal parameters – e. g. Sumer(10. 1. 4) PLLab, NTHU, Cs 2403 Programming Languages
Parameters (cont. ) • Actual and formal parameter correspondences – Positional parameters: binding is based on position – Keyword parameters: binding is based on keyword mapping • e. g. (Ada) sumer(num 1=> 10, num 2=>1. 4) • Defalut values: C++ FORTRAN 90, Ada allow default values formal parameters – e. g. (C++) void sumer(int Num 1, real num 2, int flag = 1); Caller: sumer(10. 1. 4); PLLab, NTHU, Cs 2403 Programming Languages
Local referencing environment • Local variables: variables that are defined inside the subprogram • Stack dynamic local variables – Storage is allocated from stack – Allows recursive programming – Cost of time for allocation, initialization and deallocation • Static local variables: – More efficient for direct addressing – History sensitive PLLab, NTHU, Cs 2403 Programming Languages
Example I virtual address space #include <stdio. h> int count; main( ) { int i ; for (i=0; i<=10; i++) { test( ) ; } } test( ) { int i ; static int count = 0; count = count + 1 ; } test: : i main: : i run-time stack ptr test: : count static var ptr count PLLab, NTHU, Cs 2403 Programming Languages
Example I #include <stdio. h> int count; main( ) { int i ; for (i=0; i<=10; i++) { test( ) ; } } test( ) { int i ; static int count = 0; count = count + 1 ; } Typebinding Storagebinding count static main: : i static stack-dynamic test: : count static PLLab, NTHU, Cs 2403 Programming Languages
Parameter Passing Methods • We discuss these at several different levels: – Semantic models: • • • in mode: receive data from actual params. out mode: transmit data to actual params Inout mode: do both above – Conceptual models of transfer: • • Actual value is copied Move an access path PLLab, NTHU, Cs 2403 Programming Languages
Parameter-passing methods PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-value • Pass-by-value – Use the value of the actual params to initialize the corresponding formal params – Pascal, c, c++ • EX. main( ) { int a = 6; int b = 4; Cswap(a, b); // a = 6 // b = 4 } Cswap(int c, int d) { int temp = c; c = d; d = temp; } PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-value example main( ) { int a = 6; int b = 4; Cswap(a, b); // a = 6 // b = 4 } Cswap(int c, int d) { int temp = c; c = d; d = temp; } temp=6 d=4 6 c=6 4 b=4 a=6 PLLab, NTHU, Cs 2403 Programming Languages Cswap stack point main stack point
Pass-by-result • Pass-by-result – no value is transmitted to the subprogram – the value of the formal para is passed back to the actual para when the subprogram returns • Example (in a pseudo language) caller( ) { int a ; int b ; foo(a, b); // a = 6 // b = 4 } foo(int c, int d ) { c=6; d=4; } PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-result example caller( ) { int a ; int b ; foo(a, b); // a = 6 // b = 4 } foo(int c, int d ) { c=6; d=4; } d =4 c =6 b a foo stack point caller stack point PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-value-result • Pass-by-value-result (a. k. a. pass-by-copy) – the combination of pass-by-value and pass-by-result – Ada • Example (in Ada) integer a = 3 ; integer b = 1 ; integer k[10] ; k[3] = 7; swap(a, b); swap(b, k[b]); procedure swap(a : in out integer, b : in out integer) is temp : integer; begin temp : = a ; a : = b ; b : = temp ; end swap; PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-value-result example integer a = 3 ; integer b = 1 ; swap stack point integer k[10] ; k[3] = 7; procedure swap(a : in out integer, swap(a, b); swap(b, k[b]); b : in out integer) is temp : integer; begin temp : = a ; a : = b ; b : = temp ; end swap; PLLab, NTHU, Cs 2403 Programming Languages temp =3 b=1 33 b=7 a=3 17 …. . k[3] =7 3 k[2] k[1] k[0] b=1 3 7 a=3 1 main stack point
Pass-by-reference • Pass-by-reference – access path is transmitted to the called subprogram: efficient in terms of time & space – access to formal paras are slower • Example (in C) caller( ) { int a = 3 ; int b = 1 ; int k[10] ; k[3] = 7; swap(&a, &b) ; swap(&b, &k[b]) ; } swap(int *c, int *d ) { temp = *c; *c = *d ; *d = temp ; } PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-reference example caller( ) { int a = 3 ; int b = 1 ; int k[10] ; k[3] = 7; swap(&a, &b) ; swap(&b, &k[b]) ; } swap(int *c, int *d ) { temp = *c; *c = *d ; *d = temp ; } 2024 2020 2016 2012 2008 2004 2000 temp=3 d=2004 d=2020 c=2004 …. . swap stack point k[3] =7 3 k[2] k[1] k[0] b=1 3 7 a=3 1 caller stack point PLLab, NTHU, Cs 2403 Programming Languages
Pass-by-reference (con’t) • Example (in C++) caller( ) { int a = 3 ; int b = 1 ; int k[10] ; k[3] = 7; swap(a, b) ; swap(b, k[b]) ; } swap(int &c, int &d ) { temp = c; c=d; d = temp ; } 2024 2020 2016 2012 2008 2004 2000 temp=3 &d=2004 &d=2020 &c=2004 …. . swap stack point k[3] =7 3 k[2] k[1] k[0] b=1 3 7 a=3 1 caller stack point PLLab, NTHU, Cs 2403 Programming Languages
Singlemensional array para • C does not check the array subscript range run-time error if our-of-bound access void fun(int *a) { a[3] = 77; } void fun(int a[ ]) { a[3] = 77; } main( ) { int a[10]; a[3] = 55; fun(a); // a[3] = 77 } void fun(int a[ ]) { a[13] = 77; // run-time error } main( ) { int a[10]; a[3] = 55; fun(a); } PLLab, NTHU, Cs 2403 Programming Languages
Interesting C pointer usage fun(int *a) { a = (int *) malloc(40); a[5] = 1234; } main( ) { int *array; fun(array); printf(“%d”, array[5]); } Segmentation fault!! a[5]=1234 memory leakage!! 2060 temp=6 d=4 6 4 a=0 2060 array=0 fun stack main stack PLLab, NTHU, Cs 2403 Programming Languages
Correct C pointer usage fun(int *a) { a[5] = 1234; } main( ) { int *array; array = (int *) malloc(40); fun(array); // array[5] == 1234 } a[5]=1234 2060 temp=6 d=4 6 4 a=2060 array=0 a=6 2060 fun stack main stack PLLab, NTHU, Cs 2403 Programming Languages
Array implementation • One-dim array address calculation – addr(a[j]) = addr(a[0]) + j * element. Size; int bounds[10]; // one int = 4 bytes &bounds[0] = 1200 &bounds[4] = 1216 • Row-major allocation: a[m, n] = a[3, 3] – addr(a[i, j]) = addr(a[0, 0]) + ((i * n) + j) * element. Size; a[0, ] = 3 a[1, ] = 6 a[2, ] = 1 4 2 3 7 5 8 3, 4, 7, 6, 2, 5, 1, 3, 8 &a[0, 0] = 1200 &a[1, 2] = 1220 PLLab, NTHU, Cs 2403 Programming Languages
Multidimensional array para • Compiler needs to know the declared size of the multi -dim array to build the mapping function in subprograms – C uses raw-major allocation fun(int a[ ][ ]) { a[3][5] = 4321; } main( ) { int a[10][20]; a[3][5] = 1234; fun(a); } // compiler error fun(int a[ ][25]) { a[3][5] = 4321; } main( ) { int a[10][20]; a[3][5] = 1234; fun(a); } // compiler error fun(int a[ ][20]) { a[3][5] = 4321; } main( ) { int a[10][20]; a[3][5] = 1234; fun(a); // a[3][5] = 4321 } PLLab, NTHU, Cs 2403 Programming Languages
Multidimensional array (con’t) fun(int a[ ][20][25]) { fun(int a[ ][ ][25]) { a[3][4][5] = 4321; } main( ) { int a[10][25] ; a[3][4][5] = 1234 ; fun(a); } // compiler error } main( ) { int a[10][25]; a[3][4][5] = 1234; fun(a); } // compiler error a[3][4][5] = 4321; } main( ) { int a[10][25]; a[3][4][5] = 1234; fun(a); // a[3][4][5] = 4321 } Work around: 1. Use heap-dynamic variables for array • int *a; a = (int *) malloc(sizeof(int) * m * n); 2. Pass the arrry variable alone with m and n • fun(int *a, int num_rows, int num_cols) • a[i, j] == *(a + i * num_cols + j) PLLab, NTHU, Cs 2403 Programming Languages
Function as parameters int Plus (int num) { return num + num ; } int main( ) { int Result ; int (*p. F)(int) ; int Square (int num) { return num * num; } p. F = Plus; Result = Execute(3, p. F); // Result = 6 void Execute(int seed, int (*p. F)(int)) { return p. F(seed) ; } p. F = Square; Result = Execute(3, p. F); // Result = 9 } PLLab, NTHU, Cs 2403 Programming Languages
Reference environment • Referencing env – shallow binding: env of the call statement • x=4 – deep binding: env of the defined subprogram • x=1 • C, C++, Java. – ad hoc binding: env of the actual passing statement • x=3 procedure SUB 1; var x : integer; procedure SUB 2; begin write(‘x = ‘, x); end; procedure SUB 3; var x : integer; begin x : = 3; SUB 4(SUB 2); end; procedure SUB 4(SUBX); var x : integer; begin x : = 4; SUBX end; begin x : = 1; SUB 3; end; PLLab, NTHU, Cs 2403 Programming Languages
Generic Subprograms • A generic or polymorphic subprogram is one that takes parameters of different types on different activations • A subprogram that takes a generic parameter that is used in a type expression that describes the type of the parameters of the subprogram provides parametric polymorphism PLLab, NTHU, Cs 2403 Programming Languages
Without generic data structure class Name { char fullname[64]; }; class Person { char first. Name[64]; char last. Name[32]; }; class Name. Stack { Name nodes[50]; int stackptr; public: stack() { stackptr = 0; } void push( Name data) { nodes[stackptr++] = data; } Name pop() { return nodes[stackptr--]; } }; class Person. Stack { Person nodes[50]; int stackptr; public: stack() { stackptr = 0; } void push( Person data) { nodes[stackptr++] = data; } Person pop() { return nodes[stackptr--]; } }; int main(int argc, char* argv[ ]) { Name. Stack Department. Stack; Person. Stack Students. Stack; Name dep; Department. Stack. push(dep); } PLLab, NTHU, Cs 2403 Programming Languages
Generic data structure class Name { char fullname[64]; }; class Person { char first. Name[64]; char last. Name[32]; }; int main(int argc, char* argv[ ]) { template<class item, int max_items> } class stack { item nodes[max_items]; int stackptr; public: stack() { stackptr = 0; } void push( item data) { nodes[stackptr++] = data; } item pop() { return nodes[stackptr--]; } }; stack<Name, 10> stack<Person, 20> stack<Name, 50> Department. Stack; Students. Stack; School. Stack; Name dep; Department. Stack. push(dep); PLLab, NTHU, Cs 2403 Programming Languages
Generic function • Example in C++ (similar in Ada) template <class Type> Type max(Type first, Type second) { return first > second ? first : second; } main( ) { int a, b, c; char d, e, f; c = max(a, b); // code generation for int max(…) f = max(d, e); // code generation for char max(…) b = max(a, c); // no code generation } PLLab, NTHU, Cs 2403 Programming Languages
Subprogram implementation PLLab, NTHU, Cs 2403 Programming Languages
General semantic • Def: The subprogram call and return operations of a language are together called its subprogram linkage PLLab, NTHU, Cs 2403 Programming Languages
Implementing “Simple” Subprograms • Call Semantics: 1. Save the execution status of the caller 2. Carry out the parameter-passing process 3. Pass the return address to the callee 4. Transfer control to the callee PLLab, NTHU, Cs 2403 Programming Languages
Implementing “Simple” Subprograms • Return Semantics: 1. If pass-by-value-result parameters are used, move the current values of those parameters to their corresponding actual parameters 2. If it is a function, move the functional value to a place the caller can get it 3. Restore the execution status of the caller 4. Transfer control back to the caller PLLab, NTHU, Cs 2403 Programming Languages
Implementing “Simple” Subprograms • Required Storage: – Caller status, parameters, return address, and functional value (if it is a function) • The format, or layout, of the noncode part of an executing subprogram is called an activation record PLLab, NTHU, Cs 2403 Programming Languages
Subprogram implementation • Activation record: the layout of the call stack for callrelated data • Static-scoping PL implementation – dynamic-scoping discussed later • Two approaches to implementing nonlocal variables accesses – static chains – displays Local variables Parameters Dynamic link Static link Return address An activation record PLLab, NTHU, Cs 2403 Programming Languages stack top
Scope example proc main var X 1, X 2; proc A var X 1, X 2; end proc B var X 1, X 2; call A; end call B; end Proc A reference environment Static scope: A main Dynamic scope: A B main PLLab, NTHU, Cs 2403 Programming Languages
Static & dynamic scope Procedure big; var x : integer; procedure sub 1; begin …x… (1) end; procedure sub 2; var x : integer; begin …x… (2) sub 1; end; begin sub 1; (3) …x… (4) sub 2; (5) end Static scope: (3 1) x = big’s x (4) x = big’s x (2) x = sub 2’s x (5 1) x = big’s x Dynamic scope (3 1) x = big’s x (4) x = big’s x (2) x = sub 2’s x (5 1) x = sub 2’s x PLLab, NTHU, Cs 2403 Programming Languages
Activation record Local sum Local List [5] Local List [4] Local List [3] Local List [2] Local List [1] • static link: used for nonlocal Parameter part variables reference Parameter total Dynamic link • dynamic link: points to the Static link top of the AR of the caller Return address The activation record for PLLab, NTHU, Cs 2403 Programming Languages procedure sub Procedure sub (var total: real; part: integer); var list : array [1. . 5] of integer; sum : real; Begin … End;
Local reference example Program MAIN_1; var P : real; procedure A (X : integer); var Y : boolean; procedure C (Q : boolean); begin {C} … end; {C} begin {A} … C(Y); … end; {A} procedure B (R : real); var S, T : integer; begin {B} … A(S); … end; {B} begin {MAIN_1} … B(P); … end. {MAIN_1} Parameter Q Dynamic link Static link Return (to A) Local Y Parameter X Dynamic link Static link Return (to B) Local T Local S Parameter R Dynamic link Static link Return (to MAIN) Local P PLLab, NTHU, Cs 2403 Programming Languages
Recursion example Function value 1 ? Parameter n 1 Dynamic link int factorial (int n){ If If(n(n<=1) return 1; <=1) else 1; return (n* factorial (n-1)); } void main(){ int value; value = factorial (3); } Static link Return(to factorial) Function value 2 ? Parameter n 2 Dynamic link Static link Return(to factorial) Function value 6 ? Parameter n 3 Dynamic link Static link Return (to main) Local value PLLab, NTHU, Cs 2403 Programming Languages ?
Static chain & Display • Static chain: following the static chain for nonlocal variable reference – costly – nondeterministic • Display: the only widely used alternative to static chain – static links are collected in a single array called a display – exactly 2 steps to access nonlocal variables PLLab, NTHU, Cs 2403 Programming Languages
Nested Subprograms • Technique 1 - Static Chains • A static chain is a chain of static links that connects certain activation record instances • The static link in an activation record instance for subprogram A points to one of the activation record instances of A's static parent • The static chain from an activation record instance connects it to all of its static ancestors PLLab, NTHU, Cs 2403 Programming Languages
Static Chains (continued) • To find the declaration for a reference to a nonlocal variable: – You could chase the static chain until the activation record instance (ari) that has the variable is found, searching each ari as it is found, if variable names were stored in the ari • Def: static_depth is an integer associated with a static scope whose value is the depth of nesting of that scope PLLab, NTHU, Cs 2403 Programming Languages
Static Chains (continued) main ----- static_depth = 0 A ----- static_depth = 1 B ----- static_depth = 2 C ----- static_depth = 1 PLLab, NTHU, Cs 2403 Programming Languages
Static Chains (continued) • Def: The chain_offset or nesting_depth of a nonlocal reference is the difference between the static_depth of the reference and that of the scope where it is declared • A reference can be represented by the pair: (chain_offset, local_offset) where local_offset is the offset in the activation record of the variable being referenced PLLab, NTHU, Cs 2403 Programming Languages
Nonlocal reference example program MAIN_2; var X : integer; procedure BIGSUB; var A, B, C : integer; procedure SUB 1; var A, D : integer; begin { SUB 1 } A : = B + C; <------------1 end; { SUB 1 } procedure SUB 2(X : integer); var B, E : integer; procedure SUB 3; var C, E : integer; begin { SUB 3 } SUB 1; E : = B + A: <----------2 end; { SUB 3 } begin { SUB 2 } SUB 3; A : = D + E; <------------3 end; { SUB 2 } begin { BIGSUB } SUB 2(7); end; { BIGSUB } begin BIGSUB; end. { MAIN_2 } MAIN_2 var x var A, B, C var A, D proc BIGSUB; SUB 2(7); proc SUB 1 A : = B + C; proc SUB 2(X) var B, E proc SUB 3 var C, E SUB 1; E : = B + A; PLLab, NTHU, Cs 2403 Programming Languages SUB 3; A : = X + E;
Example Pascal Program Call sequence for MAIN_2 calls BIGSUB calls SUB 2 calls SUB 3 calls SUB 1 PLLab, NTHU, Cs 2403 Programming Languages
Stack Contents at Position 1 PLLab, NTHU, Cs 2403 Programming Languages
Example Pascal Program At position 1 in SUB 1: A - (0, 3) B - (1, 4) C - (1, 5) At position 2 in SUB 3: E - (0, 4) B - (1, 4) A - (2, 3) At position 3 in SUB 2: A - (1, 3) D - an error E - (0, 5) PLLab, NTHU, Cs 2403 Programming Languages
Nonlocal reference example MAIN_2 var x proc BIGSUB; var A, B, C proc SUB 1 proc SUB 2(X) var A, D SUB 2(7); var C, E Bigsub calls sub 2 Return(to SUB 2) Local Dynamic link Static link D A E C Return(to SUB 2) A : = B + C; Main_2 calls Bigsub Local Dynamic link Static link proc SUB 3; A : = X + E; var C, E SUB 1; E : = B + A; Sub 2 calls sub 3 Sub 3 calls sub 1 Local Parameter 7 Dynamic link Static link Return(to BIGSUB) Local Dynamic link Static link E B X C B A Return(to MAIN_2) PLLab, NTHU, Cs 2403 Programming Languages Local X
Blocks • Two Methods: 1. Treat blocks as parameterless subprograms – Use activation records 2. Allocate locals on top of the ari of the subprogram – Must use a different method to access locals – A little more work for the compiler writer PLLab, NTHU, Cs 2403 Programming Languages
Blocks MAIN_5() { int x, y, z; while ( … ) { int a, b, c; … while ( … ) { int d, e; } } while ( … ) { int f, g; } } e d Block Variables c b and g a and f z Locals y x Activation Record instance For MAIN_5 PLLab, NTHU, Cs 2403 Programming Languages
Implementing dynamic scoping • Deep access: the dynamic link chain is exactly what needed to reference nonlocal variables in a dynamic-scoped language • Shallow access: each local variable is stored in a separate stack PLLab, NTHU, Cs 2403 Programming Languages
Scope example proc main var X 1, X 2; proc A var X 1, X 2; end proc B var X 1, X 2; call A; end call B; end Proc A reference environment Static scope: A main Dynamic scope: A B main PLLab, NTHU, Cs 2403 Programming Languages
Deep Access Procedure C; integer x, z; begin x : = u + v; … end; Procedure B; integer w, x; begin … end; Procedure A; integer v, w; begin … end; Program MAIN_6 integer v, u; begin … end; ARI for C ARI for B MAIN_6 calls A A calls B B calls C Local Dynamic link Return (to A) Local Dynamic link z x x w Return (to A) ARI for A Local Dynamic link w v Return (to MAIN_6) Local u ARI for MAIN_6 PLLab, NTHU, Cs 2403 Programming Languages Local v
Procedure C; integer x, z; begin x : = u + v; … end; Procedure B; integer w, x; begin … end; Procedure A; integer v, w; begin … end; Program MAIN_6 integer v, u; begin … end; Shallow Access MAIN_6 calls A A calls B B calls C A A MAIN_6 u v B C A x z w PLLab, NTHU, Cs 2403 Programming Languages
- Slides: 59