From 71aecbb75c7d8b603b1882afa7301e54f3091587 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Wed, 27 Jul 2022 23:54:56 +0300 Subject: [PATCH] [AArch64] Treat x18 as callee-saved in functions with Windows calling convention on Darwin rGcf97e0ec42b8 makes $x18 to be treated as callee-saved in functions with Windows calling convention on non-Windows OSes. Here we mark $x18 as callee-saved for functions with Windows calling convention on Darwin, as well as on other non-Windows platforms, in order to prevent some miscompilations (like miscompilation of win64cc-darwin-backup-x18.ll). Since getCalleeSavedRegs doesn't return x18 in list of callee-saved registers, assignCalleeSavedSpillSlots and determineCalleeSaves consider different sets of registers as callee-saved. It causes an error: ``` Assertion failed: ((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) && "Invalid size calculated for callee saves"), function getCalleeSavedStackSize, file AArch64MachineFunctionInfo.h, line 292. ``` Differential Revision: https://reviews.llvm.org/D130676 --- .../lib/Target/AArch64/AArch64CallingConvention.td | 9 +++++++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp | 8 +++--- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp | 2 ++ .../CodeGen/AArch64/win64cc-darwin-backup-x18.ll | 31 ++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/win64cc-darwin-backup-x18.ll diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td index c0da242..b6e2929 100644 --- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td +++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td @@ -444,6 +444,15 @@ def CSR_Darwin_AArch64_AAPCS : CalleeSavedRegs<(add LR, FP, X19, X20, X21, X22, def CSR_Darwin_AArch64_AAVPCS : CalleeSavedRegs<(add LR, FP, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, (sequence "Q%u", 8, 23))>; + +// For Windows calling convention on a non-windows OS, where X18 is treated +// as reserved, back up X18 when entering non-windows code (marked with the +// Windows calling convention) and restore when returning regardless of +// whether the individual function uses it - it might call other functions +// that clobber it. +def CSR_Darwin_AArch64_AAPCS_Win64 + : CalleeSavedRegs<(add CSR_Darwin_AArch64_AAPCS, X18)>; + def CSR_Darwin_AArch64_AAPCS_ThisReturn : CalleeSavedRegs<(add CSR_Darwin_AArch64_AAPCS, X0)>; diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 78babdf..c123030 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -2522,8 +2522,8 @@ static void computeCalleeSaveRegisterPairs( (void)CC; // MachO's compact unwind format relies on all registers being stored in // pairs. - assert((!produceCompactUnwindFrame(MF) || - CC == CallingConv::PreserveMost || CC == CallingConv::CXX_FAST_TLS || + assert((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || + CC == CallingConv::CXX_FAST_TLS || CC == CallingConv::Win64 || (Count & 1) == 0) && "Odd number of callee-saved regs to spill!"); int ByteOffset = AFI->getCalleeSavedStackSize(); @@ -2608,8 +2608,8 @@ static void computeCalleeSaveRegisterPairs( // MachO's compact unwind format relies on all registers being stored in // adjacent register pairs. - assert((!produceCompactUnwindFrame(MF) || - CC == CallingConv::PreserveMost || CC == CallingConv::CXX_FAST_TLS || + assert((!produceCompactUnwindFrame(MF) || CC == CallingConv::PreserveMost || + CC == CallingConv::CXX_FAST_TLS || CC == CallingConv::Win64 || (RPI.isPaired() && ((RPI.Reg1 == AArch64::LR && RPI.Reg2 == AArch64::FP) || RPI.Reg1 + 1 == RPI.Reg2))) && diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index f7c06b9..caabaee 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -135,6 +135,8 @@ AArch64RegisterInfo::getDarwinCalleeSavedRegs(const MachineFunction *MF) const { return CSR_Darwin_AArch64_AAPCS_SwiftTail_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost) return CSR_Darwin_AArch64_RT_MostRegs_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::Win64) + return CSR_Darwin_AArch64_AAPCS_Win64_SaveList; return CSR_Darwin_AArch64_AAPCS_SaveList; } diff --git a/llvm/test/CodeGen/AArch64/win64cc-darwin-backup-x18.ll b/llvm/test/CodeGen/AArch64/win64cc-darwin-backup-x18.ll new file mode 100644 index 0000000..0f376f2 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/win64cc-darwin-backup-x18.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +;; Testing that x18 is backed up and restored, and that x29 (if used) still +;; points to the x29,x30 pair on the stack. + +; RUN: llc < %s -mtriple=arm64-apple-darwin | FileCheck %s +; RUN: llc < %s -mtriple=arm64-apple-darwin -mattr=+reserve-x18 | FileCheck %s + +declare dso_local void @other() + +define win64cc void @func(i32 noundef %0) #0 { +; CHECK-LABEL: func: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: str x18, [sp, #-32]! ; 8-byte Folded Spill +; CHECK-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill +; CHECK: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload +; CHECK-NEXT: ldr x18, [sp], #32 ; 8-byte Folded Reload +; CHECK-NEXT: ret +entry: + %al = alloca i32, align 4 + store i32 %0, ptr %al, align 4 + tail call void @other() + ret void +} + +define i32 @main() { + call win64cc void @func(i32 noundef 17) + ret i32 0 +} + +attributes #0 = { nounwind } -- 2.7.4