nontail Bug continuations

Matthew Fluet fluet@CS.Cornell.EDU
Sun, 11 Nov 2001 08:56:02 -0500 (EST)


> > > I just fixed a weird bug caused by the interaction of removeUnused and
> > > the shrinker.  RemoveUnused changes unreachable continuations into Bug
> > > continuations.  
> > 
> > It's not that weird; or, rather, I kept meaning to mention that the
> > shrinker should turn Bug continuations into tail calls because
> > removeUnused would introduce them. ;)
> 
> Ahh.  Thinking a little more, I wonder if we should treat
> continuations exactly as we treat handlers, and have a case for
> expressing that we don't care what the continuation is.  That would
> let us turn nontail calls to functions that we can prove never return
> into tail calls with a don't care continuation.  Right now, we can
> sometimes turn these into tail calls, but not always, if the types
> don't match up.

That would be nice enough for the SSA IL, but I think things would get a
little tricky in backend.  In particular, how do you translate

Call {func, args, 
      return = {cont = None, handler = Handler.Handle l}}
or
Call {func, args, 
      return = {cont = Cont.CallerCont, handler = Handler.Handle l}}

We need to do a non-tail call, because the handler's live data is in the 
callee's frame.  I guess it's not that big a deal; we're creating dummy
stubs for each cont/handler pair anyways, so this wouldn't be that
different.  Except in the second case, we need a continuation that does
nothing but return.  But, maybe this isn't that hard.  We could change
implementHandlers to implementCalls, and have it introduce those bogus bug
and return continuations in the right place; i.e., we need a clean-up pass
that puts SSA IL calls into a cannonical form expected by backend.  I
think that the right invariant would be

handler = Handler.Handle h ==> cont = Cont.Cont l

If handler = Handler.None or Handler.CallerHandler, then we can make
either a tail or a non-tail call.

Of course, this goes back to something I was asking about over the summer:
why not treat return-continuations and raise-continuations in exactly the
same manner?  In particular, going around a loop that makes a non-tail
call with a handler, we want implementHandlers to just set the handler
once before entering the loop.  It would also be nice to set the return
continuation once before entering the loop; but I think this complicates
the interface to the GC.