From: David Majnemer Date: Wed, 16 Sep 2015 20:42:16 +0000 (+0000) Subject: [WinEHPrepare] Turn terminatepad into a cleanuppad + call + cleanupret X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=f7f5dcbad13e13f6a058e186864f7c7623a1a440;p=oota-llvm.git [WinEHPrepare] Turn terminatepad into a cleanuppad + call + cleanupret The MSVC doesn't really support exception specifications so let's just turn these into cleanuppads. Later, we might use terminatepad to more efficiently encode the "noexcept"-ness of a function body. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247848 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index fefb444cea9..3eed086a40d 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -144,6 +144,7 @@ private: Function &F); bool prepareExplicitEH(Function &F, SmallVectorImpl &EntryBlocks); + void replaceTerminatePadWithCleanup(Function &F); void colorFunclets(Function &F, SmallVectorImpl &EntryBlocks); void demotePHIsOnFunclets(Function &F); void demoteUsesBetweenFunclets(Function &F); @@ -3206,6 +3207,44 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, Num.processCallSite(None, ImmutableCallSite()); } +void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) { + if (Personality != EHPersonality::MSVC_CXX) + return; + for (BasicBlock &BB : F) { + Instruction *First = BB.getFirstNonPHI(); + auto *TPI = dyn_cast(First); + if (!TPI) + continue; + + if (TPI->getNumArgOperands() != 1) + report_fatal_error( + "Expected a unary terminatepad for MSVC C++ personalities!"); + + auto *TerminateFn = dyn_cast(TPI->getArgOperand(0)); + if (!TerminateFn) + report_fatal_error("Function operand expected in terminatepad for MSVC " + "C++ personalities!"); + + // Insert the cleanuppad instruction. + auto *CPI = CleanupPadInst::Create( + BB.getContext(), {}, Twine("terminatepad.for.", BB.getName()), &BB); + + // Insert the call to the terminate instruction. + auto *CallTerminate = CallInst::Create(TerminateFn, {}, &BB); + CallTerminate->setDoesNotThrow(); + CallTerminate->setDoesNotReturn(); + CallTerminate->setCallingConv(TerminateFn->getCallingConv()); + + // Insert a new terminator for the cleanuppad using the same successor as + // the terminatepad. + CleanupReturnInst::Create(CPI, TPI->getUnwindDest(), &BB); + + // Let's remove the terminatepad now that we've inserted the new + // instructions. + TPI->eraseFromParent(); + } +} + void WinEHPrepare::colorFunclets(Function &F, SmallVectorImpl &EntryBlocks) { SmallVector, 16> Worklist; @@ -3560,6 +3599,8 @@ bool WinEHPrepare::prepareExplicitEH( // not. removeUnreachableBlocks(F); + replaceTerminatePadWithCleanup(F); + // Determine which blocks are reachable from which funclet entries. colorFunclets(F, EntryBlocks); diff --git a/test/CodeGen/WinEH/wineh-no-demotion.ll b/test/CodeGen/WinEH/wineh-no-demotion.ll index 66857c08ed1..4e4206eb2be 100644 --- a/test/CodeGen/WinEH/wineh-no-demotion.ll +++ b/test/CodeGen/WinEH/wineh-no-demotion.ll @@ -85,3 +85,21 @@ inner: exit: unreachable } + +; CHECK-LABEL: @test3( +define void @test3() personality i32 (...)* @__CxxFrameHandler3 { +entry: + invoke void @f() + to label %invoke.cont unwind label %terminate + +invoke.cont: + ret void + +terminate: +; CHECK: cleanuppad [] +; CHECK: call void @__std_terminate() +; CHECK: unreachable + terminatepad [void ()* @__std_terminate] unwind to caller +} + +declare void @__std_terminate()