diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -836,6 +836,10 @@ return MF.getSubtarget().isTargetDarwin(); } +static bool isTargetWindows(const MachineFunction &MF) { + return MF.getSubtarget().isTargetWindows(); +} + // Convenience function to determine whether I is an SVE callee save. bool IsSVECalleeSave(MachineBasicBlock::iterator I) { switch (I->getOpcode()) { @@ -1870,6 +1874,8 @@ // TODO: LR can be paired with any register. We don't support this yet in // the MCLayer. We need to add support for the save_lrpair unwind code. + if (Reg2 == AArch64::FP) + return true; if (!NeedsWinCFI) return false; if (Reg2 == Reg1 + 1) @@ -1882,9 +1888,9 @@ /// LR and FP need to be allocated together when the frame needs to save /// the frame-record. This means any other register pairing with LR is invalid. static bool invalidateRegisterPairing(unsigned Reg1, unsigned Reg2, - bool NeedsWinCFI, bool NeedsFrameRecord) { - if (NeedsWinCFI) - return invalidateWindowsRegisterPairing(Reg1, Reg2, true); + bool UsesWinAAPCS, bool NeedsWinCFI, bool NeedsFrameRecord) { + if (UsesWinAAPCS) + return invalidateWindowsRegisterPairing(Reg1, Reg2, NeedsWinCFI); // If we need to store the frame record, don't pair any register // with LR other than FP. @@ -1934,6 +1940,7 @@ if (CSI.empty()) return; + bool IsWindows = isTargetWindows(MF); bool NeedsWinCFI = needsWinCFI(MF); AArch64FunctionInfo *AFI = MF.getInfo(); MachineFrameInfo &MFI = MF.getFrameInfo(); @@ -1976,7 +1983,7 @@ switch (RPI.Type) { case RegPairInfo::GPR: if (AArch64::GPR64RegClass.contains(NextReg) && - !invalidateRegisterPairing(RPI.Reg1, NextReg, NeedsWinCFI, + !invalidateRegisterPairing(RPI.Reg1, NextReg, IsWindows, NeedsWinCFI, NeedsFrameRecord)) RPI.Reg2 = NextReg; break; @@ -2018,6 +2025,11 @@ RPI.Reg1 == AArch64::LR) && "FrameRecord must be allocated together with LR"); + // Windows AAPCS has FP and LR reversed. + assert((!RPI.isPaired() || !NeedsFrameRecord || RPI.Reg1 != AArch64::FP || + RPI.Reg2 == AArch64::LR) && + "FrameRecord must be allocated together with LR"); + // MachO's compact unwind format relies on all registers being stored in // adjacent register pairs. assert((!produceCompactUnwindFrame(MF) || diff --git a/llvm/test/CodeGen/AArch64/win64-no-uwtable.ll b/llvm/test/CodeGen/AArch64/win64-no-uwtable.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/win64-no-uwtable.ll @@ -0,0 +1,35 @@ +; RUN: llc -mtriple=arm64-windows -o - %s | FileCheck %s + +declare void @f() +declare void @g() + +; Function Attrs: nounwind +define dso_local void @SEHfilter() nounwind "frame-pointer"="all" { +; CHECK-LABEL: @SEHfilter +; CHECK: %bb.0: +; CHECK-NEXT: stp x30, x29, [sp, #-32]! +; CHECK-NEXT: str x19, [sp, #16] +; CHECK-NEXT: ldr w19, [x8] +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: bl g +; CHECK-NEXT: cbz w19, .LBB0_2 +; CHECK-NEXT: ; %bb.1: +; CHECK-NEXT: ldr x19, [sp, #16] +; CHECK-NEXT: ldp x30, x29, [sp], #32 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_2: ; %if.end.i +; CHECK-NEXT: bl f +; CHECK-NEXT: brk #0x1 + %1 = load i32, i32* undef, align 4 + tail call void @g() + %tobool.i = icmp eq i32 %1, 0 + br i1 %tobool.i, label %if.end.i, label %exit + +if.end.i: + call void @f() + unreachable + +exit: + ret void +} +