@@ -423,18 +423,84 @@ bool RISCVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
423
423
return true ;
424
424
}
425
425
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
+
426
495
bool RISCVCallLowering::lowerFormalArguments (MachineIRBuilder &MIRBuilder,
427
496
const Function &F,
428
497
ArrayRef<ArrayRef<Register>> VRegs,
429
498
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 ())
432
502
return true ;
433
503
434
- // TODO: Support vararg functions.
435
- if (F.isVarArg ())
436
- return false ;
437
-
438
504
const RISCVSubtarget &Subtarget =
439
505
MIRBuilder.getMF ().getSubtarget <RISCVSubtarget>();
440
506
for (auto &Arg : F.args ()) {
@@ -467,8 +533,16 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
467
533
/* IsRet=*/ false );
468
534
RISCVFormalArgHandler Handler (MIRBuilder, MF.getRegInfo ());
469
535
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 ;
472
546
}
473
547
474
548
bool RISCVCallLowering::lowerCall (MachineIRBuilder &MIRBuilder,
0 commit comments