]> granicus.if.org Git - clang/commitdiff
Don't emit exceptional stackrestore cleanups around inalloca functions
authorReid Kleckner <rnk@google.com>
Thu, 8 Oct 2015 00:17:45 +0000 (00:17 +0000)
committerReid Kleckner <rnk@google.com>
Thu, 8 Oct 2015 00:17:45 +0000 (00:17 +0000)
The backend restores the stack pointer after recovering from an
exception.  This is similar to r245879, but it doesn't try to use the
normal cleanup mechanism, so hopefully it won't cause the same breakage.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249640 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
lib/CodeGen/CGCall.h
test/CodeGenCXX/microsoft-abi-arg-order.cpp
test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp

index f4cd314550bc7e73066bd8e55ca2941b412a6d93..82420f12e7982a25d820a294b0b6eb88a0b9d9ad 100644 (file)
@@ -2752,25 +2752,12 @@ void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
   // Save the stack.
   llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave);
   StackBase = CGF.Builder.CreateCall(F, {}, "inalloca.save");
-
-  // Control gets really tied up in landing pads, so we have to spill the
-  // stacksave to an alloca to avoid violating SSA form.
-  // TODO: This is dead if we never emit the cleanup.  We should create the
-  // alloca and store lazily on the first cleanup emission.
-  StackBaseMem = CGF.CreateTempAlloca(CGF.Int8PtrTy, CGF.getPointerAlign(),
-                                      "inalloca.spmem");
-  CGF.Builder.CreateStore(StackBase, StackBaseMem);
-  CGF.pushStackRestore(EHCleanup, StackBaseMem);
-  StackCleanup = CGF.EHStack.getInnermostEHScope();
-  assert(StackCleanup.isValid());
 }
 
 void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const {
   if (StackBase) {
-    CGF.DeactivateCleanupBlock(StackCleanup, StackBase);
+    // Restore the stack after the call.
     llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
-    // We could load StackBase from StackBaseMem, but in the non-exceptional
-    // case we can skip it.
     CGF.Builder.CreateCall(F, StackBase);
   }
 }
index 1b75c153661ef14751acd342d030c5adae217984..2ebd09b9eb57c4db172c70515d3f3966d4513a01 100644 (file)
@@ -56,7 +56,7 @@ namespace CodeGen {
   class CallArgList :
     public SmallVector<CallArg, 16> {
   public:
-    CallArgList() : StackBase(nullptr), StackBaseMem(Address::invalid()) {}
+    CallArgList() : StackBase(nullptr) {}
 
     struct Writeback {
       /// The original argument.  Note that the argument l-value
@@ -134,9 +134,6 @@ namespace CodeGen {
     /// The stacksave call.  It dominates all of the argument evaluation.
     llvm::CallInst *StackBase;
 
-    /// The alloca holding the stackbase.  We need it to maintain SSA form.
-    Address StackBaseMem;
-
     /// The iterator pointing to the stack restore cleanup.  We manually run and
     /// deactivate this cleanup after the call in the unexceptional case because
     /// it doesn't run in the normal order.
index cbef1045080e5318b3fcff572543de33f381373d..a4fdb8272ad4f3e845da54718dd758feea964332 100644 (file)
@@ -42,12 +42,12 @@ void call_foo() {
 // X86: call i8* @llvm.stacksave()
 // X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
 // X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 2
-// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
+// X86: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
 // X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
 // X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
 // X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
 // X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
-// X86: invoke void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// X86: call void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
 // X86: call void @llvm.stackrestore
 // X86: ret void
 //
index 686b2b0994c5e153d564be3c005319f3a74a71ca..c3f757a3bce97aef9f8d3e7c0daadb1eee66bfdc 100644 (file)
@@ -17,18 +17,17 @@ void HasEHCleanup() {
 // WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
 // WIN32:   %[[base:.*]] = call i8* @llvm.stacksave()
 //    If this call throws, we have to restore the stack.
-// WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
 //    If this call throws, we have to cleanup the first temporary.
 // WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
 //    If this call throws, we have to cleanup the stacksave.
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
-// WIN32:   call void @llvm.stackrestore(i8* %[[base]])
+// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32:   call void @llvm.stackrestore
 // WIN32:   ret void
 //
 //    There should be one dtor call for unwinding from the second getA.
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32-NOT: @"\01??1A@@QAE@XZ"
-// WIN32:   call void @llvm.stackrestore
 // WIN32: }
 
 void TakeRef(const A &a);
@@ -41,7 +40,7 @@ int HasDeactivatedCleanups() {
 // WIN32:   call i8* @llvm.stacksave()
 // WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
 // WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
 //
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
@@ -54,10 +53,9 @@ int HasDeactivatedCleanups() {
 // WIN32:   store i1 false, i1* %[[isactive]]
 //
 // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
-// WIN32:   call void @llvm.stackrestore
 //        Destroy the two const ref temporaries.
 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32:   ret i32
 //
 //        Conditionally destroy arg1.
@@ -76,18 +74,18 @@ int HasConditionalCleanup(bool cond) {
 // WIN32:   store i1 false
 // WIN32:   br i1
 // WIN32:   call i8* @llvm.stacksave()
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
 // WIN32:   store i1 true
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
-// WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+//
 // WIN32:   call void @llvm.stackrestore
 //
 // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
 //
 //        Only one dtor in the invoke for arg1
-// 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:   call void @llvm.stackrestore
 // WIN32: }
 
 // Now test both.
@@ -105,7 +103,7 @@ int HasConditionalDeactivatedCleanups(bool cond) {
 // WIN32:   store i1 false
 // WIN32:   br i1
 //        True condition.
-// WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
 // WIN32:   store i1 true
 // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
 // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
@@ -121,7 +119,7 @@ int HasConditionalDeactivatedCleanups(bool cond) {
 // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
 //        Two normal cleanups for TakeRef args.
 // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// WIN32:   invoke 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.