r249748 - [WinEH] Push cleanupendpad scopes around exceptional cleanups

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 8 14:14:56 PDT 2015


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 at Z"([[argmem_ty]]* inalloca %[[argmem]])
 //        Destroy the two const ref temporaries.
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE at XZ"
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE at XZ"
 // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE at 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 at XZ"(%struct.A* %[[arg1]])
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE at 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 at XZ"
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE at XZ"
 // WIN32-NOT:   invoke x86_thiscallcc void @"\01??1A@@QAE at 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 at XZ"
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE at 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 at crash_on_partial_destroy@@UAE at XZ"
+// WIN32:      call x86_thiscallcc void @"\01??1B at crash_on_partial_destroy@@UAE at 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 at dont_call_terminate@@QAE at XZ"({{.*}})
 }
+
+namespace noexcept_false_dtor {
+struct D {
+  ~D() noexcept(false);
+};
+void f() {
+  D d;
+  CouldThrow();
+}
+}
+
+// WIN32-LABEL: define void @"\01?f at noexcept_false_dtor@@YAXXZ"()
+// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// WIN32: call x86_thiscallcc void @"\01??1D at noexcept_false_dtor@@QAE at XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32: cleanuppad
+// WIN32: invoke x86_thiscallcc void @"\01??1D at noexcept_false_dtor@@QAE at XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
+// WIN32: cleanupret
+// WIN32: cleanupendpad




More information about the cfe-commits mailing list