@@ -1994,7 +1994,108 @@ bool AArch64InstructionSelector::selectVectorAshrLshr(
1994
1994
1995
1995
bool AArch64InstructionSelector::selectVaStartAAPCS (
1996
1996
MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const {
1997
- return false ;
1997
+
1998
+ if (MF.getSubtarget <AArch64Subtarget>().isCallingConvWin64 (
1999
+ MF.getFunction ().getCallingConv (), MF.getFunction ().isVarArg ()))
2000
+ return false ;
2001
+
2002
+ // The layout of the va_list struct is specified in the AArch64 Procedure Call
2003
+ // Standard, section 10.1.5.
2004
+
2005
+ const AArch64FunctionInfo *FuncInfo = MF.getInfo <AArch64FunctionInfo>();
2006
+ const unsigned PtrSize = STI.isTargetILP32 () ? 4 : 8 ;
2007
+ const auto *PtrRegClass =
2008
+ STI.isTargetILP32 () ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
2009
+
2010
+ const MCInstrDesc &MCIDAddAddr =
2011
+ TII.get (STI.isTargetILP32 () ? AArch64::ADDWri : AArch64::ADDXri);
2012
+ const MCInstrDesc &MCIDStoreAddr =
2013
+ TII.get (STI.isTargetILP32 () ? AArch64::STRWui : AArch64::STRXui);
2014
+
2015
+ /*
2016
+ * typedef struct va_list {
2017
+ * void * stack; // next stack param
2018
+ * void * gr_top; // end of GP arg reg save area
2019
+ * void * vr_top; // end of FP/SIMD arg reg save area
2020
+ * int gr_offs; // offset from gr_top to next GP register arg
2021
+ * int vr_offs; // offset from vr_top to next FP/SIMD register arg
2022
+ * } va_list;
2023
+ */
2024
+ const auto VAList = I.getOperand (0 ).getReg ();
2025
+
2026
+ // Our current offset in bytes from the va_list struct (VAList).
2027
+ unsigned OffsetBytes = 0 ;
2028
+
2029
+ // Helper function to store (FrameIndex + Imm) to VAList at offset OffsetBytes
2030
+ // and increment OffsetBytes by PtrSize.
2031
+ const auto PushAddress = [&](const int FrameIndex, const int64_t Imm) {
2032
+ const Register Top = MRI.createVirtualRegister (PtrRegClass);
2033
+ auto MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (), MCIDAddAddr)
2034
+ .addDef (Top)
2035
+ .addFrameIndex (FrameIndex)
2036
+ .addImm (Imm)
2037
+ .addImm (0 );
2038
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2039
+
2040
+ MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (), MCIDStoreAddr)
2041
+ .addUse (Top)
2042
+ .addUse (VAList)
2043
+ .addImm (OffsetBytes / PtrSize)
2044
+ .addMemOperand (MF.getMachineMemOperand (
2045
+ (*I.memoperands_begin ())
2046
+ ->getPointerInfo ()
2047
+ .getWithOffset (OffsetBytes),
2048
+ MachineMemOperand::MOStore, PtrSize, Align (PtrSize)));
2049
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2050
+
2051
+ OffsetBytes += PtrSize;
2052
+ };
2053
+
2054
+ // void* stack at offset 0
2055
+ PushAddress (FuncInfo->getVarArgsStackIndex (), 0 );
2056
+
2057
+ // void* gr_top at offset 8 (4 on ILP32)
2058
+ const unsigned GPRSize = FuncInfo->getVarArgsGPRSize ();
2059
+ PushAddress (FuncInfo->getVarArgsGPRIndex (), GPRSize);
2060
+
2061
+ // void* vr_top at offset 16 (8 on ILP32)
2062
+ const unsigned FPRSize = FuncInfo->getVarArgsFPRSize ();
2063
+ PushAddress (FuncInfo->getVarArgsFPRIndex (), FPRSize);
2064
+
2065
+ // Helper function to store a 4-byte integer constant to VAList at offset
2066
+ // OffsetBytes, and increment OffsetBytes by 4.
2067
+ const auto PushIntConstant = [&](const int32_t Value) {
2068
+ constexpr int IntSize = 4 ;
2069
+ const Register Temp = MRI.createVirtualRegister (&AArch64::GPR32RegClass);
2070
+ auto MIB =
2071
+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (AArch64::MOVi32imm))
2072
+ .addDef (Temp)
2073
+ .addImm (Value);
2074
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2075
+
2076
+ MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (AArch64::STRWui))
2077
+ .addUse (Temp)
2078
+ .addUse (VAList)
2079
+ .addImm (OffsetBytes / IntSize)
2080
+ .addMemOperand (MF.getMachineMemOperand (
2081
+ (*I.memoperands_begin ())
2082
+ ->getPointerInfo ()
2083
+ .getWithOffset (OffsetBytes),
2084
+ MachineMemOperand::MOStore, IntSize, Align (IntSize)));
2085
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2086
+ OffsetBytes += IntSize;
2087
+ };
2088
+
2089
+ // int gr_offs at offset 24 (12 on ILP32)
2090
+ PushIntConstant (-static_cast <int32_t >(GPRSize));
2091
+
2092
+ // int vr_offs at offset 28 (16 on ILP32)
2093
+ PushIntConstant (-static_cast <int32_t >(FPRSize));
2094
+
2095
+ assert (OffsetBytes == (STI.isTargetILP32 () ? 20 : 32 ) && " Unexpected offset" );
2096
+
2097
+ I.eraseFromParent ();
2098
+ return true ;
1998
2099
}
1999
2100
2000
2101
bool AArch64InstructionSelector::selectVaStartDarwin (
0 commit comments