Honors Compilers Addressing of Local Variables Mar 19 th, 2002.

Slides:



Advertisements
Similar presentations
The University of Adelaide, School of Computer Science
Advertisements

CSI 3120, Implementing subprograms, page 1 Implementing subprograms The environment in block-structured languages The structure of the activation stack.
Procedures in more detail. CMPE12cGabriel Hugh Elkaim 2 Why use procedures? –Code reuse –More readable code –Less code Microprocessors (and assembly languages)
CSE 5317/4305 L7: Run-Time Storage Organization1 Run-Time Storage Organization Leonidas Fegaras.
(1) ICS 313: Programming Language Theory Chapter 10: Implementing Subprograms.
Chapter 9 Subprogram Control Consider program as a tree- –Each parent calls (transfers control to) child –Parent resumes when child completes –Copy rule.
1 Storage Registers vs. memory Access to registers is much faster than access to memory Goal: store as much data as possible in registers Limitations/considerations:
Procedures in more detail. CMPE12cCyrus Bazeghi 2 Procedures Why use procedures? Reuse of code More readable Less code Microprocessors (and assembly languages)
1 Chapter 7: Runtime Environments. int * larger (int a, int b) { if (a > b) return &a; //wrong else return &b; //wrong } int * larger (int *a, int *b)
Memory Allocation. Three kinds of memory Fixed memory Stack memory Heap memory.
The Procedure Abstraction Part III: Allocating Storage & Establishing Addressability Copyright 2003, Keith D. Cooper, Ken Kennedy & Linda Torczon, all.
ISBN Chapter 10 Implementing Subprograms.
Run time vs. Compile time
Semantics of Calls and Returns
The environment of the computation Declarations introduce names that denote entities. At execution-time, entities are bound to values or to locations:
Chapter 9: Subprogram Control
Microprocessors Frame Pointers and the use of the –fomit-frame-pointer switch Feb 25th, 2002.
Run-time Environment and Program Organization
1 Run time vs. Compile time The compiler must generate code to handle issues that arise at run time Representation of various data types Procedure linkage.
Chapter 8 :: Subroutines and Control Abstraction
Chapter TwelveModern Programming Languages1 Memory Locations For Variables.
Chapter 7: Runtime Environment –Run time memory organization. We need to use memory to store: –code –static data (global variables) –dynamic data objects.
Runtime Environments What is in the memory? Runtime Environment2 Outline Memory organization during program execution Static runtime environments.
Names and Scope. Scope Suppose that a name is used many times for different entities in text of the program, or in the course of execution. When the name.
Programming Language Principles Lecture 24 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines.
Compiler Construction
CSc 453 Runtime Environments Saumya Debray The University of Arizona Tucson.
1 Copyright © 1998 by Addison Wesley Longman, Inc. Chapter 9 Def: The subprogram call and return operations of a language are together called its subprogram.
10/16/2015IT 3271 All about binding n Variables are bound (dynamically) to values n values must be stored somewhere in the memory. Memory Locations for.
Functions and Procedures. Function or Procedure u A separate piece of code u Possibly separately compiled u Located at some address in the memory used.
CPSC 388 – Compiler Design and Construction Runtime Environments.
Copyright © 2005 Elsevier Chapter 8 :: Subroutines and Control Abstraction Programming Language Pragmatics Michael L. Scott.
Activation Records CS 671 February 7, CS 671 – Spring The Compiler So Far Lexical analysis Detects inputs with illegal tokens Syntactic analysis.
COP4020 Programming Languages Subroutines and Parameter Passing Prof. Xin Yuan.
Runtime Environments. Support of Execution  Activation Tree  Control Stack  Scope  Binding of Names –Data object (values in storage) –Environment.
Runtime Stack Computer Organization I 1 November 2009 © McQuain, Feng & Ribbens MIPS Memory Organization In addition to memory for static.
1 CIS 461 Compiler Design and Construction Winter 2012 Lecture-Module #16 slides derived from Tevfik Bultan, Keith Cooper, and Linda Torczon.
ISBN Chapter 10 Implementing Subprograms.
Implementing Subprograms What actions must take place when subprograms are called and when they terminate? –calling a subprogram has several associated.
RUN-Time Organization Compiler phase— Before writing a code generator, we must decide how to marshal the resources of the target machine (instructions,
ITCS 3181 Logic and Computer Systems 2015 B. Wilkinson Slides4-2.ppt Modification date: March 23, Procedures Essential ingredient of high level.
CSC 8505 Compiler Construction Runtime Environments.
1 Chapter 10 © 2002 by Addison Wesley Longman, Inc The General Semantics of Calls and Returns - Def: The subprogram call and return operations of.
Functions Illustration of: Pass by value, reference Scope Allocation Reference: See your CS115/215 textbook.
7. Runtime Environments Zhang Zhizheng
ISBN Chapter 10 Implementing Subprograms.
Implementing Subprograms
© G. Drew Kessler and William M. Pottenger1 Subroutines, Part 2 CSE 262, Spring 2003.
Subprograms - implementation. Calling a subprogram  transferring control to a subprogram: save conditions in calling program pass parameters allocate.
Procedure Definitions and Semantics Procedures support control abstraction in programming languages. In most programming languages, a procedure is defined.
ISBN Chapter 10 Implementing Subprograms.
1 Compiler Construction Run-time Environments,. 2 Run-Time Environments (Chapter 7) Continued: Access to No-local Names.
ISBN Chapter 10 Implementing Subprograms.
LECTURE 19 Subroutines and Parameter Passing. ABSTRACTION Recall: Abstraction is the process by which we can hide larger or more complex code fragments.
Runtime Environments Chapter 7. Support of Execution  Activation Tree  Control Stack  Scope  Binding of Names –Data object (values in storage) –Environment.
1 Topic 6: Activation Records COS 320 Compiling Techniques Princeton University Spring 2016 Lennart Beringer.
Implementing Subprograms Chapter 10
COMPILERS Activation Records
Implementing Subprograms
The Procedure Abstraction Part IV: Allocating Storage & Establishing Addressability Copyright 2003, Keith D. Cooper, Ken Kennedy & Linda Torczon, all rights.
Functions and Procedures
Chapter 9 :: Subroutines and Control Abstraction
Chap. 8 :: Subroutines and Control Abstraction
Chap. 8 :: Subroutines and Control Abstraction
Stack Frame Linkage.
Implementing Subprograms
Runtime Environments What is in the memory?.
Where is all the knowledge we lost with information? T. S. Eliot
Chapter 10 Def: The subprogram call and return operations of
Presentation transcript:

Honors Compilers Addressing of Local Variables Mar 19 th, 2002

Procedure frame Assume stack builds down Assume stack builds down Parameters  stored by caller Return point  stored by callee Saved regs  stored by callee Old frame ptr  stored by callee FRAME PTR  local variables  STACK PTR  Parameters  stored by caller Return point  stored by callee Saved regs  stored by callee Old frame ptr  stored by callee FRAME PTR  local variables  STACK PTR 

Passing Parameters Parameters can be passed three ways Parameters can be passed three ways In registers In registers On the stack, addressed by stack ptr on entry On the stack, addressed by stack ptr on entry In memory, referenced by an argument ptr In memory, referenced by an argument ptr Cannot pass all parameters in registers Cannot pass all parameters in registers So use method 2 or 3 as a backup So use method 2 or 3 as a backup

Addressing Parameters Parameters in registers Parameters in registers Either keep them in the register and use there Either keep them in the register and use there Or store as a local variable Or store as a local variable Parameters on stack Parameters on stack Address using the frame pointer Address using the frame pointer Parameters referenced by arg ptr Parameters referenced by arg ptr Reference via arg ptr, possibly have to save arg ptr as a local variable if not leaf procedure Reference via arg ptr, possibly have to save arg ptr as a local variable if not leaf procedure

Local Variables If a local variable is of fixed size, it can be addressed directly using a fixed offset from the frame pointer or stack pointer If a local variable is of fixed size, it can be addressed directly using a fixed offset from the frame pointer or stack pointer For a variable of dynamic size (e.g. a local array with dynamic bounds), we use a hidden pointer For a variable of dynamic size (e.g. a local array with dynamic bounds), we use a hidden pointer

Addressing a Variable Length Object Parameters Return point Old frame ptr  frame ptr Fixed part of stack Dynamic object Dynamic object  stack ptr Parameters Return point Old frame ptr  frame ptr Fixed part of stack Dynamic object Dynamic object  stack ptr For each dynamic object we put a pointer into the fixed part of the stack. This pointer can be addressed as a normal fixed length local variable. For each dynamic object we put a pointer into the fixed part of the stack. This pointer can be addressed as a normal fixed length local variable.

Variables in Blocks Consider simple case {int a,b,c ….. } {int a,d,e ….. } Consider simple case {int a,b,c ….. } {int a,d,e ….. } First, the clash of a’s is a compile time issue, not a run-time issue First, the clash of a’s is a compile time issue, not a run-time issue For example, rename to a1, a2 For example, rename to a1, a2 Now just include a1,b,c,a2,d,e in parent frame and address of parent frame ptr Now just include a1,b,c,a2,d,e in parent frame and address of parent frame ptr Can overlap the sets of variables Can overlap the sets of variables

Variables in Blocks (continued) Consider this case {int a[10000]; ….} {int b[10000]; ….} lots more code here Consider this case {int a[10000]; ….} {int b[10000]; ….} lots more code here Now do we really want to have int’s allocated throughout the procedure? Now do we really want to have int’s allocated throughout the procedure? Perhaps not Perhaps not

Variables in Blocks (continued) So in this case {int a[10000]; ….} we could consider using a different technique So in this case {int a[10000]; ….} we could consider using a different technique Allocate *int in enclosing frame (call it __a) On block entry: Save stack pointer in some local variable Decrement stack pointer by Copy stack ptr to __a Address indirectly through __a On block exit Restore stack ptr from saved location

Up Level Addressing PROC outer = (INT x) INT : ( INT a; INT b; PROC inner = (INT y) INT : ( INT c; … c := a + b; …) …) PROC outer = (INT x) INT : ( INT a; INT b; PROC inner = (INT y) INT : ( INT c; … c := a + b; …) …) How do we address a and b from inside inner How do we address a and b from inside inner

Stack Frames Inner could be recursive Stack frame for outer (has a and b) Stack frame for inner Stack frame for inner Stack frame for inner Stack frame for inner Stack frame for inner (references a,b) Inner could be recursive Stack frame for outer (has a and b) Stack frame for inner Stack frame for inner Stack frame for inner Stack frame for inner Stack frame for inner (references a,b) How does inner frame find the outer frame? How does inner frame find the outer frame? If we know frame ptr of outer, we can address off that, in the usua fashion. If we know frame ptr of outer, we can address off that, in the usua fashion.

A Horrible Solution The Saved frame pointer links each frame to the previous one. The Saved frame pointer links each frame to the previous one. Mark each frame with e.g. name of procedure it is for Mark each frame with e.g. name of procedure it is for Trace back frame pointer links until you get to the frame you need outer. Trace back frame pointer links until you get to the frame you need outer. Then get the variable you want Then get the variable you want

Some Observations Label each procedure with its static nesting level (in our example, outer = 1, inner = 2) Label each procedure with its static nesting level (in our example, outer = 1, inner = 2) You can only see one stack frame at most at each static level You can only see one stack frame at most at each static level The one you can see is the nearest one in the dynamic call chain. The one you can see is the nearest one in the dynamic call chain. The one you can see always statically encloses you at some level. The one you can see always statically encloses you at some level.

More Observations A level N procedure can call A level N procedure can call Another level N procedure Another level N procedure A procedure at level 1.. N-1 A procedure at level 1.. N-1 This is an uplevel call This is an uplevel call A procedure at level N+1 A procedure at level N+1 This is a downlevel call This is a downlevel call You cannot call a level N+2 procedure You cannot call a level N+2 procedure

The Uplevel Addressing Problem If you are an N level procedure, you can reference your own variables at level N If you are an N level procedure, you can reference your own variables at level N The variables of the immediately enclosing N-1 level procedure The variables of the immediately enclosing N-1 level procedure The variables of the immediately enclosing N-2 level procedure The variables of the immediately enclosing N-2 level procedure Etc. Etc.

How to Find Up Level Variables For a level N procedure For a level N procedure We need the address of the level N frame We need the address of the level N frame That’s the local frame pointer, no problem That’s the local frame pointer, no problem The address of the nearest enclosing N-1 level frame (statically enclosing us) The address of the nearest enclosing N-1 level frame (statically enclosing us) The address of the nearest enclosing N-2 level frame (statically enclosing us) The address of the nearest enclosing N-2 level frame (statically enclosing us)

One Solution, Static Links Pass an extra param on every call Pass an extra param on every call Called the static link Called the static link If you are calling a level N procedure, this is the address of the nearest level N-1 procedure frame If you are calling a level N procedure, this is the address of the nearest level N-1 procedure frame This static link is stored in the local stack frame at a fixed offset that everyone knows. This static link is stored in the local stack frame at a fixed offset that everyone knows.

How to Use The Static Link To address your own variables, use the frame pointer. To address your own variables, use the frame pointer. To address at N-1, use the static link To address at N-1, use the static link To address at N-2, use the static link to locate the N-1 frame, and then load its static link to locate the N-2 frame To address at N-2, use the static link to locate the N-1 frame, and then load its static link to locate the N-2 frame Etc. Etc.

How to Set The Static Link Assume you are a level N procedure Assume you are a level N procedure To call a level N+1 procedure, pass your frame pointer To call a level N+1 procedure, pass your frame pointer To call a level N procedure, pass a copy of the static link that was given to you siblings must share the same static parent) To call a level N procedure, pass a copy of the static link that was given to you siblings must share the same static parent) To call a level Q procedure (Q < N), find the address of the level Q-1 frame and pass that (see previous slide). To call a level Q procedure (Q < N), find the address of the level Q-1 frame and pass that (see previous slide).

More on Static Links When calling a global procedure (level 1) When calling a global procedure (level 1) No need to pass a static link No need to pass a static link In practice many calls are to global procedures In practice many calls are to global procedures The expression that fetches a level Q static link can be recognized as a CSE The expression that fetches a level Q static link can be recognized as a CSE And for example, if many variables are referenced at level 3, the level 3 frame pointer can end up in a local register. And for example, if many variables are referenced at level 3, the level 3 frame pointer can end up in a local register.

Another Solution: Global Display Maintain a global table Maintain a global table Length of table = max static nesting level of program (can set a reasonable max/measure) Length of table = max static nesting level of program (can set a reasonable max/measure) Within a level N procedure, entries 1-N are defined, Nth entry is copy of frame pointer. Within a level N procedure, entries 1-N are defined, Nth entry is copy of frame pointer. Entry Q is frame pointer for statically enclosing level Q procedure = most recently called level Q procedure Entry Q is frame pointer for statically enclosing level Q procedure = most recently called level Q procedure

Using the Global Display To access local variables in level Q procedure: To access local variables in level Q procedure: Simply use the Q’th entry of the global display as the frame pointer Simply use the Q’th entry of the global display as the frame pointer

Maintaining The Global Display Nothing needs to be done by caller Nothing needs to be done by caller No additional parameter passed No additional parameter passed The called level N procedure on entry: The called level N procedure on entry: Establish frame pointer as usual Establish frame pointer as usual Save N’th level entry of global display Save N’th level entry of global display Set N’th level entry to copy of frame ptr Set N’th level entry to copy of frame ptr The called level N procedure on exit The called level N procedure on exit Restore N’th level entry of global display Restore N’th level entry of global display

Notes on Global Display In a tasking program, you need a separate global display for each task (not needed with static link method) In a tasking program, you need a separate global display for each task (not needed with static link method) Global display can be stored in registers Global display can be stored in registers But that’s not a very good use of registers, better solution is to simply let frequently referenced entries from display migrate into registers as needed. But that’s not a very good use of registers, better solution is to simply let frequently referenced entries from display migrate into registers as needed.

Optimizing Global Display If a procedure has no nested procedures, then no one will ever need its entry in the display, so don’t bother to set it. And of course that means no need to restore. If a procedure has no nested procedures, then no one will ever need its entry in the display, so don’t bother to set it. And of course that means no need to restore. The invariant then becomes The invariant then becomes N’th entry of global display contains the frame pointer of the most recently called procedure that contains at least one nested procedure. N’th entry of global display contains the frame pointer of the most recently called procedure that contains at least one nested procedure. So overhead only for calling a procedure with at least one nested procedure. So overhead only for calling a procedure with at least one nested procedure.

Local Displays Classical Algol method Classical Algol method Within each stack frame keep a local display consisting of entries 1 to N of a global display value. Within each stack frame keep a local display consisting of entries 1 to N of a global display value.

Using a Local Display To access variables in the current level N procedure, use frame pointer as usual, which is the same as level N of the local display. To access variables in the current level N procedure, use frame pointer as usual, which is the same as level N of the local display. To access variables in level Q (Q < N) procedure, access Qth entry of local display. To access variables in level Q (Q < N) procedure, access Qth entry of local display.

Maintaining Local Display When entering a level N procedure, you are being called from a procedure at level N-1 or higher (never from N-2). When entering a level N procedure, you are being called from a procedure at level N-1 or higher (never from N-2). That means that the callers stack frame always has the N-1 entries you need for your local display, so copy them. That means that the callers stack frame always has the N-1 entries you need for your local display, so copy them. Establish a frame pointer as usual, and store as the N’th entry of the local display. Establish a frame pointer as usual, and store as the N’th entry of the local display.

Procedure Parameters Go back to our Inner/Outer example Go back to our Inner/Outer example Suppose that both inner and outer are recursive Suppose that both inner and outer are recursive Suppose that both inner and outer pass procedure parameters Suppose that both inner and outer pass procedure parameters A given procedure value is not just a code address, but also the environment at the time that it is passed. A given procedure value is not just a code address, but also the environment at the time that it is passed.

More on Procedure Values Basically a procedure value is a pointer to the code of the procedure, as well as the status of the invocation stack for any up level references it might have. Basically a procedure value is a pointer to the code of the procedure, as well as the status of the invocation stack for any up level references it might have. Form of procedure value depends on the way that up level referencing is handled. Form of procedure value depends on the way that up level referencing is handled.

Storing a Procedure Value For static links, we just need the address of the procedure frame, since the static links from that frame can recreate the necessary up level addressing information. For static links, we just need the address of the procedure frame, since the static links from that frame can recreate the necessary up level addressing information. For local display, the procedure frame is also sufficient, since the entire up level addressing information is stored in frame. For local display, the procedure frame is also sufficient, since the entire up level addressing information is stored in frame. For global display, need at least entries 1..N-1 of the global display to be stored For global display, need at least entries 1..N-1 of the global display to be stored

Comparison of Methods Local Display Local Display Never used any more Never used any more Clearly dominated by other methods Clearly dominated by other methods Too bad no one told Intel Too bad no one told Intel X86 implements local display in hardware X86 implements local display in hardware Enter x,4 means call a 4 th level procedure and includes copying the local display from the stack frame of the caller to the stack frame of the called function.s Enter x,4 means call a 4 th level procedure and includes copying the local display from the stack frame of the caller to the stack frame of the called function.s

Static Links vs Global Display Static Links Static Links No overhead for calling global procedure No overhead for calling global procedure Efficient representation of procedure value Efficient representation of procedure value Global Display Global Display No overhead for calling procedure with no nested procedures No overhead for calling procedure with no nested procedures Awkward representation of procedure value Awkward representation of procedure value

Static Links vs Global Display Global display probably more efficient Global display probably more efficient Only large procedures have nested procedures inside Only large procedures have nested procedures inside All leaf procedures have no nested procedures All leaf procedures have no nested procedures But mess with procedure parameters nasty But mess with procedure parameters nasty Ada is carefully designed so that no call to a procedure parameter ever modifies the display, so that displays need not be kept. Ada is carefully designed so that no call to a procedure parameter ever modifies the display, so that displays need not be kept.

Closures This entire model assumes that stack frames are created on entry, and destroyed on exit from a procedure in a stack like manner (hence the name) This entire model assumes that stack frames are created on entry, and destroyed on exit from a procedure in a stack like manner (hence the name) This works for almost everything, but there is one case which is a problem This works for almost everything, but there is one case which is a problem

Upward funarg problem Suppose that a procedure outer has a return type that is itself a procedure Suppose that a procedure outer has a return type that is itself a procedure Suppose this procedure outer has a nested procedure, inner Suppose this procedure outer has a nested procedure, inner Suppose that outer returns inner as the returned result Suppose that outer returns inner as the returned result Suppose that inner references a variable of outer Suppose that inner references a variable of outer

An Example MODE INTP = PROC (REAL) REAL; PROC compose = (INTP a, b) INTP : (REAL q) REAL : a (b (q)); INTP sqrtsin = compose (sqrt, sin); REAL result = sqrtsin (0.345); MODE INTP = PROC (REAL) REAL; PROC compose = (INTP a, b) INTP : (REAL q) REAL : a (b (q)); INTP sqrtsin = compose (sqrt, sin); REAL result = sqrtsin (0.345); The body of sqrtsin references local parameters a, b from an enclosing proc The body of sqrtsin references local parameters a, b from an enclosing proc By the time we call sqrtsin, these parameters are long gone By the time we call sqrtsin, these parameters are long gone

Closures in Algol-68 Are not implemented in full generality Are not implemented in full generality In particular cannot have upward funargs In particular cannot have upward funargs Allows simple use of stack frames Allows simple use of stack frames

How to Implement Closures Allocate stack frames on heap Allocate stack frames on heap Don’t remove stack frames on leaving a procedure Don’t remove stack frames on leaving a procedure That way things stay around and are available to reference when needed That way things stay around and are available to reference when needed Need general garbage collection to clean up stack frames eventually Need general garbage collection to clean up stack frames eventually