mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
Add method MipsTargetLowering::passByValArg.
This method emits nodes for passing byval arguments in registers and stack. This has the same functionality as existing functions PassByValArg64 and WriteByValArg which will be deleted later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166843 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eb98ae46bc
commit
db40edeb11
@ -3979,3 +3979,100 @@ copyByValRegs(SDValue Chain, DebugLoc DL, std::vector<SDValue> &OutChains,
|
||||
OutChains.push_back(Store);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy byVal arg to registers and stack.
|
||||
void MipsTargetLowering::
|
||||
passByValArg(SDValue Chain, DebugLoc DL,
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass,
|
||||
SmallVector<SDValue, 8> &MemOpChains, SDValue StackPtr,
|
||||
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
|
||||
const MipsCC &CC, const ByValArgInfo &ByVal,
|
||||
const ISD::ArgFlagsTy &Flags, bool isLittle) const {
|
||||
unsigned ByValSize = Flags.getByValSize();
|
||||
unsigned Offset = 0; // Offset in # of bytes from the beginning of struct.
|
||||
unsigned RegSize = CC.regSize();
|
||||
unsigned Alignment = std::min(Flags.getByValAlign(), RegSize);
|
||||
EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSize * 8);
|
||||
|
||||
if (ByVal.NumRegs) {
|
||||
const uint16_t *ArgRegs = CC.intArgRegs();
|
||||
bool LeftoverBytes = (ByVal.NumRegs * RegSize > ByValSize);
|
||||
unsigned I = 0;
|
||||
|
||||
// Copy words to registers.
|
||||
for (; I < ByVal.NumRegs - LeftoverBytes; ++I, Offset += RegSize) {
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr,
|
||||
MachinePointerInfo(), false, false, false,
|
||||
Alignment);
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I];
|
||||
RegsToPass.push_back(std::make_pair(ArgReg, LoadVal));
|
||||
}
|
||||
|
||||
// Return if the struct has been fully copied.
|
||||
if (ByValSize == Offset)
|
||||
return;
|
||||
|
||||
// Copy the remainder of the byval argument with sub-word loads and shifts.
|
||||
if (LeftoverBytes) {
|
||||
assert((ByValSize > Offset) && (ByValSize < Offset + RegSize) &&
|
||||
"Size of the remainder should be smaller than RegSize.");
|
||||
SDValue Val;
|
||||
|
||||
for (unsigned LoadSize = RegSize / 2, TotalSizeLoaded = 0;
|
||||
Offset < ByValSize; LoadSize /= 2) {
|
||||
unsigned RemSize = ByValSize - Offset;
|
||||
|
||||
if (RemSize < LoadSize)
|
||||
continue;
|
||||
|
||||
// Load subword.
|
||||
SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue LoadVal =
|
||||
DAG.getExtLoad(ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr,
|
||||
MachinePointerInfo(), MVT::getIntegerVT(LoadSize * 8),
|
||||
false, false, Alignment);
|
||||
MemOpChains.push_back(LoadVal.getValue(1));
|
||||
|
||||
// Shift the loaded value.
|
||||
unsigned Shamt;
|
||||
|
||||
if (isLittle)
|
||||
Shamt = TotalSizeLoaded;
|
||||
else
|
||||
Shamt = (RegSize - (TotalSizeLoaded + LoadSize)) * 8;
|
||||
|
||||
SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal,
|
||||
DAG.getConstant(Shamt, MVT::i32));
|
||||
|
||||
if (Val.getNode())
|
||||
Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift);
|
||||
else
|
||||
Val = Shift;
|
||||
|
||||
Offset += LoadSize;
|
||||
TotalSizeLoaded += LoadSize;
|
||||
Alignment = std::min(Alignment, LoadSize);
|
||||
}
|
||||
|
||||
unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I];
|
||||
RegsToPass.push_back(std::make_pair(ArgReg, Val));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy remainder of byval arg to it with memcpy.
|
||||
unsigned MemCpySize = ByValSize - Offset;
|
||||
SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
|
||||
DAG.getConstant(Offset, PtrTy));
|
||||
SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr,
|
||||
DAG.getIntPtrConstant(ByVal.Address));
|
||||
Chain = DAG.getMemcpy(Chain, DL, Dst, Src,
|
||||
DAG.getConstant(MemCpySize, PtrTy), Alignment,
|
||||
/*isVolatile=*/false, /*AlwaysInline=*/false,
|
||||
MachinePointerInfo(0), MachinePointerInfo(0));
|
||||
MemOpChains.push_back(Chain);
|
||||
}
|
||||
|
@ -287,6 +287,14 @@ namespace llvm {
|
||||
const Argument *FuncArg,
|
||||
const MipsCC &CC, const ByValArgInfo &ByVal) const;
|
||||
|
||||
/// passByValArg - Pass a byval argument in registers or on stack.
|
||||
void passByValArg(SDValue Chain, DebugLoc DL,
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass,
|
||||
SmallVector<SDValue, 8> &MemOpChains, SDValue StackPtr,
|
||||
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
|
||||
const MipsCC &CC, const ByValArgInfo &ByVal,
|
||||
const ISD::ArgFlagsTy &Flags, bool isLittle) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerFormalArguments(SDValue Chain,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
|
Loading…
Reference in New Issue
Block a user