[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