OK, Thanks for the information.  Just in case, does anybody already
have it in their head roughly where in gcc code this decision is made?

Ian Lance Taylor wrote:
"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


--
Rodney M. Bates

Reply via email to