forked from OSchip/llvm-project
[SEH] Use llvm.x86.seh.recoverfp for SEH filters on x64 as well as 32bit
llvm-svn: 255710
This commit is contained in:
parent
8f3118f449
commit
cf2626600c
|
@ -1548,27 +1548,32 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
|
|||
return;
|
||||
}
|
||||
|
||||
llvm::Value *EntryEBP = nullptr;
|
||||
llvm::Value *ParentFP;
|
||||
llvm::Value *EntryFP = nullptr;
|
||||
CGBuilderTy Builder(CGM, AllocaInsertPt);
|
||||
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(CGM, AllocaInsertPt);
|
||||
EntryEBP = Builder.CreateCall(
|
||||
// recover that with llvm.frameaddress(1).
|
||||
EntryFP = Builder.CreateCall(
|
||||
CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)});
|
||||
llvm::Function *RecoverFPIntrin =
|
||||
CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
|
||||
llvm::Constant *ParentI8Fn =
|
||||
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
|
||||
ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP});
|
||||
} else {
|
||||
// Otherwise, for x64 and 32-bit finally functions, the parent FP is the
|
||||
// second parameter.
|
||||
auto AI = CurFn->arg_begin();
|
||||
++AI;
|
||||
ParentFP = &*AI;
|
||||
EntryFP = &*AI;
|
||||
}
|
||||
|
||||
llvm::Value *ParentFP;
|
||||
if (IsFilter) {
|
||||
// Given whatever FP the runtime provided us in EntryFP, recover the true
|
||||
// frame pointer of the parent function. We only need to do this in filters,
|
||||
// since finally funclets recover the parent FP for us.
|
||||
llvm::Function *RecoverFPIntrin =
|
||||
CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
|
||||
llvm::Constant *ParentI8Fn =
|
||||
llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
|
||||
ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP});
|
||||
}
|
||||
|
||||
// Create llvm.localrecover calls for all captures.
|
||||
|
@ -1602,7 +1607,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
|
|||
}
|
||||
|
||||
if (IsFilter)
|
||||
EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP);
|
||||
EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryFP);
|
||||
}
|
||||
|
||||
/// Arrange a function prototype that can be called by Windows exception
|
||||
|
@ -1718,7 +1723,7 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
|
|||
|
||||
void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
|
||||
llvm::Value *ParentFP,
|
||||
llvm::Value *EntryEBP) {
|
||||
llvm::Value *EntryFP) {
|
||||
// Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the
|
||||
// __exception_info intrinsic.
|
||||
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
|
||||
|
@ -1731,7 +1736,7 @@ void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
|
|||
// exception registration object. It contains 6 32-bit fields, and the info
|
||||
// pointer is stored in the second field. So, GEP 20 bytes backwards and
|
||||
// load the pointer.
|
||||
SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20);
|
||||
SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryFP, -20);
|
||||
SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo());
|
||||
SEHInfo = Builder.CreateAlignedLoad(Int8PtrTy, SEHInfo, getPointerAlign());
|
||||
SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal(
|
||||
|
|
|
@ -89,7 +89,8 @@ int filter_expr_capture(void) {
|
|||
// CHECK: ret i32 %[[rv]]
|
||||
|
||||
// X64-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
|
||||
// X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
|
||||
// X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
|
||||
// X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
|
||||
//
|
||||
// X86-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"()
|
||||
// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
|
||||
|
|
|
@ -21,9 +21,10 @@ extern "C" void test_freefunc(int p1) {
|
|||
// CHECK: invoke void @might_crash()
|
||||
|
||||
// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
|
||||
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 0)
|
||||
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
|
||||
// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
|
||||
// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
|
||||
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 1)
|
||||
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
|
||||
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
|
||||
// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"\01?s1@?1??test_freefunc@@9@4HA", align 4
|
||||
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
|
||||
|
@ -50,7 +51,8 @@ void S::test_method() {
|
|||
// CHECK: invoke void @might_crash()
|
||||
|
||||
// CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
|
||||
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer, i32 0)
|
||||
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
|
||||
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
|
||||
// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
|
||||
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
|
||||
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
|
||||
|
@ -74,7 +76,8 @@ void test_lambda() {
|
|||
// CHECK: invoke void @might_crash()
|
||||
|
||||
// CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R<lambda_0>@?test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
|
||||
// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %frame_pointer, i32 0)
|
||||
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %frame_pointer)
|
||||
// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %[[fp]], i32 0)
|
||||
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
|
||||
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
|
||||
// CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]])
|
||||
|
|
Loading…
Reference in New Issue