diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 48 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 30 |
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; } |