[llvm] [GISel][RISCV]Implement indirect parameter passing (PR #95429)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 15:47:12 PDT 2024
================
@@ -765,31 +770,72 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
// intermediate values.
Args[i].Regs.resize(NumParts);
- // For each split register, create and assign a vreg that will store
- // the incoming component of the larger value. These will later be
- // merged to form the final vreg.
- for (unsigned Part = 0; Part < NumParts; ++Part)
- Args[i].Regs[Part] = MRI.createGenericVirtualRegister(NewLLT);
+ // When we have indirect parameter passing we are receiving a pointer,
+ // that points to the actual value, so we need one "temporary" pointer.
+ if (VA.getLocInfo() == CCValAssign::Indirect) {
+ if (Handler.isIncomingArgumentHandler())
+ Args[i].Regs[0] = MRI.createGenericVirtualRegister(PointerTy);
+ } else {
+ // For each split register, create and assign a vreg that will store
+ // the incoming component of the larger value. These will later be
+ // merged to form the final vreg.
+ for (unsigned Part = 0; Part < NumParts; ++Part)
+ Args[i].Regs[Part] = MRI.createGenericVirtualRegister(NewLLT);
+ }
}
assert((j + (NumParts - 1)) < ArgLocs.size() &&
"Too many regs for number of args");
// Coerce into outgoing value types before register assignment.
- if (!Handler.isIncomingArgumentHandler() && OrigTy != ValTy) {
+ if (!Handler.isIncomingArgumentHandler() && OrigTy != ValTy &&
+ VA.getLocInfo() != CCValAssign::Indirect) {
assert(Args[i].OrigRegs.size() == 1);
buildCopyToRegs(MIRBuilder, Args[i].Regs, Args[i].OrigRegs[0], OrigTy,
ValTy, extendOpFromFlags(Args[i].Flags[0]));
}
+ bool IndirectParameterPassingHandled = false;
bool BigEndianPartOrdering = TLI->hasBigEndianPartOrdering(OrigVT, DL);
for (unsigned Part = 0; Part < NumParts; ++Part) {
+ assert((VA.getLocInfo() != CCValAssign::Indirect || Part == 0) &&
+ "Only the first parameter should be processed when "
+ "handling indirect passing!");
Register ArgReg = Args[i].Regs[Part];
// There should be Regs.size() ArgLocs per argument.
unsigned Idx = BigEndianPartOrdering ? NumParts - 1 - Part : Part;
CCValAssign &VA = ArgLocs[j + Idx];
const ISD::ArgFlagsTy Flags = Args[i].Flags[Part];
+ // We found an indirect parameter passing, and we have an
+ // OutgoingValueHandler as our handler (so we are at the call site or the
+ // return value). In this case, start the construction of the following
+ // GMIR, that is responsible for the preparation of indirect parameter
+ // passing:
+ //
+ // %1(indirectly passed type) = The value to pass
+ // %3(pointer) = G_FRAME_INDEX %stack.0
+ // G_STORE %1, %3 :: (store (s128), align 8)
+ //
+ // After this GMIR, the remaining part of the loop body will decide how
+ // to get the value to the caller and we break out of the loop.
+ if (VA.getLocInfo() == CCValAssign::Indirect &&
+ !Handler.isIncomingArgumentHandler()) {
+ Align StackAlign = DL.getPrefTypeAlign(Args[i].Ty);
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ int FrameIdx = MFI.CreateStackObject(OrigTy.getScalarSizeInBits(),
+ StackAlign, false);
+ Register PointerToStackReg =
+ MIRBuilder.buildFrameIndex(PointerTy, FrameIdx).getReg(0);
+ MachinePointerInfo DstMPO =
+ MachinePointerInfo::getFixedStack(MF, FrameIdx);
+ MIRBuilder.buildStore(Args[i].OrigRegs[Part], PointerToStackReg, DstMPO,
+ inferAlignFromPtrInfo(MF, DstMPO));
----------------
topperc wrote:
Why do we need to infer align? Isn't it just `StackAlign`?
https://github.com/llvm/llvm-project/pull/95429
More information about the llvm-commits
mailing list