So I couldn't get exceptions to work on PPC darwin. After much digging and confusion, there seem to be two separate issues. The gcc testsuite is running the version of the unwinding code that was built with the local (llvm-)gcc, which doesn't work because nobody has implemented builtin_return_address for that target. So that's one problem. More seriously, the version of the unwinding code installed on the system doesn't work either, for a different reason (and also doesn't work on x86 Darwin). It turns out the installed code has the following patch, which is not in the llvm-gcc source (or Apple's gcc sources for that matter; libgcc lives in a separate repository these days): Index: gcc/unwind-dw2.c ==================================================================--- gcc/unwind-dw2.c (revision 124749) +++ gcc/unwind-dw2.c (working copy) @@ -1526,7 +1526,7 @@ static inline _Unwind_Ptr uw_identify_context (struct _Unwind_Context *context) { - return _Unwind_GetIP (context); + return _Unwind_GetCFA (context); } I'm uncertain of the merit of this patch, but it's in shipping Leopard and works with gcc, so we're stuck with it. The effect of this is that llvm's strategy of making every C++ selector claim that it has a catch-all handler at the end, as described here http://llvm.org/docs/ExceptionHandling.html#restrictions does not work in this environment. Claiming that a function has a catch-all handler when it does not causes the unwinder to go into a loop. I tried simply removing the code that does this: Index: cp/except.c ==================================================================--- cp/except.c (revision 44663) +++ cp/except.c (working copy) @@ -104,7 +104,7 @@ lang_eh_runtime_type = build_eh_type_type; lang_protect_cleanup_actions = &cp_protect_cleanup_actions; /* LLVM local */ - lang_eh_catch_all = return_null_tree; +/* lang_eh_catch_all = return_null_tree;*/ } /* Returns an expression to be executed if an unhandled exception is and that works well for me; i.e., the gcc tests that exercise exceptions work as well with the two patches above (on x86) as they did before. Now I need some help: - Why was C++ claiming that every selector has a catch-all handler? The documentation above just says the C++ personality function will terminate the program if it detects that unwinding the exception only results in matches with cleanups. Isn't that what's supposed to happen if there's no handler anywhere? - What is the right thing for Linux? Is the deletion above safe there? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20071207/9bb08cf8/attachment.html>
On Dec 7, 2007, at 4:40 PM, Dale Johannesen wrote:> So I couldn't get exceptions to work on PPC darwin. After much > digging and confusion, there seem > to be two separate issues.Ok.> The gcc testsuite is running the version of the unwinding code that > was built with the local (llvm-)gcc, > which doesn't work because nobody has implemented > builtin_return_address for that target. > So that's one problem.That's an easy problem. I just implemented __builtin_return_address on PPC, at least builtin_return_address(0), please let me know if that is sufficient.> More seriously, the version of the unwinding code installed on the > system doesn't work either, for a > different reason (and also doesn't work on x86 Darwin). It turns > out the installed code has the > following patch, which is not in the llvm-gcc source (or Apple's gcc > sources for that matter; libgcc > lives in a separate repository these days):Yuck :)> Index: gcc/unwind-dw2.c > ==================================================================> --- gcc/unwind-dw2.c (revision 124749) > +++ gcc/unwind-dw2.c (working copy) > @@ -1526,7 +1526,7 @@ > static inline _Unwind_Ptr > uw_identify_context (struct _Unwind_Context *context) > { > - return _Unwind_GetIP (context); > + return _Unwind_GetCFA (context); > } > > I'm uncertain of the merit of this patch, but it's in shipping > Leopard and works with gcc, so we're > stuck with it.Right, this is effectively part of the darwin ABI now.> The effect of this is that llvm's strategy of making every C++ > selector claim that it has a catch-all > handler at the end, as described here > http://llvm.org/docs/ExceptionHandling.html#restrictions > does not work in this environment. Claiming that a function has a > catch-all handler when it does > not causes the unwinder to go into a loop.Okay, you're beyond my knowledge here :)> I tried simply removing the code that does this: > > Index: cp/except.c > ==================================================================> --- cp/except.c (revision 44663) > +++ cp/except.c (working copy) > @@ -104,7 +104,7 @@ > lang_eh_runtime_type = build_eh_type_type; > lang_protect_cleanup_actions = &cp_protect_cleanup_actions; > /* LLVM local */ > - lang_eh_catch_all = return_null_tree; > +/* lang_eh_catch_all = return_null_tree;*/ > } > > /* Returns an expression to be executed if an unhandled exception is > > and that works well for me; i.e., the gcc tests that exercise > exceptions work as well with the > two patches above (on x86) as they did before.Ok, cool :) Duncan, Anton, what do you guys think about this?> Now I need some help: > - Why was C++ claiming that every selector has a catch-all handler? > The documentation above just says > the C++ personality function will terminate the program if it > detects that unwinding the exception only results in matches with > cleanups. > Isn't that what's supposed to happen if there's no handler anywhere? > - What is the right thing for Linux? Is the deletion above safe > there?Unsure, -Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20071208/d8092ab0/attachment.html>
Hi Dale,> - Why was C++ claiming that every selector has a catch-all handler?this is easy: because the semantics of invoke require it. Yes, really. If unwinding reaches an invoke then control is required to jump to the unwind basic block. At first I thought this probably wouldn't matter - that it would be OK to not jump to the landing pad if the exception was not being caught by it - and didn't implement it, but several eh failures in the LLVM testsuite could be tracked down to it: the optimizers really do exploit this property of invoke - it is quite subtle. You typically see it when code is massively inlined into one big flat main function. Then I tried to implement it by pushing a "cleanup" at the end of the exception list. But the unwinder treats cleanups specially, and ignores them if during unwinding it only sees cleanups all the way up to the top - in short there were testsuite failures with this approach. So the only thing to do was to push a catch-all on to the end of the list.> The documentation above just says > the C++ personality function will terminate the program if it detects > that unwinding the exception only results in matches with cleanups. > Isn't that what's supposed to happen if there's no handler anywhere?It is, and it is what will happen: with the current code you will unwind into each landing pad and be rethrown until you get to the top. Then the program will be terminated. Yes, this means that you get terminated slightly more slowly than with gcc, however I don't see how to obtain correct invoke semantics (and thus: correctly working programs) without it.> - What is the right thing for Linux? Is the deletion above safe there?No, and it's not safe anywhere else either, though most of the time it doesn't make any difference. Ciao, Duncan.
Hi Chris,> ... Claiming that a function has a > > catch-all handler when it does > > not causes the unwinder to go into a loop.this is the bit I don't understand. Why does it go into a loop? How can the unwinder possibly know that the original code did not have a catch-all, since we tell it which catches there are and we say: there is a catch-all!> > - lang_eh_catch_all = return_null_tree; > > +/* lang_eh_catch_all = return_null_tree;*/> Ok, cool :) Duncan, Anton, what do you guys think about this?This is wrong - it breaks the semantics of invoke and causes eh to not work properly in some cases (see my email to Dale). Ciao, Duncan.
On Dec 8, 2007, at 12:48 AM, Duncan Sands wrote:> Hi Dale, > >> - Why was C++ claiming that every selector has a catch-all handler? > > this is easy: because the semantics of invoke require it. Yes, > really. > If unwinding reaches an invoke then control is required to jump to the > unwind basic block. At first I thought this probably wouldn't > matter - > that it would be OK to not jump to the landing pad if the exception > was > not being caught by it - and didn't implement it, but several eh > failures > in the LLVM testsuite could be tracked down to it: the optimizers > really > do exploit this property of invoke - it is quite subtle. You > typically see > it when code is massively inlined into one big flat main function. > Then I > tried to implement it by pushing a "cleanup" at the end of the > exception > list. But the unwinder treats cleanups specially, and ignores them > if during > unwinding it only sees cleanups all the way up to the top - in > short there > were testsuite failures with this approach. So the only thing to > do was > to push a catch-all on to the end of the list.OK, playing around with the testsuite it appears there's a bug in llvm's inliner with EH, which is probably what's causing the effect you're talking about. Suppose we have #include <cstdio> class A { public: A() {} ~A() {} }; void f() { A a; throw 5.0; } main() { try { f(); } catch(...) { printf("caught\n"); } } The IR for f correctly has the throw call reaching the landing pad, which cleans up 'a' and then calls Unwind_Resume. Inlining g into f naively copies this structure which is wrong; we do not want to call Unwind_Resume in this case because there is a real handler in the same function. See the code produced by gcc -O3. I think what you did is make this incorrect Unwind_Resume work (on your OS), but that's not the right way to fix this.>> The documentation above just says >> the C++ personality function will terminate the program if it detects >> that unwinding the exception only results in matches with cleanups. >> Isn't that what's supposed to happen if there's no handler anywhere? > > It is, and it is what will happen: with the current code you will > unwind > into each landing pad and be rethrown until you get to the top. > Then the > program will be terminated. Yes, this means that you get > terminated slightly > more slowly than with gcc, however I don't see how to obtain > correct invoke > semantics (and thus: correctly working programs) without it. > >> - What is the right thing for Linux? Is the deletion above safe >> there? > > No, and it's not safe anywhere else either, though most of the time it > doesn't make any difference. > > Ciao, > > Duncan.