summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-10-08 21:14:56 +0000
committerReid Kleckner <rnk@google.com>2015-10-08 21:14:56 +0000
commit55391524043b55115dbec692fd898afb676a3cb4 (patch)
treede9da3fe2f43a1d380bebf0d765a74a4b893081f /clang/lib/CodeGen
parent5beec213e24139e99ebbf1b35ca9731849f8843a (diff)
downloadbcm5719-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')
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp48
-rw-r--r--clang/lib/CodeGen/CGException.cpp30
2 files changed, 37 insertions, 41 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);
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 16f6e83647b..2c1ede4b76d 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1410,10 +1410,8 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
namespace {
struct PerformSEHFinally final : EHScopeStack::Cleanup {
llvm::Function *OutlinedFinally;
- EHScopeStack::stable_iterator EnclosingScope;
- PerformSEHFinally(llvm::Function *OutlinedFinally,
- EHScopeStack::stable_iterator EnclosingScope)
- : OutlinedFinally(OutlinedFinally), EnclosingScope(EnclosingScope) {}
+ PerformSEHFinally(llvm::Function *OutlinedFinally)
+ : OutlinedFinally(OutlinedFinally) {}
void Emit(CodeGenFunction &CGF, Flags F) override {
ASTContext &Context = CGF.getContext();
@@ -1438,28 +1436,7 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
CGM.getTypes().arrangeFreeFunctionCall(Args, FPT,
/*chainCall=*/false);
- // If this is the normal cleanup, just emit the call.
- if (!F.isForEHCleanup()) {
- CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
- return;
- }
-
- // Build a cleanupendpad to unwind through.
- llvm::BasicBlock *CleanupBB = CGF.Builder.GetInsertBlock();
- llvm::BasicBlock *CleanupEndBB = CGF.createBasicBlock("ehcleanup.end");
- llvm::Instruction *PadInst = CleanupBB->getFirstNonPHI();
- auto *CPI = cast<llvm::CleanupPadInst>(PadInst);
- CGBuilderTy(CGF, CleanupEndBB)
- .CreateCleanupEndPad(CPI, CGF.getEHDispatchBlock(EnclosingScope));
-
- // Push and pop the cleanupendpad around the call.
- CGF.EHStack.pushPadEnd(CleanupEndBB);
CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
- CGF.EHStack.popPadEnd();
-
- // Insert the catchendpad block here.
- CGF.CurFn->getBasicBlockList().insertAfter(CGF.Builder.GetInsertBlock(),
- CleanupEndBB);
}
};
} // end anonymous namespace
@@ -1815,8 +1792,7 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
// Push a cleanup for __finally blocks.
- EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc,
- EHStack.getInnermostEHScope());
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
return;
}
OpenPOWER on IntegriCloud