1 / 39

Honors Compilers

Honors Compilers. Addressing of Local Variables Mar 19 th , 2002. Procedure frame. 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 .

meghan
Download Presentation

Honors Compilers

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. Honors Compilers Addressing of Local Variables Mar 19th, 2002

  2. Procedure frame • Assume stack builds down • Parameters  stored by callerReturn point  stored by calleeSaved regs  stored by calleeOld frame ptr  stored by calleeFRAME PTR local variables STACK PTR 

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

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

  5. 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 • For a variable of dynamic size (e.g. a local array with dynamic bounds), we use a hidden pointer

  6. Addressing a Variable Length Object • 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.

  7. Variables in Blocks • 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 • For example, rename to a1, a2 • Now just include a1,b,c,a2,d,e in parent frame and address of parent frame ptr • Can overlap the sets of variables

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

  9. Variables in Blocks (continued) • 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 10000 Copy stack ptr to __a Address indirectly through __a On block exit Restore stack ptr from saved location

  10. Up Level Addressing • 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

  11. 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) • How does inner frame find the outer frame? • If we know frame ptr of outer, we can address off that, in the usua fashion.

  12. A Horrible Solution • The Saved frame pointer links each frame to the previous one. • 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. • Then get the variable you want

  13. Some Observations • 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 • 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.

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

  15. The Uplevel Addressing Problem • 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-2 level procedure • Etc.

  16. How to Find Up Level Variables • For a level N procedure • We need the address of the level N frame • 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-2 level frame (statically enclosing us)

  17. One Solution, Static Links • Pass an extra param on every call • Called the static link • 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.

  18. How to Use The Static Link • To address your own variables, use the frame pointer. • 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 • Etc.

  19. How to Set The Static Link • Assume you are a level N procedure • 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 Q procedure (Q < N), find the address of the level Q-1 frame and pass that (see previous slide).

  20. More on Static Links • When calling a global procedure (level 1) • No need to pass a static link • In practice many calls are to global procedures • 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.

  21. Another Solution: Global Display • Maintain a global table • 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. • Entry Q is frame pointer for statically enclosing level Q procedure = most recently called level Q procedure

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

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

  24. Notes on Global Display • 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 • 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.

  25. 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. • 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. • So overhead only for calling a procedure with at least one nested procedure.

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

  27. 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 level Q (Q < N) procedure, access Qth entry of local display.

  28. 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). • 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.

  29. Procedure Parameters • Go back to our Inner/Outer example • Suppose that both inner and outer are recursive • 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.

  30. 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. • Form of procedure value depends on the way that up level referencing is handled.

  31. 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 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

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

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

  34. Static Links vs Global Display • Global display probably more efficient • Only large procedures have nested procedures inside • All leaf procedures have no nested procedures • 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.

  35. 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 works for almost everything, but there is one case which is a problem

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

  37. 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); • The body of sqrtsin references local parameters a, b from an enclosing proc • By the time we call sqrtsin, these parameters are long gone

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

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

More Related