]> granicus.if.org Git - clang/commitdiff
[SEH] Pass the frame pointer from SEH finally to finally functions
authorSanjin Sijaric <ssijaric@codeaurora.org>
Wed, 16 Jan 2019 07:39:44 +0000 (07:39 +0000)
committerSanjin Sijaric <ssijaric@codeaurora.org>
Wed, 16 Jan 2019 07:39:44 +0000 (07:39 +0000)
Pass the frame pointer that the first finally block receives onto the nested
finally block, instead of generating it using localaddr.

Differential Revision: https://reviews.llvm.org/D56463

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

lib/CodeGen/CGException.cpp
test/CodeGen/exceptions-seh-nested-finally.c [new file with mode: 0644]

index dd4298cc57f33b67635ce2d007c4cdab7d70a2ff..5756e13d2623e16f1c03be5cc716a94ee98aa91c 100644 (file)
@@ -1627,8 +1627,16 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
 
     // Compute the two argument values.
     QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
-    llvm::Value *LocalAddrFn = CGM.getIntrinsic(llvm::Intrinsic::localaddress);
-    llvm::Value *FP = CGF.Builder.CreateCall(LocalAddrFn);
+    llvm::Value *FP = nullptr;
+    // If CFG.IsOutlinedSEHHelper is true, then we are within a finally block.
+    if (CGF.IsOutlinedSEHHelper) {
+      FP = &CGF.CurFn->arg_begin()[1];
+    } else {
+      llvm::Value *LocalAddrFn =
+          CGM.getIntrinsic(llvm::Intrinsic::localaddress);
+      FP = CGF.Builder.CreateCall(LocalAddrFn);
+    }
+
     llvm::Value *IsForEH =
         llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
     Args.add(RValue::get(IsForEH), ArgTys[0]);
diff --git a/test/CodeGen/exceptions-seh-nested-finally.c b/test/CodeGen/exceptions-seh-nested-finally.c
new file mode 100644 (file)
index 0000000..7385d18
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN:         | FileCheck %s
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
+// RUN:         | FileCheck %s
+// RUN: %clang_cc1 %s -triple aarch64-windows -fms-extensions -emit-llvm -o - \
+// RUN:         | FileCheck %s
+
+// Check that the first finally block passes the enclosing function's frame
+// pointer to the second finally block, instead of generating it via localaddr.
+
+// CHECK-LABEL: define internal void @"?fin$0@0@main@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
+// CHECK: call void @"?fin$1@0@main@@"({{i8( zeroext)?}} 0, i8* %frame_pointer)
+int
+main() {
+  int Check = 0;
+  __try {
+    Check = 3;
+  } __finally {
+    __try {
+      Check += 2;
+    } __finally {
+      Check += 4;
+    }
+  }
+  return Check;
+}