[llvm-commits] [patch] Fix the inlining of invokes into invokes for libUnwind-like EH implementations
Bill Wendling
wendling at apple.com
Mon May 23 14:29:26 PDT 2011
On May 20, 2011, at 6:57 PM, John McCall wrote:
> I couldn't take it anymore, so I wrote up a dirty little patch to fix inlining through invokes. The patch does two things:
>
> 1) Calls (not invokes) of _Unwind_Resume in the inlined function are turned into branches to the unwind dest of the outer invoke.
>
> This is required because we really want to be using _Unwind_Resume to resume after a cleanup, but libUnwind and the standard personality functions don't expect us to call _Unwind_Resume without handling the exception if the action table said we were going to handle it. This is not the ideal solution to this problem — among other things, it requires every landing pad to be capable of correctly handling a cleanup action, even if only trivially — but it's an improvement over the current situation, which actually requires every landing pad to advertise itself as having a catch-all (and then actually handle that!). The ideal solution is not really attainable while still gluing together EH CFGs.
>
> 2) If a call to llvm.eh.selector can be found for the enclosing unwind destination, calls to llvm.eh.selector in the inlined function are augmented with the actions of the outer selector.
>
> This allows the backend to assemble the correct set of unwind actions for a landing pad without gratuitous labor.
>
> In no way is this patch a replacement for a proper revision of LLVM's EH IR: the current IR is still awkward, challenging to optimize and lower to reasonable code, and almost inextricably tied to libUnwind-like unwinders and GCC-style personality functions. But it eliminates the problems with spurious catch-alls that prevent the proper processing of uncaught exceptions, and it permits frontends to go back to emitting cleanups that call themselves cleanups and calls to _Unwind_Resume instead of _Unwind_Resume_or_Rethrow.
>
Hi John,
This looks good, and it may supersede the slow code in DwarfEHPrepare.cpp that's trying to do similar things. A couple of things:
+static bool isUnwindResume(Value *value) {
...
+ if (fnType->isVarArg()) return false;
I think that the Ada front-end generates a call to _Unwind_Resume which takes more than one argument (and possibly a varargs).
+/// [LIBUNWIND] Check whether this selector is "only cleanups":
+/// call i32 @llvm.eh.selector(blah, blah, i32 0)
+static bool isCleanupOnlySelector(EHSelectorInst *selector) {
+ if (selector->getNumArgOperands() != 3) return false;
+ ConstantInt *val = dyn_cast<ConstantInt>(selector->getArgOperand(2));
+ return (val && val->isZero());
+}
This doesn't take 'filters' into account.
+ // Otherwise, we just append the outer selector to the inner selector.
+ SmallVector<Value*, 16> NewSelector;
+ for (unsigned i = 0, e = Inner->getNumArgOperands(); i != e; ++i)
+ NewSelector.push_back(Inner->getArgOperand(i));
+ for (unsigned i = 2, e = Outer->getNumArgOperands(); i != e; ++i)
+ NewSelector.push_back(Outer->getArgOperand(i));
This might not work 100% if there are filters and / or there is a catchall in one or both of the selectors. Basically, the llvm.eh.selector's structure will have to be interpreted for both selectors and reassembled.
-bw
More information about the llvm-commits
mailing list