[LLVMdev] nonlocal go to -- how?
Hendrik Boom
hendrik at topoi.pooq.com
Sun May 4 16:56:22 PDT 2008
On Sun, 04 May 2008 16:05:44 +0000, Hendrik Boom wrote:
> The languages I'm faced with compiling in the near future have nonlocal
> go to statements and nested procedures.
>
> A procedure gets implemented as a structure containing its entry point
> and an environment pointer. It is easy enough to call its entry point
> and pass the environment pointer as an extra argument (rather like the
> pointer to this or self in object-oriented code). It's no problem. The
> trampoline intrinsic is a neat way of packaging this so as to retrofit
> into C's one-address-only function pointer, but that's not necessary in
> a language where procedures are all known to have this behaviour.
>
> The problem is with the go to statement. Again, local go to's, that go
> somewhere within the same function are no particular problem -- though I
> haven't studied the interaction with alloca yet; that might offer a few
> surprises. The questions I have are about goto's that exit from a
> function. The traditional mechanism is to implement a label as an
> instruction-pointer/environment-pointer pair, just as for procedures.
> You just load the environment-pointer into the appropriate register, and
> jump to the address. (again there are technical details about the size
> of the local stack at the destination, disposition of alloca storage,
> and the like, and nowadays, unwinding the stack).
>
> I don't see a mechanism for this.
>
> The closest I see is the mechanism for exceptions. I cannot tell by
> reading the documentation for exception-handling whether it is
> sufficiently flexible to accomodate nonlocal goto's. It's plain that on
> modern systems (which dribble saved registers all over the sack) some
> kind of unwinding is necessary, and that the traditional model of
> loading a register and jumping is no longer sufficient. What's not
> clear is whether the exception handling mechanism is sufficiently
> dynamic to permit an accurate specification of the jump target. It's
> not necessarily the most local version of the label on the stack that's
> the target; it's the one whose stack frame is reached by the jumping
> procedure's array of static links.
>
> -- hendrik
Well, I suppose it could be kind of done in not-quite C++, and therefore
it could probably be made to work in LLVM, like this.
Labels are values, like:
struct Label{ void * level, *target; }
The level identifies the activation record in which the jump target
occurs; the target is the actual address of the instruction to be jumped
to when the label is used.
Suppose the high-level language defined a label L in functino foo. Then
we build a Label object LL to represent it.
foo()
{
Label LL;
LL.level = ≪
LL.target = &L;
...
...
L:
}
Someplace else, syntactically nested within foo, there's another function
bar, which contains a goto L.
This goto gets translated into something like:
Translate the goto inso something like
throw appropriate_static_link->LL;
where appropriate static link is whatever is needed to access the proper
variable in the enclosing scope.
Around every call *from* any function that contains a Label, we have code
like:
try(
the_call
}
catch(Label e)
{ if(e.level == LL.level)
goto e.label;
else throw e;
}
Of course this coding requires that you can take addresses of labels and
jump to them later in C++, which as far as I can recall is not one of its
language features.
But LLVM is a lower-level language, so I'm hoping that something similar
can be accomplished. But I haven't noticed dynamic arguments to the br
instruction.
-- hendrik
More information about the llvm-dev
mailing list