The default of the dispatch switch statement was to branch to a BB that executed

the 'unwind' instruction. However, later on that instruction was converted into
a jump to the basic block it was located in, causing an infinite loop when we
get there.

It turns out, we get there if the _Unwind_Resume_or_Rethrow call returns (which
it's not supposed to do). It returns if it cannot find a place to unwind
to. Thus we would get what appears to be a "hang" when in reality it's just that
the EH couldn't be propagated further along.

Instead of infinitely looping (or calling `unwind', which none of our back-ends
support (it's lowered into nothing...)), call the @llvm.trap() intrinsic
instead. This may not conform to specific rules of a particular language, but
it's rather better than infinitely looping.

<rdar://problem/9175843&9233582>


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129302 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2011-04-11 21:32:34 +00:00
parent 35563fee7b
commit cc88595bce

View File

@ -443,16 +443,17 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F);
// Insert a load of the callsite in the dispatch block, and a switch on its
// value. By default, we go to a block that just does an unwind (which is the
// correct action for a standard call).
BasicBlock *UnwindBlock =
BasicBlock::Create(F.getContext(), "unwindbb", &F);
Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock));
// value. By default, we issue a trap statement.
BasicBlock *TrapBlock =
BasicBlock::Create(F.getContext(), "trapbb", &F);
CallInst::Create(Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap),
"", TrapBlock);
new UnreachableInst(F.getContext(), TrapBlock);
Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true,
DispatchBlock);
SwitchInst *DispatchSwitch =
SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(),
SwitchInst::Create(DispatchLoad, TrapBlock, Invokes.size(),
DispatchBlock);
// Split the entry block to insert the conditional branch for the setjmp.
BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(),
@ -561,7 +562,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
// Replace all unwinds with a branch to the unwind handler.
// ??? Should this ever happen with sjlj exceptions?
for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) {
BranchInst::Create(UnwindBlock, Unwinds[i]);
BranchInst::Create(TrapBlock, Unwinds[i]);
Unwinds[i]->eraseFromParent();
}