mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-02 07:41:38 +00:00
Next bits of PPC byval handling. Basically functional
but there are bugs. llvm-svn: 48028
This commit is contained in:
parent
08ec4919ea
commit
3e6bacf7be
@ -1347,6 +1347,8 @@ SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
// represented with two words (long long or double) must be copied to an
|
// represented with two words (long long or double) must be copied to an
|
||||||
// even GPR_idx value or to an even ArgOffset value.
|
// even GPR_idx value or to an even ArgOffset value.
|
||||||
|
|
||||||
|
SmallVector<SDOperand, 8> MemOps;
|
||||||
|
|
||||||
for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
|
for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
|
||||||
SDOperand ArgVal;
|
SDOperand ArgVal;
|
||||||
bool needsLoad = false;
|
bool needsLoad = false;
|
||||||
@ -1355,12 +1357,50 @@ SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
unsigned ArgSize = ObjSize;
|
unsigned ArgSize = ObjSize;
|
||||||
unsigned Flags = cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
|
unsigned Flags = cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
|
||||||
unsigned AlignFlag = 1 << ISD::ParamFlags::OrigAlignmentOffs;
|
unsigned AlignFlag = 1 << ISD::ParamFlags::OrigAlignmentOffs;
|
||||||
|
unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
|
||||||
// See if next argument requires stack alignment in ELF
|
// See if next argument requires stack alignment in ELF
|
||||||
bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
|
bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
|
||||||
(cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) &&
|
(cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) &&
|
||||||
(!(Flags & AlignFlag)));
|
(!(Flags & AlignFlag)));
|
||||||
|
|
||||||
unsigned CurArgOffset = ArgOffset;
|
unsigned CurArgOffset = ArgOffset;
|
||||||
|
|
||||||
|
// FIXME alignment for ELF may not be right
|
||||||
|
// FIXME the codegen can be much improved in some cases.
|
||||||
|
// We do not have to keep everything in memory.
|
||||||
|
if (isByVal) {
|
||||||
|
// Double word align in ELF
|
||||||
|
if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
|
||||||
|
// ObjSize is the true size, ArgSize rounded up to multiple of registers.
|
||||||
|
ObjSize = (Flags & ISD::ParamFlags::ByValSize) >>
|
||||||
|
ISD::ParamFlags::ByValSizeOffs;
|
||||||
|
ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
|
||||||
|
// The value of the object is its address.
|
||||||
|
int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
|
||||||
|
SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
|
||||||
|
ArgValues.push_back(FIN);
|
||||||
|
for (unsigned j = 0; j < ArgSize; j += PtrByteSize) {
|
||||||
|
// Store whatever pieces of the object are in registers
|
||||||
|
// to memory. ArgVal will be address of the beginning of
|
||||||
|
// the object.
|
||||||
|
if (GPR_idx != Num_GPR_Regs) {
|
||||||
|
unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
|
||||||
|
RegInfo.addLiveIn(GPR[GPR_idx], VReg);
|
||||||
|
int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset);
|
||||||
|
SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
|
||||||
|
SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
|
||||||
|
SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
|
||||||
|
MemOps.push_back(Store);
|
||||||
|
++GPR_idx;
|
||||||
|
if (isMachoABI) ArgOffset += PtrByteSize;
|
||||||
|
} else {
|
||||||
|
ArgOffset += ArgSize - (ArgOffset-CurArgOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ObjectVT) {
|
switch (ObjectVT) {
|
||||||
default: assert(0 && "Unhandled argument type!");
|
default: assert(0 && "Unhandled argument type!");
|
||||||
case MVT::i32:
|
case MVT::i32:
|
||||||
@ -1453,7 +1493,7 @@ SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
|
|
||||||
ArgValues.push_back(ArgVal);
|
ArgValues.push_back(ArgVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the function takes variable number of arguments, make a frame index for
|
// If the function takes variable number of arguments, make a frame index for
|
||||||
// the start of the first vararg value... for expansion of llvm.va_start.
|
// the start of the first vararg value... for expansion of llvm.va_start.
|
||||||
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
|
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
|
||||||
@ -1481,8 +1521,6 @@ SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
depth);
|
depth);
|
||||||
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
|
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
|
||||||
|
|
||||||
SmallVector<SDOperand, 8> MemOps;
|
|
||||||
|
|
||||||
// In ELF 32 ABI, the fixed integer arguments of a variadic function are
|
// In ELF 32 ABI, the fixed integer arguments of a variadic function are
|
||||||
// stored to the VarArgsFrameIndex on the stack.
|
// stored to the VarArgsFrameIndex on the stack.
|
||||||
if (isELF32_ABI) {
|
if (isELF32_ABI) {
|
||||||
@ -1542,11 +1580,11 @@ SDOperand PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
|
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MemOps.empty())
|
|
||||||
Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MemOps.empty())
|
||||||
|
Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
|
||||||
|
|
||||||
ArgValues.push_back(Root);
|
ArgValues.push_back(Root);
|
||||||
|
|
||||||
// Return the new list of results.
|
// Return the new list of results.
|
||||||
@ -1705,10 +1743,37 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME Elf untested, what are alignment rules?
|
// FIXME Elf untested, what are alignment rules?
|
||||||
|
// FIXME memcpy is used way more than necessary. Correctness first.
|
||||||
if (Flags & ISD::ParamFlags::ByVal) {
|
if (Flags & ISD::ParamFlags::ByVal) {
|
||||||
unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
|
unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
|
||||||
ISD::ParamFlags::ByValSizeOffs;
|
ISD::ParamFlags::ByValSizeOffs;
|
||||||
if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2);
|
if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2);
|
||||||
|
if (Size==1 || Size==2) {
|
||||||
|
// Very small objects are passed right-justified.
|
||||||
|
// Everything else is passed left-justified.
|
||||||
|
MVT::ValueType VT = (Size==1) ? MVT::i8 : MVT::i16;
|
||||||
|
if (GPR_idx != NumGPRs) {
|
||||||
|
SDOperand Load = DAG.getExtLoad(ISD::EXTLOAD, PtrVT, Chain, Arg,
|
||||||
|
NULL, 0, VT);
|
||||||
|
MemOpChains.push_back(Load.getValue(1));
|
||||||
|
RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
|
||||||
|
if (isMachoABI)
|
||||||
|
ArgOffset += PtrByteSize;
|
||||||
|
} else {
|
||||||
|
SDOperand Const = DAG.getConstant(4 - Size, PtrOff.getValueType());
|
||||||
|
SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
|
||||||
|
SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr,
|
||||||
|
CallSeqStart.Val->getOperand(0),
|
||||||
|
Flags, DAG, Size);
|
||||||
|
// This must go outside the CALLSEQ_START..END.
|
||||||
|
SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
|
||||||
|
CallSeqStart.Val->getOperand(1));
|
||||||
|
DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
|
||||||
|
Chain = CallSeqStart = NewCallSeqStart;
|
||||||
|
ArgOffset += PtrByteSize;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (unsigned j=0; j<Size; j+=PtrByteSize) {
|
for (unsigned j=0; j<Size; j+=PtrByteSize) {
|
||||||
SDOperand Const = DAG.getConstant(j, PtrOff.getValueType());
|
SDOperand Const = DAG.getConstant(j, PtrOff.getValueType());
|
||||||
SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const);
|
SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const);
|
||||||
@ -1727,8 +1792,9 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
|
|||||||
SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
|
SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
|
||||||
CallSeqStart.Val->getOperand(1));
|
CallSeqStart.Val->getOperand(1));
|
||||||
DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
|
DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
|
||||||
CallSeqStart = NewCallSeqStart;
|
Chain = CallSeqStart = NewCallSeqStart;
|
||||||
ArgOffset += ((Size - j + 3)/4)*4;
|
ArgOffset += ((Size - j + 3)/4)*4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user