14
14
#include " XtensaISelLowering.h"
15
15
#include " XtensaConstantPoolValue.h"
16
16
#include " XtensaInstrInfo.h"
17
+ #include " XtensaMachineFunctionInfo.h"
17
18
#include " XtensaSubtarget.h"
18
19
#include " XtensaTargetMachine.h"
19
20
#include " llvm/CodeGen/CallingConvLower.h"
@@ -133,6 +134,13 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
133
134
setOperationAction (ISD::STACKSAVE, MVT::Other, Custom);
134
135
setOperationAction (ISD::STACKRESTORE, MVT::Other, Custom);
135
136
137
+ // VASTART, VAARG and VACOPY need to deal with the Xtensa-specific varargs
138
+ // structure, but VAEND is a no-op.
139
+ setOperationAction (ISD::VASTART, MVT::Other, Custom);
140
+ setOperationAction (ISD::VAARG, MVT::Other, Custom);
141
+ setOperationAction (ISD::VACOPY, MVT::Other, Custom);
142
+ setOperationAction (ISD::VAEND, MVT::Other, Expand);
143
+
136
144
// Compute derived properties from the register classes
137
145
computeRegisterProperties (STI.getRegisterInfo ());
138
146
}
@@ -217,12 +225,12 @@ void XtensaTargetLowering::LowerAsmOperandForConstraint(
217
225
218
226
#include " XtensaGenCallingConv.inc"
219
227
228
+ static const MCPhysReg IntRegs[] = {Xtensa::A2, Xtensa::A3, Xtensa::A4,
229
+ Xtensa::A5, Xtensa::A6, Xtensa::A7};
230
+
220
231
static bool CC_Xtensa_Custom (unsigned ValNo, MVT ValVT, MVT LocVT,
221
232
CCValAssign::LocInfo LocInfo,
222
233
ISD::ArgFlagsTy ArgFlags, CCState &State) {
223
- static const MCPhysReg IntRegs[] = {Xtensa::A2, Xtensa::A3, Xtensa::A4,
224
- Xtensa::A5, Xtensa::A6, Xtensa::A7};
225
-
226
234
if (ArgFlags.isByVal ()) {
227
235
Align ByValAlign = ArgFlags.getNonZeroByValAlign ();
228
236
unsigned ByValSize = ArgFlags.getByValSize ();
@@ -304,13 +312,11 @@ SDValue XtensaTargetLowering::LowerFormalArguments(
304
312
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
305
313
MachineFunction &MF = DAG.getMachineFunction ();
306
314
MachineFrameInfo &MFI = MF.getFrameInfo ();
315
+ XtensaMachineFunctionInfo *XtensaFI = MF.getInfo <XtensaMachineFunctionInfo>();
307
316
308
317
// Used with vargs to acumulate store chains.
309
318
std::vector<SDValue> OutChains;
310
319
311
- if (IsVarArg)
312
- report_fatal_error (" Var arg not supported by FormalArguments Lowering" );
313
-
314
320
// Assign locations to all of the incoming arguments.
315
321
SmallVector<CCValAssign, 16 > ArgLocs;
316
322
CCState CCInfo (CallConv, IsVarArg, DAG.getMachineFunction (), ArgLocs,
@@ -323,17 +329,14 @@ SDValue XtensaTargetLowering::LowerFormalArguments(
323
329
// Arguments stored on registers
324
330
if (VA.isRegLoc ()) {
325
331
EVT RegVT = VA.getLocVT ();
326
- const TargetRegisterClass *RC;
327
332
328
- if (RegVT == MVT::i32)
329
- RC = &Xtensa::ARRegClass;
330
- else
333
+ if (RegVT != MVT::i32)
331
334
report_fatal_error (" RegVT not supported by FormalArguments Lowering" );
332
335
333
336
// Transform the arguments stored on
334
337
// physical registers into virtual ones
335
- unsigned Register = MF.addLiveIn (VA.getLocReg (), RC );
336
- SDValue ArgValue = DAG.getCopyFromReg (Chain, DL, Register , RegVT);
338
+ Register Reg = MF.addLiveIn (VA.getLocReg (), &Xtensa::ARRegClass );
339
+ SDValue ArgValue = DAG.getCopyFromReg (Chain, DL, Reg , RegVT);
337
340
338
341
// If this is an 8 or 16-bit value, it has been passed promoted
339
342
// to 32 bits. Insert an assert[sz]ext to capture this, then
@@ -378,6 +381,56 @@ SDValue XtensaTargetLowering::LowerFormalArguments(
378
381
}
379
382
}
380
383
384
+ if (IsVarArg) {
385
+ unsigned Idx = CCInfo.getFirstUnallocated (IntRegs);
386
+ unsigned ArgRegsNum = std::size (IntRegs);
387
+ const TargetRegisterClass *RC = &Xtensa::ARRegClass;
388
+ MachineFrameInfo &MFI = MF.getFrameInfo ();
389
+ MachineRegisterInfo &RegInfo = MF.getRegInfo ();
390
+ unsigned RegSize = 4 ;
391
+ MVT RegTy = MVT::i32;
392
+ MVT FITy = getFrameIndexTy (DAG.getDataLayout ());
393
+
394
+ XtensaFI->setVarArgsFirstGPR (Idx + 2 ); // 2 - number of a2 register
395
+
396
+ XtensaFI->setVarArgsOnStackFrameIndex (
397
+ MFI.CreateFixedObject (4 , CCInfo.getStackSize (), true ));
398
+
399
+ // Offset of the first variable argument from stack pointer, and size of
400
+ // the vararg save area. For now, the varargs save area is either zero or
401
+ // large enough to hold a0-a7.
402
+ int VaArgOffset, VarArgsSaveSize;
403
+
404
+ // If all registers are allocated, then all varargs must be passed on the
405
+ // stack and we don't need to save any argregs.
406
+ if (ArgRegsNum == Idx) {
407
+ VaArgOffset = CCInfo.getStackSize ();
408
+ VarArgsSaveSize = 0 ;
409
+ } else {
410
+ VarArgsSaveSize = RegSize * (ArgRegsNum - Idx);
411
+ VaArgOffset = -VarArgsSaveSize;
412
+
413
+ // Record the frame index of the first variable argument
414
+ // which is a value necessary to VASTART.
415
+ int FI = MFI.CreateFixedObject (RegSize, VaArgOffset, true );
416
+ XtensaFI->setVarArgsInRegsFrameIndex (FI);
417
+
418
+ // Copy the integer registers that may have been used for passing varargs
419
+ // to the vararg save area.
420
+ for (unsigned I = Idx; I < ArgRegsNum; ++I, VaArgOffset += RegSize) {
421
+ const Register Reg = RegInfo.createVirtualRegister (RC);
422
+ RegInfo.addLiveIn (IntRegs[I], Reg);
423
+
424
+ SDValue ArgValue = DAG.getCopyFromReg (Chain, DL, Reg, RegTy);
425
+ FI = MFI.CreateFixedObject (RegSize, VaArgOffset, true );
426
+ SDValue PtrOff = DAG.getFrameIndex (FI, FITy);
427
+ SDValue Store = DAG.getStore (Chain, DL, ArgValue, PtrOff,
428
+ MachinePointerInfo::getFixedStack (MF, FI));
429
+ OutChains.push_back (Store);
430
+ }
431
+ }
432
+ }
433
+
381
434
// All stores are grouped in one node to allow the matching between
382
435
// the size of Ins and InVals. This only happens when on varg functions
383
436
if (!OutChains.empty ()) {
@@ -579,9 +632,6 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
579
632
const SmallVectorImpl<ISD::OutputArg> &Outs,
580
633
const SmallVectorImpl<SDValue> &OutVals,
581
634
const SDLoc &DL, SelectionDAG &DAG) const {
582
- if (IsVarArg)
583
- report_fatal_error (" VarArg not supported" );
584
-
585
635
MachineFunction &MF = DAG.getMachineFunction ();
586
636
587
637
// Assign locations to each returned value.
@@ -859,6 +909,156 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
859
909
return DAG.getMergeValues (Ops, DL);
860
910
}
861
911
912
+ SDValue XtensaTargetLowering::LowerVASTART (SDValue Op,
913
+ SelectionDAG &DAG) const {
914
+ MachineFunction &MF = DAG.getMachineFunction ();
915
+ XtensaMachineFunctionInfo *XtensaFI = MF.getInfo <XtensaMachineFunctionInfo>();
916
+ SDValue Chain = Op.getOperand (0 );
917
+ SDValue Addr = Op.getOperand (1 );
918
+ EVT PtrVT = Addr.getValueType ();
919
+ SDLoc DL (Op);
920
+
921
+ // Struct va_list_tag
922
+ // int32 *va_stk - points to the arguments passed in memory
923
+ // int32 *va_reg - points to the registers with arguments saved in memory
924
+ // int32 va_ndx - offset from va_stk or va_reg pointers which points to the
925
+ // next variable argument
926
+
927
+ SDValue VAIndex;
928
+ SDValue StackOffsetFI =
929
+ DAG.getFrameIndex (XtensaFI->getVarArgsOnStackFrameIndex (), PtrVT);
930
+ unsigned ArgWords = XtensaFI->getVarArgsFirstGPR () - 2 ;
931
+
932
+ // If first variable argument passed in registers (maximum words in registers
933
+ // is 6) then set va_ndx to the position of this argument in registers area
934
+ // stored in memory (va_reg pointer). Otherwise va_ndx should point to the
935
+ // position of the first variable argument on stack (va_stk pointer).
936
+ if (ArgWords < 6 ) {
937
+ VAIndex = DAG.getConstant (ArgWords * 4 , DL, MVT::i32);
938
+ } else {
939
+ VAIndex = DAG.getConstant (32 , DL, MVT::i32);
940
+ }
941
+
942
+ SDValue FrameIndex =
943
+ DAG.getFrameIndex (XtensaFI->getVarArgsInRegsFrameIndex (), PtrVT);
944
+ uint64_t FrameOffset = PtrVT.getStoreSize ();
945
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand (2 ))->getValue ();
946
+
947
+ // Store pointer to arguments given on stack (va_stk)
948
+ SDValue StackPtr = DAG.getNode (ISD::SUB, DL, PtrVT, StackOffsetFI,
949
+ DAG.getConstant (32 , DL, PtrVT));
950
+
951
+ SDValue StoreStackPtr =
952
+ DAG.getStore (Chain, DL, StackPtr, Addr, MachinePointerInfo (SV));
953
+
954
+ uint64_t NextOffset = FrameOffset;
955
+ SDValue NextPtr =
956
+ DAG.getObjectPtrOffset (DL, Addr, TypeSize::getFixed (NextOffset));
957
+
958
+ // Store pointer to arguments given on registers (va_reg)
959
+ SDValue StoreRegPtr = DAG.getStore (StoreStackPtr, DL, FrameIndex, NextPtr,
960
+ MachinePointerInfo (SV, NextOffset));
961
+ NextOffset += FrameOffset;
962
+ NextPtr = DAG.getObjectPtrOffset (DL, Addr, TypeSize::getFixed (NextOffset));
963
+
964
+ // Store third word : position in bytes of the first VA argument (va_ndx)
965
+ return DAG.getStore (StoreRegPtr, DL, VAIndex, NextPtr,
966
+ MachinePointerInfo (SV, NextOffset));
967
+ }
968
+
969
+ SDValue XtensaTargetLowering::LowerVACOPY (SDValue Op, SelectionDAG &DAG) const {
970
+ // Size of the va_list_tag structure
971
+ constexpr unsigned VAListSize = 3 * 4 ;
972
+ SDValue Chain = Op.getOperand (0 );
973
+ SDValue DstPtr = Op.getOperand (1 );
974
+ SDValue SrcPtr = Op.getOperand (2 );
975
+ const Value *DstSV = cast<SrcValueSDNode>(Op.getOperand (3 ))->getValue ();
976
+ const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand (4 ))->getValue ();
977
+ SDLoc DL (Op);
978
+
979
+ return DAG.getMemcpy (Chain, DL, DstPtr, SrcPtr,
980
+ DAG.getConstant (VAListSize, SDLoc (Op), MVT::i32),
981
+ Align (4 ), /* isVolatile*/ false , /* AlwaysInline*/ true ,
982
+ /* CI=*/ nullptr , std::nullopt, MachinePointerInfo (DstSV),
983
+ MachinePointerInfo (SrcSV));
984
+ }
985
+
986
+ SDValue XtensaTargetLowering::LowerVAARG (SDValue Op, SelectionDAG &DAG) const {
987
+ SDNode *Node = Op.getNode ();
988
+ EVT VT = Node->getValueType (0 );
989
+ Type *Ty = VT.getTypeForEVT (*DAG.getContext ());
990
+ EVT PtrVT = Op.getValueType ();
991
+ SDValue InChain = Node->getOperand (0 );
992
+ SDValue VAListPtr = Node->getOperand (1 );
993
+ const Value *SV = cast<SrcValueSDNode>(Node->getOperand (2 ))->getValue ();
994
+ SDLoc DL (Node);
995
+ auto &TD = DAG.getDataLayout ();
996
+ Align ArgAlignment = TD.getABITypeAlign (Ty);
997
+ unsigned ArgAlignInBytes = ArgAlignment.value ();
998
+ unsigned ArgSizeInBytes = TD.getTypeAllocSize (Ty);
999
+ unsigned VASizeInBytes = llvm::alignTo (ArgSizeInBytes, 4 );
1000
+
1001
+ // va_stk
1002
+ SDValue VAStack =
1003
+ DAG.getLoad (MVT::i32, DL, InChain, VAListPtr, MachinePointerInfo ());
1004
+ InChain = VAStack.getValue (1 );
1005
+
1006
+ // va_reg
1007
+ SDValue VARegPtr =
1008
+ DAG.getObjectPtrOffset (DL, VAListPtr, TypeSize::getFixed (4 ));
1009
+ SDValue VAReg =
1010
+ DAG.getLoad (MVT::i32, DL, InChain, VARegPtr, MachinePointerInfo ());
1011
+ InChain = VAReg.getValue (1 );
1012
+
1013
+ // va_ndx
1014
+ SDValue VarArgIndexPtr =
1015
+ DAG.getObjectPtrOffset (DL, VARegPtr, TypeSize::getFixed (4 ));
1016
+ SDValue VAIndex =
1017
+ DAG.getLoad (MVT::i32, DL, InChain, VarArgIndexPtr, MachinePointerInfo ());
1018
+ InChain = VAIndex.getValue (1 );
1019
+
1020
+ SDValue OrigIndex = VAIndex;
1021
+
1022
+ if (ArgAlignInBytes > 4 ) {
1023
+ OrigIndex = DAG.getNode (ISD::ADD, DL, PtrVT, OrigIndex,
1024
+ DAG.getConstant (ArgAlignInBytes - 1 , DL, MVT::i32));
1025
+ OrigIndex =
1026
+ DAG.getNode (ISD::AND, DL, PtrVT, OrigIndex,
1027
+ DAG.getSignedConstant (-ArgAlignInBytes, DL, MVT::i32));
1028
+ }
1029
+
1030
+ VAIndex = DAG.getNode (ISD::ADD, DL, PtrVT, OrigIndex,
1031
+ DAG.getConstant (VASizeInBytes, DL, MVT::i32));
1032
+
1033
+ SDValue CC = DAG.getSetCC (DL, MVT::i32, OrigIndex,
1034
+ DAG.getConstant (6 * 4 , DL, MVT::i32), ISD::SETLE);
1035
+
1036
+ SDValue StkIndex =
1037
+ DAG.getNode (ISD::ADD, DL, PtrVT, VAIndex,
1038
+ DAG.getConstant (32 + VASizeInBytes, DL, MVT::i32));
1039
+
1040
+ CC = DAG.getSetCC (DL, MVT::i32, VAIndex, DAG.getConstant (6 * 4 , DL, MVT::i32),
1041
+ ISD::SETLE);
1042
+
1043
+ SDValue Array = DAG.getNode (ISD::SELECT, DL, MVT::i32, CC, VAReg, VAStack);
1044
+
1045
+ VAIndex = DAG.getNode (ISD::SELECT, DL, MVT::i32, CC, VAIndex, StkIndex);
1046
+
1047
+ CC = DAG.getSetCC (DL, MVT::i32, VAIndex, DAG.getConstant (6 * 4 , DL, MVT::i32),
1048
+ ISD::SETLE);
1049
+
1050
+ SDValue VAIndexStore = DAG.getStore (InChain, DL, VAIndex, VarArgIndexPtr,
1051
+ MachinePointerInfo (SV));
1052
+ InChain = VAIndexStore;
1053
+
1054
+ SDValue Addr = DAG.getNode (ISD::SUB, DL, PtrVT, VAIndex,
1055
+ DAG.getConstant (VASizeInBytes, DL, MVT::i32));
1056
+
1057
+ Addr = DAG.getNode (ISD::ADD, DL, PtrVT, Array, Addr);
1058
+
1059
+ return DAG.getLoad (VT, DL, InChain, Addr, MachinePointerInfo ());
1060
+ }
1061
+
862
1062
SDValue XtensaTargetLowering::LowerShiftLeftParts (SDValue Op,
863
1063
SelectionDAG &DAG) const {
864
1064
SDLoc DL (Op);
@@ -1001,6 +1201,12 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
1001
1201
return LowerFRAMEADDR (Op, DAG);
1002
1202
case ISD::DYNAMIC_STACKALLOC:
1003
1203
return LowerDYNAMIC_STACKALLOC (Op, DAG);
1204
+ case ISD::VASTART:
1205
+ return LowerVASTART (Op, DAG);
1206
+ case ISD::VAARG:
1207
+ return LowerVAARG (Op, DAG);
1208
+ case ISD::VACOPY:
1209
+ return LowerVACOPY (Op, DAG);
1004
1210
case ISD::SHL_PARTS:
1005
1211
return LowerShiftLeftParts (Op, DAG);
1006
1212
case ISD::SRA_PARTS:
0 commit comments