From: Reid Kleckner Date: Wed, 1 Jul 2015 22:33:45 +0000 (+0000) Subject: [SEH] Update EmitCapturedLocals to match r241187 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3cc214289fdc7befabf9bbb3b82cef2356bbf704;p=clang [SEH] Update EmitCapturedLocals to match r241187 It was still using frameaddress(1) to get the parent FP, even though it had the value it wanted as a parameter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241199 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index c1e7eae405..d691315679 100644 --- a/lib/CodeGen/CGException.cpp +++ b/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/test/CodeGen/exceptions-seh.c b/test/CodeGen/exceptions-seh.c index 772fe547ba..3eba3a412f 100644 --- a/test/CodeGen/exceptions-seh.c +++ b/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);