summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/WinEHPrepare.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/WinEHPrepare.cpp')
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index fefb444cea9..3eed086a40d 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -144,6 +144,7 @@ private:
Function &F);
bool prepareExplicitEH(Function &F,
SmallVectorImpl<BasicBlock *> &EntryBlocks);
+ void replaceTerminatePadWithCleanup(Function &F);
void colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &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<TerminatePadInst>(First);
+ if (!TPI)
+ continue;
+
+ if (TPI->getNumArgOperands() != 1)
+ report_fatal_error(
+ "Expected a unary terminatepad for MSVC C++ personalities!");
+
+ auto *TerminateFn = dyn_cast<Function>(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<BasicBlock *> &EntryBlocks) {
SmallVector<std::pair<BasicBlock *, BasicBlock *>, 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);
OpenPOWER on IntegriCloud