Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Honors Compilers Addressing of Local Variables Mar 19 th, 2002."— Presentation transcript:

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

2 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 

3 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

4 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

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

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

7 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

8 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 10000 int’s allocated throughout the procedure? Now do we really want to have 10000 int’s allocated throughout the procedure? Perhaps not Perhaps not

9 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 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; …) …) 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

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

12 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

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

14 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

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

16 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)

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

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

19 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).

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

21 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

22 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

23 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

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

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

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

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

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

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

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

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

32 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

33 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

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

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

36 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

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); 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

38 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

39 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


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

Similar presentations


Ads by Google