[llvm] [Xtensa] Implement vararg support. (PR #117126)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 9 15:55:34 PST 2024
================
@@ -859,6 +909,148 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
return DAG.getMergeValues(Ops, DL);
}
+SDValue XtensaTargetLowering::LowerVASTART(SDValue Op,
+ SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ XtensaMachineFunctionInfo *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
+ SDValue Chain = Op.getOperand(0);
+ SDValue Addr = Op.getOperand(1);
+ EVT PtrVT = Addr.getValueType();
+ SDLoc DL(Op);
+
+ // Struct va_list_tag
+ // int32 *va_stk - points to the arguments passed in memory
+ // int32 *va_reg - points to the registers with arguments saved in memory
+ // int32 va_ndx - offset from va_stk or va_reg pointers which points to the
+ // next variable argument
+
+ SDValue VAIndex;
+ SDValue StackOffsetFI =
+ DAG.getFrameIndex(XtensaFI->getVarArgsOnStackFrameIndex(), PtrVT);
+ unsigned ArgWords = XtensaFI->getVarArgsFirstGPR() - 2;
+
+ // If first variable argument passed in registers (maximum words in registers
+ // is 6) then set va_ndx to the position of this argument in registers area
+ // stored in memory (va_reg pointer). Otherwise va_ndx should point to the
+ // position of the first variable argument on stack (va_stk pointer).
+ if (ArgWords < 6) {
+ VAIndex = DAG.getConstant(ArgWords * 4, DL, MVT::i32);
+ } else {
+ VAIndex = DAG.getConstant(32, DL, MVT::i32);
+ }
+
+ SDValue FrameIndex =
+ DAG.getFrameIndex(XtensaFI->getVarArgsInRegsFrameIndex(), PtrVT);
+ uint64_t FrameOffset = PtrVT.getStoreSize();
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+
+ // Store pointer to arguments given on stack (va_stk)
+ SDValue StackPtr = DAG.getNode(ISD::SUB, DL, PtrVT, StackOffsetFI,
+ DAG.getConstant(32, DL, PtrVT));
+
+ SDValue StoreStackPtr =
+ DAG.getStore(Chain, DL, StackPtr, Addr, MachinePointerInfo(SV));
+
+ uint64_t NextOffset = FrameOffset;
+ SDValue NextPtr =
+ DAG.getObjectPtrOffset(DL, Addr, TypeSize::getFixed(NextOffset));
+
+ // Store pointer to arguments given on registers (va_reg)
+ SDValue StoreRegPtr = DAG.getStore(StoreStackPtr, DL, FrameIndex, NextPtr,
+ MachinePointerInfo(SV, NextOffset));
+ NextOffset += FrameOffset;
+ NextPtr = DAG.getObjectPtrOffset(DL, Addr, TypeSize::getFixed(NextOffset));
+
+ // Store third word : position in bytes of the first VA argument (va_ndx)
+ return DAG.getStore(StoreRegPtr, DL, VAIndex, NextPtr,
+ MachinePointerInfo(SV, NextOffset));
+}
+
+SDValue XtensaTargetLowering::LowerVACOPY(SDValue Op, SelectionDAG &DAG) const {
+ // Size of the va_list_tag structure
+ constexpr unsigned VAListSize = 3 * 4;
+ return DAG.getMemcpy(
+ Op.getOperand(0), Op, Op.getOperand(1), Op.getOperand(2),
+ DAG.getConstant(VAListSize, SDLoc(Op), MVT::i32), Align(4),
+ /*isVolatile=*/false, /*AlwaysInline=*/false,
+ /*CI=*/nullptr, std::nullopt, MachinePointerInfo(), MachinePointerInfo());
----------------
andreisfr wrote:
I corrected lowering VACOPY.
https://github.com/llvm/llvm-project/pull/117126
More information about the llvm-commits
mailing list