summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjin Sijaric <ssijaric@codeaurora.org>2019-01-16 07:39:44 +0000
committerSanjin Sijaric <ssijaric@codeaurora.org>2019-01-16 07:39:44 +0000
commit6177eda8577856233853ed2c036617e320c48126 (patch)
treeb493ec005213ba078fa287edc42ea5d4fb6bed61
parentfb1f12a1e98dbd88abc0650c644f7202d6149bd1 (diff)
[SEH] Pass the frame pointer from SEH finally to finally functionslinaro-local/ci/tcwg_kernel/llvm-master-arm-stable-allyesconfig
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
-rw-r--r--clang/lib/CodeGen/CGException.cpp12
-rw-r--r--clang/test/CodeGen/exceptions-seh-nested-finally.c26
2 files changed, 36 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index dd4298cc57f..5756e13d262 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -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/clang/test/CodeGen/exceptions-seh-nested-finally.c b/clang/test/CodeGen/exceptions-seh-nested-finally.c
new file mode 100644
index 00000000000..7385d18f0cd
--- /dev/null
+++ b/clang/test/CodeGen/exceptions-seh-nested-finally.c
@@ -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;
+}