diff options
| author | Reid Kleckner <reid@kleckner.net> | 2015-07-08 18:08:52 +0000 |
|---|---|---|
| committer | Reid Kleckner <reid@kleckner.net> | 2015-07-08 18:08:52 +0000 |
| commit | ed012dbf2a6fd7f71e5458ee53fac40ef607df2a (patch) | |
| tree | dfe26d7534a82b070495ff5d815c30af9fc5ba98 | |
| parent | bc832ed51d3c8bf66acbda978889cd9a8355bd87 (diff) | |
| download | bcm5719-llvm-ed012dbf2a6fd7f71e5458ee53fac40ef607df2a.tar.gz bcm5719-llvm-ed012dbf2a6fd7f71e5458ee53fac40ef607df2a.zip | |
[SEH] Ensure that empty __except blocks have their own BB
The 32-bit lowering assumed that WinEHPrepare had this invariant.
WinEHPrepare did it for C++, but not SEH. The result was that we would
insert calls to llvm.x86.seh.restoreframe in normal basic blocks, which
corrupted the frame pointer.
llvm-svn: 241699
| -rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 5 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/seh-simple.ll | 32 |
3 files changed, 40 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 0f84ba0a723..62ef1d4ae57 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -533,9 +533,9 @@ void WinEHPrepare::findSEHEHReturnPoints( BasicBlock *NextBB; Constant *Selector; if (isSelectorDispatch(BB, CatchHandler, Selector, NextBB)) { - // Split the edge if there is a phi node. Returning from EH to a phi node - // is just as impossible as having a phi after an indirectbr. - if (isa<PHINode>(CatchHandler->begin())) { + // Split the edge if there are multiple predecessors. This creates a place + // where we can insert EH recovery code. + if (!CatchHandler->getSinglePredecessor()) { DEBUG(dbgs() << "splitting EH return edge from " << BB->getName() << " to " << CatchHandler->getName() << '\n'); BBI = CatchHandler = SplitCriticalEdge( diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index 0b88d7ab7e5..3a8bcaa4bb7 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -520,6 +520,11 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { for (auto &Handler : ActionList) { if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) { auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc()); +#ifndef NDEBUG + for (BasicBlock *Pred : predecessors(BA->getBasicBlock())) + assert(Pred->isLandingPad() && + "WinEHPrepare failed to split block"); +#endif ExceptBlocks.insert(BA->getBasicBlock()); } } diff --git a/llvm/test/CodeGen/WinEH/seh-simple.ll b/llvm/test/CodeGen/WinEH/seh-simple.ll index a2d13eeb190..060186484ae 100644 --- a/llvm/test/CodeGen/WinEH/seh-simple.ll +++ b/llvm/test/CodeGen/WinEH/seh-simple.ll @@ -107,6 +107,38 @@ eh.resume: ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ] ; CHECK-NEXT: ret i32 %r +define i32 @except_join() personality i32 (...)* @__C_specific_handler { +entry: + invoke void @might_crash() + to label %return unwind label %lpad + +lpad: + %ehvals = landingpad { i8*, i32 } + catch i32 ()* @filt + %sel = extractvalue { i8*, i32 } %ehvals, 1 + %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) + %matches = icmp eq i32 %sel, %filt_sel + br i1 %matches, label %return, label %eh.resume + +return: + ret i32 0 + +eh.resume: + resume { i8*, i32 } %ehvals +} + +; CHECK-LABEL: define i32 @except_join() +; CHECK: landingpad { i8*, i32 } +; CHECK-NEXT: catch i32 ()* @filt +; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_join, %lpad.return_crit_edge)) +; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge] +; +; CHECK: lpad.return_crit_edge: +; CHECK: br label %return +; +; CHECK: return: +; CHECK-NEXT: ret i32 0 + define i32 @lpad_phi() personality i32 (...)* @__C_specific_handler { entry: invoke void @might_crash() |

