mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-28 15:33:16 +00:00
Improve PPC64 calling convention support
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28919 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
924c576e9f
commit
c91a4757b6
@ -733,8 +733,8 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
|
||||
Op.getOperand(1), Op.getOperand(2));
|
||||
}
|
||||
|
||||
static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
int &VarArgsFrameIndex) {
|
||||
static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
|
||||
int &VarArgsFrameIndex) {
|
||||
// TODO: add description of PPC stack frame format, or at least some docs.
|
||||
//
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
@ -748,10 +748,15 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
const unsigned Num_FPR_Regs = 13;
|
||||
const unsigned Num_VR_Regs = 12;
|
||||
unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
|
||||
static const unsigned GPR_32[] = { // 32-bit registers.
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
static const unsigned GPR_64[] = { // 64-bit registers.
|
||||
PPC::X3, PPC::X4, PPC::X5, PPC::X6,
|
||||
PPC::X7, PPC::X8, PPC::X9, PPC::X10,
|
||||
};
|
||||
static const unsigned FPR[] = {
|
||||
PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
|
||||
PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
|
||||
@ -760,6 +765,10 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
|
||||
PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
|
||||
};
|
||||
|
||||
MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
|
||||
bool isPPC64 = PtrVT == MVT::i64;
|
||||
const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32;
|
||||
|
||||
// Add DAG nodes to load the arguments or copy them out of registers. On
|
||||
// entry to a function on PPC, the arguments start at offset 24, although the
|
||||
@ -771,12 +780,11 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
|
||||
|
||||
unsigned CurArgOffset = ArgOffset;
|
||||
|
||||
switch (ObjectVT) {
|
||||
default: assert(0 && "Unhandled argument type!");
|
||||
case MVT::i32:
|
||||
// All int arguments reserve stack space.
|
||||
ArgOffset += 4;
|
||||
ArgOffset += isPPC64 ? 8 : 4;
|
||||
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
|
||||
@ -787,6 +795,19 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
needsLoad = true;
|
||||
}
|
||||
break;
|
||||
case MVT::i64: // PPC64
|
||||
// All int arguments reserve stack space.
|
||||
ArgOffset += 8;
|
||||
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = RegMap->createVirtualRegister(&PPC::G8RCRegClass);
|
||||
MF.addLiveIn(GPR[GPR_idx], VReg);
|
||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
|
||||
++GPR_idx;
|
||||
} else {
|
||||
needsLoad = true;
|
||||
}
|
||||
break;
|
||||
case MVT::f32:
|
||||
case MVT::f64:
|
||||
// All FP arguments reserve stack space.
|
||||
@ -838,7 +859,7 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
// slot.
|
||||
if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
|
||||
int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
|
||||
SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
|
||||
SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
|
||||
ArgVal = DAG.getLoad(ObjectVT, Root, FIN,
|
||||
DAG.getSrcValue(NULL));
|
||||
} else {
|
||||
@ -854,8 +875,9 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
// the start of the first vararg value... for expansion of llvm.va_start.
|
||||
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
|
||||
if (isVarArg) {
|
||||
VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
|
||||
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
|
||||
VarArgsFrameIndex = MFI->CreateFixedObject(MVT::getSizeInBits(PtrVT)/8,
|
||||
ArgOffset);
|
||||
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
|
||||
// If this function is vararg, store any remaining integer argument regs
|
||||
// to their spots on the stack so that they may be loaded by deferencing the
|
||||
// result of va_next.
|
||||
@ -863,13 +885,13 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) {
|
||||
unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
|
||||
MF.addLiveIn(GPR[GPR_idx], VReg);
|
||||
SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
|
||||
SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
|
||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
|
||||
Val, FIN, DAG.getSrcValue(NULL));
|
||||
MemOps.push_back(Store);
|
||||
// Increment the address by four for the next argument to store
|
||||
SDOperand PtrOff = DAG.getConstant(4, MVT::i32);
|
||||
FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff);
|
||||
SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8, PtrVT);
|
||||
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
|
||||
}
|
||||
if (!MemOps.empty())
|
||||
Root = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps);
|
||||
@ -883,11 +905,6 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG,
|
||||
return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
|
||||
}
|
||||
|
||||
static SDOperand LowerFORMAL_ARGUMENTS_64(SDOperand Op, SelectionDAG &DAG,
|
||||
int &VarArgsFrameIndex) {
|
||||
return LowerFORMAL_ARGUMENTS_32(Op, DAG, VarArgsFrameIndex);
|
||||
}
|
||||
|
||||
/// isCallCompatibleAddress - Return the immediate to use if the specified
|
||||
/// 32-bit value is representable in the immediate field of a BxA instruction.
|
||||
static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) {
|
||||
@ -911,14 +928,19 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
SDOperand Callee = Op.getOperand(4);
|
||||
unsigned NumOps = (Op.getNumOperands() - 5) / 2;
|
||||
|
||||
MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
|
||||
bool isPPC64 = PtrVT == MVT::i64;
|
||||
unsigned PtrByteSize = isPPC64 ? 8 : 4;
|
||||
|
||||
|
||||
// args_to_use will accumulate outgoing args for the PPCISD::CALL case in
|
||||
// SelectExpr to use to put the arguments in the appropriate registers.
|
||||
std::vector<SDOperand> args_to_use;
|
||||
|
||||
// Count how many bytes are to be pushed on the stack, including the linkage
|
||||
// area, and parameter passing area. We start with 24 bytes, which is
|
||||
// area, and parameter passing area. We start with 24/48 bytes, which is
|
||||
// prereserved space for [SP][CR][LR][3 x unused].
|
||||
unsigned NumBytes = 24;
|
||||
unsigned NumBytes = 6*PtrByteSize;
|
||||
|
||||
// Add up all the space actually used.
|
||||
for (unsigned i = 0; i != NumOps; ++i)
|
||||
@ -929,29 +951,37 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
// Because we cannot tell if this is needed on the caller side, we have to
|
||||
// conservatively assume that it is needed. As such, make sure we have at
|
||||
// least enough stack space for the caller to store the 8 GPRs.
|
||||
if (NumBytes < 24+8*4)
|
||||
NumBytes = 24+8*4;
|
||||
if (NumBytes < 6*PtrByteSize+8*PtrByteSize)
|
||||
NumBytes = 6*PtrByteSize+8*PtrByteSize;
|
||||
|
||||
// Adjust the stack pointer for the new arguments...
|
||||
// These operations are automatically eliminated by the prolog/epilog pass
|
||||
Chain = DAG.getCALLSEQ_START(Chain,
|
||||
DAG.getConstant(NumBytes, MVT::i32));
|
||||
DAG.getConstant(NumBytes, PtrVT));
|
||||
|
||||
// Set up a copy of the stack pointer for use loading and storing any
|
||||
// arguments that may not fit in the registers available for argument
|
||||
// passing.
|
||||
SDOperand StackPtr = DAG.getRegister(PPC::R1, MVT::i32);
|
||||
SDOperand StackPtr;
|
||||
if (isPPC64)
|
||||
StackPtr = DAG.getRegister(PPC::X1, MVT::i64);
|
||||
else
|
||||
StackPtr = DAG.getRegister(PPC::R1, MVT::i32);
|
||||
|
||||
// Figure out which arguments are going to go in registers, and which in
|
||||
// memory. Also, if this is a vararg function, floating point operations
|
||||
// must be stored to our stack, and loaded into integer regs as well, if
|
||||
// any integer regs are available for argument passing.
|
||||
unsigned ArgOffset = 24;
|
||||
unsigned ArgOffset = 6*PtrByteSize;
|
||||
unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
static const unsigned GPR_32[] = { // 32-bit registers.
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
static const unsigned GPR_64[] = { // 64-bit registers.
|
||||
PPC::X3, PPC::X4, PPC::X5, PPC::X6,
|
||||
PPC::X7, PPC::X8, PPC::X9, PPC::X10,
|
||||
};
|
||||
static const unsigned FPR[] = {
|
||||
PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
|
||||
PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
|
||||
@ -960,10 +990,12 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
|
||||
PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
|
||||
};
|
||||
const unsigned NumGPRs = sizeof(GPR)/sizeof(GPR[0]);
|
||||
const unsigned NumGPRs = sizeof(GPR_32)/sizeof(GPR_32[0]);
|
||||
const unsigned NumFPRs = sizeof(FPR)/sizeof(FPR[0]);
|
||||
const unsigned NumVRs = sizeof( VR)/sizeof( VR[0]);
|
||||
|
||||
const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32;
|
||||
|
||||
std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
|
||||
std::vector<SDOperand> MemOpChains;
|
||||
for (unsigned i = 0; i != NumOps; ++i) {
|
||||
@ -972,17 +1004,27 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
// PtrOff will be used to store the current argument to the stack if a
|
||||
// register cannot be found for it.
|
||||
SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
|
||||
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
|
||||
PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff);
|
||||
|
||||
// On PPC64, promote integers to 64-bit values.
|
||||
if (isPPC64 && Arg.getValueType() == MVT::i32) {
|
||||
unsigned ExtOp = ISD::ZERO_EXTEND;
|
||||
if (cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue())
|
||||
ExtOp = ISD::SIGN_EXTEND;
|
||||
Arg = DAG.getNode(ExtOp, MVT::i64, Arg);
|
||||
}
|
||||
|
||||
switch (Arg.getValueType()) {
|
||||
default: assert(0 && "Unexpected ValueType for argument!");
|
||||
case MVT::i32:
|
||||
case MVT::i64:
|
||||
if (GPR_idx != NumGPRs) {
|
||||
RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg));
|
||||
} else {
|
||||
MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
|
||||
Arg, PtrOff, DAG.getSrcValue(NULL)));
|
||||
}
|
||||
ArgOffset += 4;
|
||||
ArgOffset += PtrByteSize;
|
||||
break;
|
||||
case MVT::f32:
|
||||
case MVT::f64:
|
||||
@ -997,15 +1039,15 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
|
||||
// Float varargs are always shadowed in available integer registers
|
||||
if (GPR_idx != NumGPRs) {
|
||||
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff,
|
||||
SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff,
|
||||
DAG.getSrcValue(NULL));
|
||||
MemOpChains.push_back(Load.getValue(1));
|
||||
RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
|
||||
}
|
||||
if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64) {
|
||||
SDOperand ConstFour = DAG.getConstant(4, PtrOff.getValueType());
|
||||
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
|
||||
SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff,
|
||||
PtrOff = DAG.getNode(ISD::ADD, PtrVT, PtrOff, ConstFour);
|
||||
SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff,
|
||||
DAG.getSrcValue(NULL));
|
||||
MemOpChains.push_back(Load.getValue(1));
|
||||
RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
|
||||
@ -1016,14 +1058,17 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
// GPRs.
|
||||
if (GPR_idx != NumGPRs)
|
||||
++GPR_idx;
|
||||
if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64)
|
||||
if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64)
|
||||
++GPR_idx;
|
||||
}
|
||||
} else {
|
||||
MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
|
||||
Arg, PtrOff, DAG.getSrcValue(NULL)));
|
||||
}
|
||||
ArgOffset += (Arg.getValueType() == MVT::f32) ? 4 : 8;
|
||||
if (isPPC64)
|
||||
ArgOffset += 8;
|
||||
else
|
||||
ArgOffset += Arg.getValueType() == MVT::f32 ? 4 : 8;
|
||||
break;
|
||||
case MVT::v4f32:
|
||||
case MVT::v4i32:
|
||||
@ -1127,6 +1172,11 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
}
|
||||
NodeTys.push_back(MVT::i32);
|
||||
break;
|
||||
case MVT::i64:
|
||||
Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1);
|
||||
ResultVals.push_back(Chain.getValue(0));
|
||||
NodeTys.push_back(MVT::i64);
|
||||
break;
|
||||
case MVT::f32:
|
||||
case MVT::f64:
|
||||
Chain = DAG.getCopyFromReg(Chain, PPC::F1, Op.Val->getValueType(0),
|
||||
@ -1146,7 +1196,7 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
}
|
||||
|
||||
Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
|
||||
DAG.getConstant(NumBytes, MVT::i32));
|
||||
DAG.getConstant(NumBytes, PtrVT));
|
||||
NodeTys.push_back(MVT::Other);
|
||||
|
||||
// If the function returns void, just return the chain.
|
||||
@ -2136,10 +2186,7 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
case ISD::SETCC: return LowerSETCC(Op, DAG);
|
||||
case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex);
|
||||
case ISD::FORMAL_ARGUMENTS:
|
||||
if (getPointerTy() == MVT::i32)
|
||||
return LowerFORMAL_ARGUMENTS_32(Op, DAG, VarArgsFrameIndex);
|
||||
else
|
||||
return LowerFORMAL_ARGUMENTS_64(Op, DAG, VarArgsFrameIndex);
|
||||
return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
|
||||
case ISD::CALL: return LowerCALL(Op, DAG);
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user