Author: rnk Date: Thu Oct 8 16:14:56 2015 New Revision: 249748 URL: http://llvm.org/viewvc/llvm-project?rev=249748&view=rev Log: [WinEH] Push cleanupendpad scopes around exceptional cleanups
We were only doing this for SEH as a special case. Generalize it to all cleanups. Modified: cfe/trunk/lib/CodeGen/CGCleanup.cpp cfe/trunk/lib/CodeGen/CGException.cpp cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Modified: cfe/trunk/lib/CodeGen/CGCleanup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.cpp?rev=249748&r1=249747&r2=249748&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGCleanup.cpp (original) +++ cfe/trunk/lib/CodeGen/CGCleanup.cpp Thu Oct 8 16:14:56 2015 @@ -521,15 +521,6 @@ static void EmitCleanup(CodeGenFunction 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 // 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(bo 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(bo 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); Modified: cfe/trunk/lib/CodeGen/CGException.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=249748&r1=249747&r2=249748&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGException.cpp (original) +++ cfe/trunk/lib/CodeGen/CGException.cpp Thu Oct 8 16:14:56 2015 @@ -1410,10 +1410,8 @@ void CodeGenFunction::EmitSEHTryStmt(con 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 : EHScope 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(co HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); // Push a cleanup for __finally blocks. - EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc, - EHStack.getInnermostEHScope()); + EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc); return; } Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp?rev=249748&r1=249747&r2=249748&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp (original) +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp Thu Oct 8 16:14:56 2015 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s struct A { A(); @@ -54,14 +54,14 @@ int HasDeactivatedCleanups() { // // WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) // Destroy the two const ref temporaries. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Conditionally destroy arg1. // WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]] // WIN32: br i1 %[[cond]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: } // Test putting the cleanups inside a conditional. @@ -118,14 +118,14 @@ int HasConditionalDeactivatedCleanups(bo // False condition. // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() // Two normal cleanups for TakeRef args. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Somewhere in the landing pad soup, we conditionally destroy arg1. // WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] // WIN32: br i1 %[[isactive]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: } namespace crash_on_partial_destroy { @@ -155,7 +155,7 @@ C::C() { foo(); } // WIN32: getelementptr i8, i8* %{{.*}}, i32 4 // WIN32-NOT: load // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* -// WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" // // WIN32-NOT: load // WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* @@ -188,3 +188,21 @@ void f() { // WIN32-NEXT: cleanuppad // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) } + +namespace noexcept_false_dtor { +struct D { + ~D() noexcept(false); +}; +void f() { + D d; + CouldThrow(); +} +} + +// WIN32-LABEL: define void @"\01?f@noexcept_false_dtor@@YAXXZ"() +// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) +// WIN32: cleanuppad +// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) +// WIN32: cleanupret +// WIN32: cleanupendpad _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits