[llvm] [GISel][RISCV]Implement indirect parameter passing (PR #95429)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 16 12:51:51 PDT 2024


================
@@ -790,6 +810,59 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
       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.
+      // NOTE: In the case, when the the pointer pointing to the value is passed
+      // in a register there is an exception to this, that is detailed bellow.
+      if (VA.getLocInfo() == CCValAssign::Indirect && Flags.isSplit() &&
+          !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);
+
+        Align DstAlign =
+            std::max(DL.getStackAlignment(), inferAlignFromPtrInfo(MF, DstMPO));
+
+        MIRBuilder.buildStore(Args[i].OrigRegs[Part], PointerToStackReg, DstMPO,
+                              DstAlign);
+
+        // If the value is not on the stack, then dispatch the process of
+        // moving it to the correct place for the call to the rest of the code.
+        if (!VA.isMemLoc()) {
+          ArgReg = PointerToStackReg;
+        }
+        // This value assign or load are needed here for the case, when the
+        // pointer to stack is passed, since there is no other case later that
+        // would handle this.
+        if (VA.isMemLoc()) {
+          LLT MemTy = Handler.getStackValueStoreType(DL, VA, Flags);
+          MachinePointerInfo MPO;
+          auto PassedStackAddress = Handler.getStackAddress(
+              MemTy.getSizeInBytes(), VA.getLocMemOffset(), MPO, Flags);
+          MIRBuilder.buildStore(PointerToStackReg, PassedStackAddress, DstMPO,
+                                DstAlign);
----------------
spaits wrote:

If I remove this "exception", but keep the `ArgReg = PointerToStackReg;` (Needed so we try to store/copy the right thing) statement I will end up with GMIR like this:
```
%18:_(p0) = G_FRAME_INDEX %stack.0
  G_STORE %2:_(s128), %18:_(p0) :: (store (s128) into %stack.0)
  %19:_(s32) = G_CONSTANT i32 8
  %20:_(p0) = G_PTR_ADD %13:_, %19:_(s32)
  G_STORE %2:_(s128), %20:_(p0) :: (store (s32) into stack + 8, align 8)
```
So basically instead of puting the pointer onto the stack, it will try to put the whole argument onto the stack. The reason for this is the Handler API or to be more exact, the way that API is used here. In the branch, you have mentioned, this is how the function is called:
```cpp
Handler.assignValueToAddress(Args[i], Part, StackAddr, MemTy, MPO, VA);
``` 
So here we are not passing a register, but rather an `ArgInfo` and an index to the register.
If I remember correctly, there is another overload of this function, that takes a concrete register. I will try to replace this call with that, and see how that would work.

https://github.com/llvm/llvm-project/pull/95429


More information about the llvm-commits mailing list