diff options
| -rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 25 | ||||
| -rw-r--r-- | clang/test/CodeGen/exceptions-seh.c | 27 |
2 files changed, 25 insertions, 27 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index c1e7eae405f..d6913156794 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1447,15 +1447,11 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, llvm::Value *EntryEBP = nullptr; llvm::Value *ParentFP; - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - // On x64, the parent FP is passed as the second argument. - auto AI = CurFn->arg_begin(); - ++AI; - ParentFP = AI; - } else { - // The end of the EH registration is passed in as the EBP physical register. - // We can recover that with llvm.frameaddress(1), and adjust that to - // recover the parent's true frame pointer. + if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) { + // 32-bit SEH filters need to be careful about FP recovery. The end of the + // EH registration is passed in as the EBP physical register. We can + // recover that with llvm.frameaddress(1), and adjust that to recover the + // parent's true frame pointer. CGBuilderTy Builder(AllocaInsertPt); EntryEBP = Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)}); @@ -1464,11 +1460,12 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, llvm::Constant *ParentI8Fn = llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP}); - - // Inlining will break llvm.frameaddress(1), so disable it. - // FIXME: We could teach the inliner about the special meaning of - // frameaddress, framerecover, and frameescape to remove this limitation. - CurFn->addFnAttr(llvm::Attribute::NoInline); + } else { + // Otherwise, for x64 and 32-bit finally functions, the parent FP is the + // second parameter. + auto AI = CurFn->arg_begin(); + ++AI; + ParentFP = AI; } // Create llvm.framerecover calls for all captures. diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c index 772fe547ba5..3eba3a412fe 100644 --- a/clang/test/CodeGen/exceptions-seh.c +++ b/clang/test/CodeGen/exceptions-seh.c @@ -168,21 +168,20 @@ int nested_try(void) { // CHECK: load i32, i32* // CHECK: icmp eq i32 %{{.*}}, 123 -static unsigned g = 0; -void basic_finally(void) { - ++g; +int basic_finally(int g) { __try { j(); } __finally { - --g; + ++g; } + return g; } -// CHECK-LABEL: define void @basic_finally() +// CHECK-LABEL: define i32 @basic_finally(i32 %g) // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) -// CHECK: load i32, i32* @g -// CHECK: add i32 %{{.*}}, 1 -// CHECK: store i32 %{{.*}}, i32* @g +// CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4 +// CHECK: call void (...) @llvm.frameescape(i32* %[[g_addr]]) +// CHECK: store i32 %g, i32* %[[g_addr]] // // CHECK: invoke void @j() // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] @@ -190,7 +189,8 @@ void basic_finally(void) { // CHECK: [[cont]] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) -// CHECK: ret void +// CHECK: load i32, i32* %[[g_addr]], align 4 +// CHECK: ret i32 // // CHECK: [[lpad]] // CHECK: landingpad { i8*, i32 } @@ -199,10 +199,11 @@ void basic_finally(void) { // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) // CHECK: resume -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}}) -// CHECK: load i32, i32* @g, align 4 -// CHECK: add i32 %{{.*}}, -1 -// CHECK: store i32 %{{.*}}, i32* @g, align 4 +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer) +// CHECK: call i8* @llvm.framerecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0) +// CHECK: load i32, i32* %{{.*}}, align 4 +// CHECK: add nsw i32 %{{.*}}, 1 +// CHECK: store i32 %{{.*}}, i32* %{{.*}}, align 4 // CHECK: ret void int returns_int(void); |

