summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SjLjEHPrepare.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-04-11 21:32:34 +0000
committerBill Wendling <isanbard@gmail.com>2011-04-11 21:32:34 +0000
commitcc88595bce813464f4dc0c8351f7311bb233a3e2 (patch)
treeae5c3706f99b81550363e232be220ef70b7828cc /lib/CodeGen/SjLjEHPrepare.cpp
parent35563fee7b52f3bc9ef828abc139e8d9cb4ba2b9 (diff)
downloadllvm-cc88595bce813464f4dc0c8351f7311bb233a3e2.tar.gz
llvm-cc88595bce813464f4dc0c8351f7311bb233a3e2.tar.bz2
llvm-cc88595bce813464f4dc0c8351f7311bb233a3e2.tar.xz
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
Diffstat (limited to 'lib/CodeGen/SjLjEHPrepare.cpp')
-rw-r--r--lib/CodeGen/SjLjEHPrepare.cpp15
1 files changed, 8 insertions, 7 deletions
diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp
index aaa8568c2f..43904a76cf 100644
--- a/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/lib/CodeGen/SjLjEHPrepare.cpp
@@ -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();
}