[LLVMdev] Darwin vs exceptions

Duncan Sands baldrick at free.fr
Mon Dec 10 11:38:03 PST 2007

Hi Dale,

> > ...  Suppose we don't artificially add catch-alls to  
> > selectors.  Then
> > the above example compiles to:
> > ...
> I wasn't advocating this; agree it is wrong.

it's maybe not as wrong as it seems since having an empty
selector is equivalent to having a cleanup (IIRC) :)

> >  ... If you force a "cleanup" by changing the selector call to:
> >        %eh_select8.i = tail call i32 (i8*, i8*, ...)*  
> > @llvm.eh.selector.i32( i8* %eh_ptr.i, i8* bitcast (i32 (...)*  
> > @__gxx_personality_v0 to i8*), i32 0)
> > then it doesn't work either: the unwinder observes that there is  
> > only a cleanup, and
> > using some special logic (bogus in this case) deduces that the  
> > exception will be rethrown
> > after running the cleanup code (and thus the program terminated), so  
> > doesn't bother running
> > the cleanup code and directly terminates the program (apparently  
> > terminating programs quickly
> > was important to whoever wrote the unwinder, I don't know why; the  
> > Ada unwinder doesn't do
> > this for example :) ).
> OTOH, claiming that everything has a cleanup seems to me a correct  
> description of what the IR code does:  control reenters the throwing  
> function to execute a possibly null cleanup,  then resumes.

I agree, and this is why I originally tried to get the desired effect
using cleanups.

> The trouble is you can't simply copy that IR while inlining and expect  
> things to still work, because the operation of Unwind_Resume depends  
> on what stack frame it's in.   I don't agree that the inlined version  
> is correct IR.  The 'invoke semantics' you're talking about are  
> inextricably intertwined with _Unwind_Resume's semantics.

The semantics of invoke are described in the LangRef.  I took the
approach of artificially obtaining these semantics, which have an
impedance mismatch with the gcc unwinder, by playing with the way we
set up the exception table.  If you manage to obtain invoke semantics
then you can expect inlining to work.  And I did manage to obtain them
on linux - so this was a simple solution that also meant I didn't have
to audit all the optimizers to check how they used invoke (though most
likely the inliner is the only one that matters).

You are suggesting changing the meaning of invoke, a bolder approach
which certainly has some advantages.  If I understand right you want
to allow some exceptions to unwind through an invoke without branching
to the unwind label (instead they just keep on unwinding); which
exceptions are caught is to be determined by the eh.selector call.
In other words, you want to model LLVM's EH on the way the gcc unwinder
works.  With this model indeed the inliner needs to copy the selector
to the appropriate places when inlining.  Perhaps some other optimizers
need to be tweaked too.  Unfortunately this approach immediately hits
PR1508 (http://llvm.org/bugs/show_bug.cgi?id=1508), i.e. the problem
of actually finding the selector for a landing pad.  Personally I would
like to see the selector somehow be attached to the unwind edge - perhaps
it could be done as part of PR1269.

> > ... It is true that you can imagine a solution in which the inliner  
> > knows about selector calls
> > and shuffles them around.  I will think about this.  That said,  
> > invoke is defined to have
> > certain semantics, and I don't much like the idea of trying to do an  
> > end-run around them
> > and around optimizers that exploit them...
> I don't see much choice.  I guess I'll look at getting the inliner to  
> do what I think it should do.   (I'll make it Darwin-specific at  
> first, but it should work on Linux, and let me point out that you'll  
> get more efficient code this way.)

Yes, you certainly will get more efficient unwinding.  This probably
doesn't matter much for Ada or C++, but I guess some languages out
there like to throw exceptions a lot.

> I guess an easy but undesirable fallback position is to tell the  
> inliner not to inline anything that invokes Unwind_Resume.

If you push a "cleanup" instead of a catch-all on Darwin, does
everything work?  This is exactly what you get if you apply your

-  lang_eh_catch_all = return_null_tree;
+/*  lang_eh_catch_all = return_null_tree;*/



More information about the llvm-dev mailing list