@@ -423,18 +423,84 @@ bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
423423 return true ;
424424}
425425
426+ static const MCPhysReg ArgGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,
427+ RISCV::X13, RISCV::X14, RISCV::X15,
428+ RISCV::X16, RISCV::X17};
429+
430+ // / If there are varargs that were passed in a0-a7, the data in those registers
431+ // / must be copied to the varargs save area on the stack.
432+ void RISCVCallLowering::saveVarArgRegisters (
433+ MachineIRBuilder &MIRBuilder, CallLowering::IncomingValueHandler &Handler,
434+ IncomingValueAssigner &Assigner, CCState &CCInfo) const {
435+ MachineFunction &MF = MIRBuilder.getMF ();
436+ const RISCVSubtarget &Subtarget = MF.getSubtarget <RISCVSubtarget>();
437+ unsigned XLenInBytes = Subtarget.getXLen () / 8 ;
438+ ArrayRef<MCPhysReg> ArgRegs (ArgGPRs);
439+ unsigned Idx = CCInfo.getFirstUnallocated (ArgRegs);
440+
441+ // Offset of the first variable argument from stack pointer, and size of
442+ // the vararg save area. For now, the varargs save area is either zero or
443+ // large enough to hold a0-a7.
444+ int VaArgOffset, VarArgsSaveSize;
445+ // If all registers are allocated, then all varargs must be passed on the
446+ // stack and we don't need to save any argregs.
447+ if (ArgRegs.size () == Idx) {
448+ VaArgOffset = Assigner.StackSize ;
449+ VarArgsSaveSize = 0 ;
450+ } else {
451+ VarArgsSaveSize = XLenInBytes * (ArgRegs.size () - Idx);
452+ VaArgOffset = -VarArgsSaveSize;
453+ }
454+
455+ // Record the frame index of the first variable argument which is a value
456+ // necessary to G_VASTART.
457+ MachineFrameInfo &MFI = MF.getFrameInfo ();
458+ int FI = MFI.CreateFixedObject (XLenInBytes, VaArgOffset, true );
459+ RISCVMachineFunctionInfo *RVFI = MF.getInfo <RISCVMachineFunctionInfo>();
460+ RVFI->setVarArgsFrameIndex (FI);
461+
462+ // If saving an odd number of registers then create an extra stack slot to
463+ // ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
464+ // offsets to even-numbered registered remain 2*XLEN-aligned.
465+ if (Idx % 2 ) {
466+ MFI.CreateFixedObject (XLenInBytes, VaArgOffset - (int )XLenInBytes, true );
467+ VarArgsSaveSize += XLenInBytes;
468+ }
469+ RVFI->setVarArgsSaveSize (VarArgsSaveSize);
470+
471+ // Copy the integer registers that may have been used for passing varargs
472+ // to the vararg save area.
473+ const LLT p0 = LLT::pointer (MF.getDataLayout ().getAllocaAddrSpace (),
474+ Subtarget.getXLen ());
475+ const LLT sXLen = LLT::scalar (Subtarget.getXLen ());
476+ const MVT XLenVT = Subtarget.getXLenVT ();
477+ MachineRegisterInfo &MRI = MF.getRegInfo ();
478+ for (unsigned I = Idx; I < ArgRegs.size (); ++I, VaArgOffset += XLenInBytes) {
479+ const Register VReg = MRI.createGenericVirtualRegister (sXLen );
480+ Handler.assignValueToReg (
481+ VReg, ArgRegs[I],
482+ CCValAssign::getReg (I + MF.getFunction ().getNumOperands (), XLenVT,
483+ ArgRegs[I], XLenVT, CCValAssign::Full));
484+ FI = MFI.CreateFixedObject (XLenInBytes, VaArgOffset, true );
485+ auto FIN = MIRBuilder.buildFrameIndex (p0, FI);
486+ auto MPO = MachinePointerInfo::getFixedStack (MF, FI);
487+ auto Store =
488+ MIRBuilder.buildStore (VReg, FIN, MPO, inferAlignFromPtrInfo (MF, MPO));
489+ // This was taken from SelectionDAG, but we are not sure why it exists.
490+ // It is being investigated in github.com/llvm/llvm-project/issues/73735.
491+ Store->memoperands ()[0 ]->setValue ((Value *)nullptr );
492+ }
493+ }
494+
426495bool RISCVCallLowering::lowerFormalArguments (MachineIRBuilder &MIRBuilder,
427496 const Function &F,
428497 ArrayRef<ArrayRef<Register>> VRegs,
429498 FunctionLoweringInfo &FLI) const {
430- // Early exit if there are no arguments.
431- if (F.arg_empty ())
499+ // Early exit if there are no arguments. varargs are not part of F.args() but
500+ // must be lowered.
501+ if (F.arg_empty () && !F.isVarArg ())
432502 return true ;
433503
434- // TODO: Support vararg functions.
435- if (F.isVarArg ())
436- return false ;
437-
438504 const RISCVSubtarget &Subtarget =
439505 MIRBuilder.getMF ().getSubtarget <RISCVSubtarget>();
440506 for (auto &Arg : F.args ()) {
@@ -467,8 +533,16 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
467533 /* IsRet=*/ false );
468534 RISCVFormalArgHandler Handler (MIRBuilder, MF.getRegInfo ());
469535
470- return determineAndHandleAssignments (Handler, Assigner, SplitArgInfos,
471- MIRBuilder, CC, F.isVarArg ());
536+ SmallVector<CCValAssign, 16 > ArgLocs;
537+ CCState CCInfo (CC, F.isVarArg (), MIRBuilder.getMF (), ArgLocs, F.getContext ());
538+ if (!determineAssignments (Assigner, SplitArgInfos, CCInfo) ||
539+ !handleAssignments (Handler, SplitArgInfos, CCInfo, ArgLocs, MIRBuilder))
540+ return false ;
541+
542+ if (F.isVarArg ())
543+ saveVarArgRegisters (MIRBuilder, Handler, Assigner, CCInfo);
544+
545+ return true ;
472546}
473547
474548bool RISCVCallLowering::lowerCall (MachineIRBuilder &MIRBuilder,
0 commit comments