forked from OSchip/llvm-project
[SEH] [ARM64] Retrieve the frame pointer from SEH funclets
The Windows ARM64 runtime passes the establisher frame to funclets as the first argument. llvm-svn: 351404
This commit is contained in:
parent
82ceec5d01
commit
685565ae9a
|
@ -923,6 +923,17 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
|
|||
if (NeedsWinCFI)
|
||||
BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
|
||||
// SEH funclets are passed the frame pointer in X1. If the parent
|
||||
// function uses the base register, then the base register is used
|
||||
// directly, and is not retrieved from X1.
|
||||
if (F.hasPersonalityFn()) {
|
||||
EHPersonality Per = classifyEHPersonality(F.getPersonalityFn());
|
||||
if (isAsynchronousEHPersonality(Per))
|
||||
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), AArch64::FP)
|
||||
.addReg(AArch64::X1).setMIFlag(MachineInstr::FrameSetup);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
; RUN: llc -o - %s -mtriple=aarch64-windows | FileCheck %s
|
||||
|
||||
; Windows runtime passes the establisher frame as the second argument to the
|
||||
; termination handler. Check that we copy it into fp.
|
||||
|
||||
; CHECK: ?dtor$3@?0?main@4HA":
|
||||
; CHECK: .seh_proc "?dtor$3@?0?main@4HA"
|
||||
; CHECK: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
|
||||
; CHECK-NEXT: mov x29, x1
|
||||
|
||||
target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
|
||||
target triple = "aarch64-unknown-windows-msvc19.15.26732"
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @main() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
%Counter = alloca i32, align 4
|
||||
%__exception_code = alloca i32, align 4
|
||||
call void (...) @llvm.localescape(i32* %Counter)
|
||||
store i32 0, i32* %retval, align 4
|
||||
store i32 0, i32* %Counter, align 4
|
||||
%call = invoke i32 bitcast (i32 (...)* @RaiseStatus to i32 (i32)*)(i32 -1073741675) #3
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
%0 = call i8* @llvm.localaddress()
|
||||
invoke void @"?fin$0@0@main@@"(i8 0, i8* %0) #3
|
||||
to label %invoke.cont1 unwind label %catch.dispatch
|
||||
|
||||
invoke.cont1: ; preds = %invoke.cont
|
||||
br label %__try.cont
|
||||
|
||||
ehcleanup: ; preds = %entry
|
||||
%1 = cleanuppad within none []
|
||||
%2 = call i8* @llvm.localaddress()
|
||||
invoke void @"?fin$0@0@main@@"(i8 1, i8* %2) #3 [ "funclet"(token %1) ]
|
||||
to label %invoke.cont2 unwind label %catch.dispatch
|
||||
|
||||
invoke.cont2: ; preds = %ehcleanup
|
||||
cleanupret from %1 unwind label %catch.dispatch
|
||||
|
||||
catch.dispatch: ; preds = %invoke.cont2, %ehcleanup, %invoke.cont
|
||||
%3 = catchswitch within none [label %__except] unwind to caller
|
||||
|
||||
__except: ; preds = %catch.dispatch
|
||||
%4 = catchpad within %3 [i8* null]
|
||||
catchret from %4 to label %__except3
|
||||
|
||||
__except3: ; preds = %__except
|
||||
%5 = call i32 @llvm.eh.exceptioncode(token %4)
|
||||
store i32 %5, i32* %__exception_code, align 4
|
||||
%6 = load i32, i32* %Counter, align 4
|
||||
%add = add nsw i32 %6, 5
|
||||
store i32 %add, i32* %Counter, align 4
|
||||
br label %__try.cont
|
||||
|
||||
__try.cont: ; preds = %__except3, %invoke.cont1
|
||||
%7 = load i32, i32* %retval, align 4
|
||||
ret i32 %7
|
||||
}
|
||||
|
||||
define internal void @"?fin$0@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) {
|
||||
entry:
|
||||
%frame_pointer.addr = alloca i8*, align 8
|
||||
%abnormal_termination.addr = alloca i8, align 1
|
||||
%0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
|
||||
%Counter = bitcast i8* %0 to i32*
|
||||
store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
|
||||
store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
|
||||
store i32 3, i32* %Counter, align 4
|
||||
call void @"?fin$1@0@main@@"(i8 0, i8* %frame_pointer)
|
||||
%1 = load i32, i32* %Counter, align 4
|
||||
%add = add nsw i32 %1, 2
|
||||
store i32 %add, i32* %Counter, align 4
|
||||
%call = call i32 bitcast (i32 (...)* @RaiseStatus to i32 (i32)*)(i32 -1073741675)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i8* @llvm.localrecover(i8*, i8*, i32) #1
|
||||
|
||||
define internal void @"?fin$1@0@main@@"(i8 %abnormal_termination, i8* %frame_pointer) {
|
||||
entry:
|
||||
%frame_pointer.addr = alloca i8*, align 8
|
||||
%abnormal_termination.addr = alloca i8, align 1
|
||||
%0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %frame_pointer, i32 0)
|
||||
%Counter = bitcast i8* %0 to i32*
|
||||
store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
|
||||
store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
|
||||
%1 = load i32, i32* %Counter, align 4
|
||||
%cmp = icmp eq i32 %1, 3
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%2 = load i32, i32* %Counter, align 4
|
||||
%add = add nsw i32 %2, 1
|
||||
store i32 %add, i32* %Counter, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
declare dso_local i32 @RaiseStatus(...)
|
||||
|
||||
declare dso_local i32 @__C_specific_handler(...)
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i8* @llvm.localaddress() #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @llvm.eh.exceptioncode(token) #1
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @llvm.localescape(...) #2
|
||||
|
||||
attributes #0 = { noinline nounwind optnone uwtable }
|
||||
attributes #1 = { nounwind readnone }
|
||||
attributes #2 = { nounwind }
|
||||
attributes #3 = { noinline }
|
Loading…
Reference in New Issue