"Rodney M. Bates" <[EMAIL PROTECTED]> writes: > When executing in foo, the frame pointer will point to a fixed spot in the > activation record of foo. On i386, the FP is %ebx and it points to the > dynamic link field. From there, loc is at displacement -4. Code in the > body of foo will reference x at -4(FP). > > When we get into any instance of s1, s1's AR will contain a static link that > points to the AR of foo, which is what you said. The question is where > in foo's AR does the SL point to. It would make sense for it to be the same > as where the frame pointer points when executing in foo, i.e., the static > link would point to the dynamic link field of foo's AR. Then x could be > accessed from within sl by loading the SL into some register, say REG, and > referring to -4(REG). loc is at the same displacement relative to the static > link in s1 as is used in foo relative to the FP.
Thanks for the explanation. I think I may now understand what you are getting at. Consider this slight adjustment to your example: extern void bar (int *, int *); int foo (int x, int y) { int a; int loc; int b; int s1 () { if (--y == 0) return 0; return loc + s1 (); } loc = x; bar (&a, &b); bar (&a, &b); return s1 (); } When I compile this, the static chain is 24 bytes off from the frame pointer. That example was just to show an aspect of how gcc implements the activation record. gcc builds a struct holding all the information which needs to be referenced. Then it passes the address of that struct as the static chain. If you pass a variable size object (e.g., int a[i]) then gcc will store a pointer to that object in the activation record. gcc will also store a pointer if you try to pass down a struct which is a parameter in the calling function. These are examples where it isn't obvious that we want the static chain pointer to be the same as the frame pointer. That said, I think I now agree that since the activation record always has a constant size, we could make the static chain pointer always be the same as the frame pointer. The users would apply a constant offset to their static chain pointer to get to the activation record. Issues would arise on processors with limited offset space in addresses, but those issues are solvable. > This all executes correctly, even if it's a bit strange. But it has to take > extra trouble for the code generator to keep track of two different reference > addresses for the same AR and adjust SL offsets to be different from FP > offsets for the same AR. I can't see any benefit. It doesn't change the > set of fields a SL can access in the AR it points to a bit. Only the > displacements needed change. Actually, it is not extra trouble for the code generator, it is less trouble. The code generator simply builds an internal struct to serve as the activation record, puts the struct on the stack, and makes the static chain always be a pointer to that struct. The code generator moves simple values into the struct, and stores pointers for complex values. Then all references through the static chain are easy to implement. Making the static chain be the same as the frame pointer requires a bit of extra work because the frame pointer can be eliminated to the stack pointer (via the -fomit-frame-pointer option, which is the default for some processors when optimizing). The static chain pointer would have to be eliminated just as the frame pointer is. > And it wouldn't matter to me, except it's making it a lot more difficult > to give gdb the ability to execute gdb-user-typed calls on nested functions > and pass nested functions as parameters (where gdb has to generate static > link values) and print nonlocal variables (where gdb has to know how to > interpret the contents of a SL). To make that work is going to take more than making the static chain pointer and the frame pointer equivalent. You are going to have to know how to build the activation record, which as we have seen can contain pointers to variables which live in the frame. So I think you are on the wrong path here. Instead of trying to equate the static chain pointer and the frame pointer, I think what you need to do is find some way for the debugging information to describe the activation record, and to describe where it lives on the stack. Ian