[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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241699 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner 2015-07-08 18:08:52 +00:00
parent 1ba30c84d5
commit f0999f3b02
3 changed files with 40 additions and 3 deletions

View File

@ -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(

View File

@ -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());
}
}

View File

@ -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()