This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: A correction: Different invariants about the contents of static links]


"Rodney M. Bates" <rbatesjk@cox.net> 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]