1 / 127

Implementing Subprograms: General Semantics and Examples

This chapter discusses the general semantics of subprogram calls and returns, as well as the implementation of "simple" subprograms, subprograms with stack-dynamic local variables, nested subprograms, and blocks. It also covers the implementation of dynamic scoping.

billi
Download Presentation

Implementing Subprograms: General Semantics and Examples

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 10 Implementing Subprograms

  2. Chapter 10 Topics • The General Semantics of Calls and Returns • Implementing “Simple” Subprograms • Implementing Subprograms with Stack-Dynamic Local Variables • Nested Subprograms • Blocks • Implementing Dynamic Scoping

  3. The General Semantics of Calls • The subprogram call and returnoperations of a language are together called subprogram linkage • The implementation of subprograms must be based on the semantics of the subprogram linkage of the language being implemented.

  4. The General Semantics of Calls Example: Mergesort algorithm Algorithm Mergesort(A[0 .. n-1]) //sort array (A[0 .. n-1]) by recursive mergesort //Input: An array A[0 . .n-1] of orderable elements //Output: Array A[0 . .n-1] sorted in nondecreasing order if n > 1 copy A[0… └n/2┘ -1] to B[0… └n/2┘ -1] ; copy A[└n/2┘ .. n -1] to C[0… ┌n/2┐ -1] ; S1: Mergesort (B[0 .. └n/2┘ -1]); S2: Mergesort (C[0 .. ┌n/2┐ -1]); S3: Merge(B, C, A); R: return;

  5. The General Semantics of Calls Algorithm Merge(B[0 .. p-1] , C[0 .. q-1], A[0 .. p+q-1]) //Merges two sorted arrays into one sorted array //Input: Array B[0 .. p-1]) and C[0 .. q-1] both sorted. //Output: Sorted array A[0 .. p+q-1] of the elements of B and C //set pointers i, j and k to the first element of B, C and A, respectively. i ← 0; j ← 0; k ← 0; //if none of the pointers i and j reaches either end of B or C while i < p and j < q do {/*enter the SmallerElement(B,C) into A and then pointer to the next element */ … } //end of while-do //enter the rest of the elements of B or C into A. if i = p copy C[j .. q-1] to A[k .. p+q-1] else copy B[i .. p-1] to A[k .. p+q-1]; return;

  6. The General Semantics of CallsMerge Algorithm (-Complete) Algorithm Merge(B[0 .. p-1] , C[0 .. q-1], A[0 .. p+q-1]) //Merges two sorted arrays into one sorted array //Input: Array B[0 .. p-1]) and C[0 .. q-1] both sorted. //Output: Sorted array A[0 .. p+q-1] of the elements of B and C //set pointers i, j and k to the first element of B, C and A, respectively. i ← 0; j ← 0; k ← 0; //if none of the pointers i and j reaches either end of B or C while i < p and j < q do { /*enter the SmallerElement(B,C) into A and then pointer to the next element */ if B[i] ≤ C[j] { A[k] ← B[i]; i ← i + 1 } else { A[k] ← C[j]; j ← j + 1 } //end of if-else //move pointer to the next location of A k ← k + 1 } //end of while-do //enter the rest of the elements of B or C into A. if i = p copy C[j .. q-1] to A[k .. p+q-1] else copy B[i .. p-1] to A[k .. p+q-1]; return;

  7. The General Semantics of CallsMerge Algorithm (-Complete) Algorithm Merge(B[0 .. p-1] , C[0 .. q-1], A[0 .. p+q-1]) //Merges two sorted arrays into one sorted array //Input: Array B[0 .. p-1]) and C[0 .. q-1] both sorted. //Output: Sorted array A[0 .. p+q-1] of the elements of B and C //set pointers i, j and k to the first element of B, C and A, respectively. i ← 0; j ← 0; k ← 0; //if none of the pointers i and j reaches either end of B or C while i < p and j < q do { /*enter the SmallerElement(B,C) into A and then pointer to the next element */ if B[i] ≤ C[j] { A[k] ← B[i]; i ← i + 1 } else { A[k] ← C[j]; j ← j + 1 } //end of if-else //move pointer to the next location of A k ← k + 1 } //end of while-do //enter the rest of the elements of B or C into A. if i = p copy C[j .. q-1] to A[k .. p+q-1] else copy B[i .. p-1] to A[k .. p+q-1]; return; while i < p and j < q do { /*enter the SmallerElement(B,C) into A and then pointer to the next element */ if B[i] ≤ C[j] { A[k] ← B[i]; i ← i + 1 } else { A[k] ← C[j]; j ← j + 1 } //end of if-else //move pointer to the next location of A k ← k + 1 } //end of while-do //enter the rest of the elements of B or C into A.

  8. The General Semantics of Calls M s1 s2,1 s3,6 … R R s1 s2, 2 s3,3 s1 s2,7 s3,8 … … R R … R … s1 s2,4 s3,5 … R … s1 s2,9 s3,10 … R … R … R … R Call Mergesort algorithm Stack to keep the return address for Transfer of Control.

  9. The General Semantics of Calls • General semantics of a subprogram call • Parameter passing methods • Stack-dynamic allocation for local variables declared in the called subprogram • Save the execution status of calling program (the caller) • The execution status needed to resume execution of a calling subprogram. • Things include register values, CPU status bits and the environment pointer (EP, used to access parameters and local variables during the execution of a subprogram) • Transfer of control and arrange for the return • …

  10. The General Semantics of Calls • General semantics of a subprogram call • … • If subprogram nesting is supported, access to non-local variables must be arranged. • The call process must create some mechanism for providing access to these nonlocal variables that are visible to the called subprogram.

  11. Recall: Parameter-passing methodsin Chapter 9 • Parameter-passing methods are the ways in which parameters are transmitted to and/or from called subprogram. Let recognize • Caller calls Callee Calling program unit Called subprogram … Sub(a, b, c) void Sub(int x, int y, int z) {…} … Actual parameters Formal parameters

  12. Recall: Parameter-passing methodsSemantic Models of Parameter Passing • The different semantics models of parameter-passing methods • Formal parameters are characterized by one of three distinct semantics models • They can receive data from the corresponding actual parameter (called in mode model) • They can transmit data to the actual parameter (called out mode model) • They can do both (call inout mode model)

  13. Parameter-passing methodsThree semantics models of parameter passing when physical moves are used

  14. Recall: Parameter-passing methodsSemanticModels of Parameter Passing • There are two conceptual models of passing parameters – of how data transfers take place in parameter transmission: • Physically copy the values • An actual value is copied (to the caller, to the called, or both ways) or • Using the pointers • an access path is transmitted • Most commonly, the access path is a simple pointer or reference.

  15. Parameter-passing methods Implementation models of parameter passing Semantic Model of Parameter-Passing In mode Out mode Inout mode • Let consider the implementation models for the three semantics models of parameter passing. That is, the implementation of the three basic parameter transmission modes (namely, in mode, out mode, and inout mode) • When a parameter is: • Pass-by-Value (in mode) • Pass-by-Result (out mode) • Pass-by-Value-Result (inout mode) • Pass-by-Reference (inout mode) • Pass-by-Name Pass-by-Value Pass-by-Value-Result Pass-by-Reference - Semantics of these two impl. models are the same Pass-by-Result

  16. Parameter-passing methods Implementation models of parameter passing • Pass-by-value (inmode) • When a parameter is passed by value, either by physical copy or by giving an access path • Physical copy simply initializes the formal parameter using the corresponding actual parameter value • The formal parameter then acts as a local variable in the subprogram, thus implementing in-mode semantics. • Giving the callee (the called subprogram) the access path to the value of the actual parameter in the caller, • but that would require that the value be in a write-protected cell (one that can only be read).

  17. Parameter-passing methods Implementation models of parameter passing • Pass-by-result (for out mode parameters) • When a parameter is passed by result, no value is transmitted to the called subprogram (the callee). • The corresponding formal parameter acts as a local variable, its value is transmitted back to the caller’s actual parameter (i.e., a variable of a calling program unit) before control is transferred back to the caller (the calling program). • Actual parameter must be a variable • This change of a variable is an expected side-effect • Physical copy is usually used • Upon return, the formal parameter’s value is copied back to the caller

  18. Parameter-passing methods Implementation models of parameter passing • Pass-by-reference (inout mode) • This is inout mode implemented by passing an access path (an address) to the called subprogram. • Provides the access path to the cell storing the actual parameter. • Thus, the called subprogram is allowed to access the actual parameter in the calling program unit. • In effect, the actual parameter is shared by the caller and the callee (called subprogram) • Also called pass-by-sharing

  19. Parameter-passing methods Implementation models of parameter passing • Summary - • For all these parameter-passing methods, formal parameters are bound to • actual values or • addresses at the time of the subprogram call. • The semantics of pass-by-value-result is identical to those of pass-by-reference.

  20. Parameter-passing methods Implementation models of parameter passing • Pass-by-name (Not widely used) • The actual parameter is textually substituted for the corresponding formal parameter. • A pass-by-name formal parameter is bound to an access method at the time of the subprogram call • But the actual binding to a value or an address is delayed until the formal parameter is assigned or referenced.

  21. Parameter-passing methods Implementation models of parameter passing • Pass-by-name • Implementing a pass-by-name parameter requires a subprogram to be passed to the called subprogram to evaluate the address or value of the formal parameter. • The referencing environment of the passed subprogram must also be passed. This subprogram/referencing environment is a closure. • Pass-by-name parameters are both complex to implement and inefficient.

  22. The General Semantics of Subprogram Returns • General semantics issues of subprogram returns: • The required actions of a subprogram return include: • If the subprogram has outmode and in-outmode parameters (implemented by copy) must have their values returned of associated formal parameters to the actual parameters. • De-allocation of stack-dynamic storage used for local variables • Restore the execution status of the caller • Return the control back to the caller (the calling program unit)

  23. Implementing “Simple” Subprograms • “Simple” means that subprograms cannot be nested and all local variables are static. • Call Semantics: The semantics of a call to a simple subprogram requires the following actions • Savethe execution status of the caller • Compute and pass the parameters • Passthe return address to the called (i.e., callee) • Transfer control to the called

  24. Implementing “Simple” Subprograms • Call Semantics: The semantics of a call to a simple subprogram requires the following actions (i.e., call semantics): • Save the execution status of the caller • Compute and pass the parameters • Pass the return address to the callee • Transfer control to the callee • Who is responsible for these actions? • The final three actions must be done by the caller. • Saving the execution status of the caller could be done by either.

  25. Implementing “Simple” Subprograms (continued) • Return Semantics: The semantics of a return from a simple subprogram requires the following actions: • If pass-by-value-result (in-out mode) parameters are used, • movethe current values of those parameters to their corresponding actual parameters • If the subprogram is a function, • move the functional value (return value) to a place accessible to the caller • Restore the execution status of the caller • Transfer control back to the caller • Who is responsible for these actions?

  26. Implementing “Simple” Subprograms (continued) • Who is responsible for these actions? • The first, second, and fourth actions must be done by the called subprogram. • Again the restoration of the execution status of the caller (the calling program unit) could be done by either the caller or the called subprogram.

  27. Implementing “Simple” Subprograms (continued) • Required Storage: The call and return actions require storage for the following: • Status information about the caller • Parameters • return address • return value for functions • Temporaries used by the code of the subprograms • Along with the local variables and the subprogram code, these form the complete collection of information a subprogram needs to execute and then return control to the caller

  28. Implementing “Simple” Subprograms (continued) • Linkage: In general, the linkage actions of the called subprogram can occur at two different times, either • at the beginning of its execution (called the prologue of the subprogram linkage), or • at the end of its execution (called the epilogue of the subprogram linkage). • For a simple subprogram, all of the linkage actions of the callee occur at the end of its execution.

  29. Implementing “Simple” Subprograms • A simple subprogram has two separate parts: • the actual code of the subprogram, which is constant • the non-code part (local variables and data that can change when the subprogram is executed) • For simple subprograms, both of these parts have fixed sizes.

  30. Implementing “Simple” Subprograms • A simple subprogram has two separate parts: • the actual code of the subprogram, and the non-code part. • The format, layout, of the non-code part of an executing subprogram is called an activation record • The form of an activation is static • The data it describes are relevant only during the activation or execution of the subprogram • An activation record instance is a concrete example of an activation record • Contains a collection of data for a particular subprogram in the form of an activation record.

  31. Implementing “Simple” Subprogramsan activation record for simple subprograms • A simple subprogram does not support recursion. • There can be only a single instance of the activation record for a subprogram. • The activation record instance has fixed size. • It is statically allocated. • It could be attached to the code part of the subprogram. • One possible layout for activation records is as follows: An activation record for simple subprogram

  32. Implementing “Simple” SubprogramsCode and activation records of a program with “simple” subprograms MAIN Data • A figure shows a program consisting of a main program and three subprograms, A, B and C. • The figure shows all the code segments separated from all the activation record instances,in some cases, the activation record instances are attached to their associated code segments. The code and activation records of a program with simple subprograms An activation record for simple subprogram A B C Code MAIN A B C

  33. Implementing “Simple” Subprogramsan activation record • The construction of the complete program shown in previous viewgraph is not done entirely by the compiler. • Compileeach unit, write the machine code, with a list of references to external subprograms, to a file • The linker puts together the executable program shown in previous viewgraph. • The linker is part of the operating system. • Sometimes, linkers are called loaders, linker/loaders, or link editors.

  34. Implementing “Simple” Subprogramsan activation record • When the linker is called for a main program, • Find the files that contain the translated subprograms referenced in that program and • load them into memory. • Then set the target addresses of all calls to those subprograms in the main program to the entry addresses of those subprograms. • The same must be done for all calls to subprograms in the loaded subprograms and all calls to library subprograms.

  35. Implementing “Simple” Subprogramsan activation record MAIN Data • Example: The linker was called for the MAIN. • The linker finds the machine code programs for A, B, and C, along with their activation record instances, and loads them into memory with the code for MAIN. • Then it has to patch in the target addresses for all calls to A, B, C and any library subprograms called in A, B, C, and MAIN. A B C Code MAIN A B C

  36. Implementing “Simple” Subprograms • Two separate parts: • the actual code • the non-code part (local variables and data that can change) • The format, layout, of the non-code part of an executing subprogram is called an activation record • An activation record instance is a concrete example of an activation record • Contains the collection of data for a particular subprogram

  37. Physical Structure of a Running Program

  38. Implementing Subprograms with Stack-Dynamic Local Variables: Activation Record • The activation record format is static, but its size may be dynamic • ESP – Stack Pointer register • Used by PUSH and POP instructions, points to top of stack • EBP – Base Pointerregister :dynamic link • Used to reference parameters and local variables on the stack • An activation record instance is dynamically created when a subprogram is called • Activation record instances reside on the run-time stack : top top

  39. Implementing Subprograms with Stack-Dynamic Local Variables: Activation Record instance for function sub • Consider the following skeletal C function: void sub(float total, int part) { int list(5); float sum; …} void main() { float x; … sub(45.6, 30); L: … } • The activation record for function sub is: top sub function’s AR. This stack is part of the run-time system and therefore is call the run-time stack

  40. Revised Semantic Call/Return Actions • Caller’s Actions: • Create an activation record instance • Save the execution status of the current program unit • Compute and pass the parameters • Save the return address of the caller • Transfer control to the callee • Callee’s Prologue Actions: • Save the old EP/BP(environment pointer/base pointer, ebp) in the stack as the dynamic link and create the new value • Allocate local variables

  41. The General Semantics of Calls • The caller actions are as follows: • Create an activation record instance. • Save the execution status of the current program unit. Upon returning from the calling program, the caller needed to resume execution of a calling subprogram. Things include register values, CPU status bits and the environment pointer (EP, used to access parameters and local variables during the execution of a subprogram). • Compute an pass the parameters. • Pass the return address to the called program. • Transfer control to the called program.

  42. The General Semantics of Calls • The prologue actions of the called program are as follows: • Save the old EP in the stack as the dynamic link and create the new value. • Allocate local variables.

  43. The General Semantics of Calls • The epilogue actions of the called program are as follows: • If there are pass-by-value-result or out-mode parameters, the current values of those parameters are moved to the corresponding actual parameters. • If the subprogram is a function, the functional value is moved to a place accessible to the caller. • Restore the stack pointer SP by setting it to the value of the current EP minus one and set the EP to the old dynamic link. • Restore the execution status of the caller. • Transfer control back to the caller.

  44. An Example Without Recursion void fun1(float r) { int s, t; ... 1 fun2(s); ... } void fun2(int x) { int y; ... 2 fun3(y); ... } void fun3(int q) { ... (3) } void main() { float p; ... fun1(p); ... } The sequence of function calls in this program is: main calls fun1 fun1 calls fun2 fun2 calls fun3

  45. The stack contents for the points labeled 1, 2, and 3 are as follows: • At point 1, only the activation record instances for function main and function fun1 are on the stack. ARI = activation record instance void fun1(float r) { int s, t; ... 1 fun2(s); ... } void fun2(int x) { int y; ... 2 fun3(y); ... } void fun3(int q) { ... (3) } void main() { float p; ... fun1(p); ... }

  46. The stack contents for the points labeled 1, 2, and 3 are as follows: • When fun1 calls fun2, an instance of fun2’s activation record is created on the stack. ARI = activation record instance void fun1(float r) { int s, t; ... 1 fun2(s); ... } void fun2(int x) { int y; ... 2 fun3(y); ... } void fun3(int q) { ... (3) } void main() { float p; ... fun1(p); ... }

  47. The stack contents for the points labeled 1, 2, and 3 are as follows: • When fun2 calls fun3, an instance of fun3’s activation record is created on the stack. ARI = activation record instance void fun1(float r) { int s, t; ... 1 fun2(s); ... } void fun2(int x) { int y; ... 2 fun3(y); ... } void fun3(int q) { ... (3) } void main() { float p; ... fun1(p); ... }

More Related