@@ -1994,7 +1994,106 @@ 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 (STI.isCallingConvWin64 (MF.getFunction ().getCallingConv (),
1999
+ 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
+ const auto *MMO = *I.memoperands_begin ();
2041
+ MIB = BuildMI (*I.getParent (), I, I.getDebugLoc (), MCIDStoreAddr)
2042
+ .addUse (Top)
2043
+ .addUse (VAList)
2044
+ .addImm (OffsetBytes / PtrSize)
2045
+ .addMemOperand (MF.getMachineMemOperand (
2046
+ MMO->getPointerInfo ().getWithOffset (OffsetBytes),
2047
+ MachineMemOperand::MOStore, PtrSize, MMO->getBaseAlign ()));
2048
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2049
+
2050
+ OffsetBytes += PtrSize;
2051
+ };
2052
+
2053
+ // void* stack at offset 0
2054
+ PushAddress (FuncInfo->getVarArgsStackIndex (), 0 );
2055
+
2056
+ // void* gr_top at offset 8 (4 on ILP32)
2057
+ const unsigned GPRSize = FuncInfo->getVarArgsGPRSize ();
2058
+ PushAddress (FuncInfo->getVarArgsGPRIndex (), GPRSize);
2059
+
2060
+ // void* vr_top at offset 16 (8 on ILP32)
2061
+ const unsigned FPRSize = FuncInfo->getVarArgsFPRSize ();
2062
+ PushAddress (FuncInfo->getVarArgsFPRIndex (), FPRSize);
2063
+
2064
+ // Helper function to store a 4-byte integer constant to VAList at offset
2065
+ // OffsetBytes, and increment OffsetBytes by 4.
2066
+ const auto PushIntConstant = [&](const int32_t Value) {
2067
+ constexpr int IntSize = 4 ;
2068
+ const Register Temp = MRI.createVirtualRegister (&AArch64::GPR32RegClass);
2069
+ auto MIB =
2070
+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (AArch64::MOVi32imm))
2071
+ .addDef (Temp)
2072
+ .addImm (Value);
2073
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2074
+
2075
+ const auto *MMO = *I.memoperands_begin ();
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
+ MMO->getPointerInfo ().getWithOffset (OffsetBytes),
2082
+ MachineMemOperand::MOStore, IntSize, MMO->getBaseAlign ()));
2083
+ constrainSelectedInstRegOperands (*MIB, TII, TRI, RBI);
2084
+ OffsetBytes += IntSize;
2085
+ };
2086
+
2087
+ // int gr_offs at offset 24 (12 on ILP32)
2088
+ PushIntConstant (-static_cast <int32_t >(GPRSize));
2089
+
2090
+ // int vr_offs at offset 28 (16 on ILP32)
2091
+ PushIntConstant (-static_cast <int32_t >(FPRSize));
2092
+
2093
+ assert (OffsetBytes == (STI.isTargetILP32 () ? 20 : 32 ) && " Unexpected offset" );
2094
+
2095
+ I.eraseFromParent ();
2096
+ return true ;
1998
2097
}
1999
2098
2000
2099
bool AArch64InstructionSelector::selectVaStartDarwin (
0 commit comments