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 | 55391524043b55115dbec692fd898afb676a3cb4 (patch) | |
tree | de9da3fe2f43a1d380bebf0d765a74a4b893081f /clang/lib/CodeGen/CGCleanup.cpp | |
parent | 5beec213e24139e99ebbf1b35ca9731849f8843a (diff) | |
download | bcm5719-llvm-55391524043b55115dbec692fd898afb676a3cb4.tar.gz bcm5719-llvm-55391524043b55115dbec692fd898afb676a3cb4.zip |
[WinEH] Push cleanupendpad scopes around exceptional cleanups
We were only doing this for SEH as a special case. Generalize it to all
cleanups.
llvm-svn: 249748
Diffstat (limited to 'clang/lib/CodeGen/CGCleanup.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index 5796320894b..8bad58d78b7 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/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); |