Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
dizzywhip
Dec 23, 2005

I've got a homework assignment that's driving me nuts. I'm implementing a compiler for a custom language that translates to C. This language supports nested functions that can reference variables in their parent functions. From what I understand, the best way to implement this is to pass a static link (a pointer to the stack frame of the enclosing function) to each function, from which you can find the variable you want by applying a constant offset.

The problem I'm having is that I can't seem to figure out a way to consistently get the correct offset for a given variable. Here's a quick example:

code:
// This function is nested inside parent and tries to print the value of x inside parent.
void nested(void* staticLink) {
    // Need to figure out the offset at compile time.
    printf("%d\n", *(int*)((long)staticLink + ???));
}

void parent(void* staticLink) {
    int x = 5;
    nested((void*)&staticLink);
}
I've been looking at the addresses of the local variables, but I've been unable to find an identifiable pattern from which to calculate an offset. For example, if I have up to 4 local ints, they seem to be at staticLink + 20, 16, 12, and 8 respectively. But if I have 5 local ints, it's something else entirely.

First of all, am I on the right track with this? I'm not sure if using a pointer to the parent function's first parameter is the "proper" way to implement a static link. Second, how can I determine the offset of a given local variable from the static link at compile time? It'd be a heck of a lot easier if I knew exactly what a given function's stack frame looked like, but I'm not sure how to figure that out.

A nudge in the right direction would be greatly appreciated.

Adbot
ADBOT LOVES YOU

dizzywhip
Dec 23, 2005

Ugg boots posted:

Just figure out which variables from the parent function are being used in the nested function and pass references/pointers to all of them when calling the nested function.

I guess that would work, though when we were going over the assignment in class the professor specifically mentioned that we should use a static link. Wikipedia and other places online also mention that as being the way nested functions are typically implemented. I'll probably do it this way as a last resort though.

pseudorandom name posted:

You can't predict anything about the layout of stack variables. The compiler can (and will) place them in any order it feels like, sometimes combining multiple variables into a single stack slot or never allocating any stack space at all.

That makes sense. I suppose the solution is to figure out the offset at run time then?

rjmccall posted:

There are tons of different ways to implement nested functions. There are several key points of language design which influence the choice:
  • Are captured variables captured by reference or by value?
  • Do you need to be able to take the address of the nested function? i.e., if you have an expression which names the nested function, can you do anything with it besides immediately call it? If so:
    • Does a reference to a nested function have the same type as a reference to a top-level function with the same formal signature would? If so, are there ABI constraints on the representation of that type?
    • What happens if a reference to a nested function outlives the enclosing function?
      • If this doesn't have undefined behavior, then are variables captured by reference allowed to change their address?

If all variables are captured by reference and the only thing you can do with a reference to a nested function is call it, then your basic choice is between Ugg Boots's suggestion (passing the address of every captured variable to the nested function) and Vanadium's (putting all the captured variables in a struct and passing the address of that to nested functions). Remember that you might have multiple levels of nesting.

Variables are captured by reference and functions aren't first-class objects, so all you can do with a function is call it, and you can never reference a function outside of the scope in which it was declared.

I think I'm going to try out figuring out the static link offset at run time for now, and if that doesn't work out I'll go with Ugg Boots's suggestion.

Edit: Well it looks like poo poo but it works. woop :toot:

dizzywhip fucked around with this message at 21:17 on May 6, 2011

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply