[PATCH] D61892: [RFC] [AArch64] Back up and restore X18 in the prologue/epilogue for Windows calling convention on non-Windows OSes
Martin Storsjö via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue May 14 06:04:55 PDT 2019
mstorsjo created this revision.
mstorsjo added reviewers: rnk, t.p.northover.
Herald added subscribers: kristof.beyls, javed.absar.
Herald added a project: LLVM.
This makes sure that X18 isn't clobbered after returns from Wine functions, but doesn't maintain X18 during such functions (e.g. during callbacks).
Posting this to concretely evaluate different PoCs for handling this matter.
Repository:
rL LLVM
https://reviews.llvm.org/D61892
Files:
lib/Target/AArch64/AArch64CallingConvention.td
lib/Target/AArch64/AArch64FrameLowering.cpp
lib/Target/AArch64/AArch64ISelLowering.cpp
lib/Target/AArch64/AArch64RegisterInfo.cpp
test/CodeGen/AArch64/win64cc-backup-x18.ll
Index: test/CodeGen/AArch64/win64cc-backup-x18.ll
===================================================================
--- /dev/null
+++ test/CodeGen/AArch64/win64cc-backup-x18.ll
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s
+
+declare dso_local void @other()
+
+define dso_local win64cc void @func() #0 {
+; CHECK-LABEL: func:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: stp x18, x30, [sp, #-16]! // 16-byte Folded Spill
+; CHECK-NEXT: bl other
+; CHECK-NEXT: ldp x18, x30, [sp], #16 // 16-byte Folded Reload
+; CHECK-NEXT: ret
+entry:
+ tail call void @other()
+ ret void
+}
+
+attributes #0 = { nounwind "target-features"="+reserve-x18" }
Index: lib/Target/AArch64/AArch64RegisterInfo.cpp
===================================================================
--- lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -63,6 +63,11 @@
return CSR_AArch64_AAPCS_SwiftError_SaveList;
if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost)
return CSR_AArch64_RT_MostRegs_SaveList;
+ else if (MF->getFunction().getCallingConv() == CallingConv::Win64 &&
+ MF->getSubtarget<AArch64Subtarget>().isXRegisterReserved(18))
+ // This is for OSes other than Windows; Windows is a separate case further
+ // above.
+ return CSR_AArch64_AAPCS_X18_SaveList;
else
return CSR_AArch64_AAPCS_SaveList;
}
Index: lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- lib/Target/AArch64/AArch64ISelLowering.cpp
+++ lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3418,6 +3418,13 @@
CallingConv::ID CallerCC = CallerF.getCallingConv();
bool CCMatch = CallerCC == CalleeCC;
+ // When using the Windows calling convention on a non-windows OS, we want
+ // to back up and restore X18 in such functions; we can't do a tail call
+ // from those functions.
+ if (CallerCC == CallingConv::Win64 && !Subtarget->isTargetWindows() &&
+ Subtarget->isXRegisterReserved(18))
+ return false;
+
// Byval parameters hand the function a pointer directly into the stack area
// we want to reuse during a tail call. Working around this *is* possible (see
// X86) but less efficient and uglier in LowerCall.
Index: lib/Target/AArch64/AArch64FrameLowering.cpp
===================================================================
--- lib/Target/AArch64/AArch64FrameLowering.cpp
+++ lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -1998,6 +1998,7 @@
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
const AArch64RegisterInfo *RegInfo = static_cast<const AArch64RegisterInfo *>(
MF.getSubtarget().getRegisterInfo());
+ const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
unsigned UnspilledCSGPR = AArch64::NoRegister;
unsigned UnspilledCSGPRPaired = AArch64::NoRegister;
@@ -2059,6 +2060,14 @@
SavedRegs.set(AArch64::LR);
}
+ if (MF.getFunction().getCallingConv() == CallingConv::Win64 &&
+ !Subtarget.isTargetWindows() && Subtarget.isXRegisterReserved(18)) {
+ // 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.
+ SavedRegs.set(AArch64::X18);
+ }
+
LLVM_DEBUG(dbgs() << "*** determineCalleeSaves\nUsed CSRs:";
for (unsigned Reg
: SavedRegs.set_bits()) dbgs()
Index: lib/Target/AArch64/AArch64CallingConvention.td
===================================================================
--- lib/Target/AArch64/AArch64CallingConvention.td
+++ lib/Target/AArch64/AArch64CallingConvention.td
@@ -311,6 +311,10 @@
D8, D9, D10, D11,
D12, D13, D14, D15)>;
+// A variant for treating X18 as callee saved, when interfacing with
+// code that needs X18 to be preserved.
+def CSR_AArch64_AAPCS_X18 : CalleeSavedRegs<(add CSR_AArch64_AAPCS, X18)>;
+
// Win64 has unwinding codes for an (FP,LR) pair, save_fplr and save_fplr_x.
// We put FP before LR, so that frame lowering logic generates (FP,LR) pairs,
// and not (LR,FP) pairs.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D61892.199417.patch
Type: text/x-patch
Size: 4421 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190514/7a11abd7/attachment.bin>
More information about the llvm-commits
mailing list