diff options
author | Reid Kleckner <rnk@google.com> | 2015-10-08 21:14:56 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2015-10-08 21:14:56 +0000 |
commit | 5e9628e28dadbf03ba7d7fd97f2c62a0d5a6bbd6 (patch) | |
tree | 1068384fb6443c51d1bb041cff5cd6bb6c9e0a6f /lib/CodeGen/CGCleanup.cpp | |
parent | 8f49c4c25cac5d5477c67f557b0f009c93119371 (diff) |
[WinEH] Push cleanupendpad scopes around exceptional cleanups
We were only doing this for SEH as a special case. Generalize it to all
cleanups.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249748 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCleanup.cpp')
-rw-r--r-- | lib/CodeGen/CGCleanup.cpp | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 5796320894..8bad58d78b 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -521,15 +521,6 @@ static void EmitCleanup(CodeGenFunction &CGF, EHScopeStack::Cleanup *Fn, EHScopeStack::Cleanup::Flags flags, Address ActiveFlag) { - // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't - // have this behavior, and the Microsoft C++ runtime will call terminate for - // us if the cleanup throws. - bool PushedTerminate = false; - if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) { - CGF.EHStack.pushTerminate(); - PushedTerminate = true; - } - // If there's an active flag, load it and skip the cleanup if it's // false. llvm::BasicBlock *ContBB = nullptr; @@ -549,10 +540,6 @@ static void EmitCleanup(CodeGenFunction &CGF, // Emit the continuation block if there was an active flag. if (ActiveFlag.isValid()) CGF.EmitBlock(ContBB); - - // Leave the terminate scope. - if (PushedTerminate) - CGF.EHStack.popTerminate(); } static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit, @@ -931,11 +918,29 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); EmitBlock(EHEntry); + + // Push terminate scopes around the potentially throwing destructor calls. + // We don't emit these when using funclets, because the runtime does it for + // us as part of unwinding out of a cleanuppad. + bool PushedTerminate = false; + if (!EHPersonality::get(*this).usesFuncletPads()) { + EHStack.pushTerminate(); + PushedTerminate = true; + } + llvm::CleanupPadInst *CPI = nullptr; + llvm::BasicBlock *CleanupEndBB = nullptr; llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent); - if (EHPersonality::get(*this).usesFuncletPads()) + if (EHPersonality::get(*this).usesFuncletPads()) { CPI = Builder.CreateCleanupPad({}); + // Build a cleanupendpad to unwind through. Our insertion point should be + // in the cleanuppad block. + CleanupEndBB = createBasicBlock("ehcleanup.end"); + CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction); + EHStack.pushPadEnd(CleanupEndBB); + } + // We only actually emit the cleanup code if the cleanup is either // active or was used before it was deactivated. if (EHActiveFlag.isValid() || IsActive) { @@ -948,6 +953,21 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { else Builder.CreateBr(NextAction); + // Insert the cleanupendpad block here, if it has any uses. + if (CleanupEndBB) { + EHStack.popPadEnd(); + if (CleanupEndBB->hasNUsesOrMore(1)) { + CurFn->getBasicBlockList().insertAfter(Builder.GetInsertBlock(), + CleanupEndBB); + } else { + delete CleanupEndBB; + } + } + + // Leave the terminate scope. + if (PushedTerminate) + EHStack.popTerminate(); + Builder.restoreIP(SavedIP); SimplifyCleanupEntry(*this, EHEntry); |