mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Resolve bug 2947: vararg-marked functions must spill registers R3-R79 to stack
so that va_start/va_arg/et.al. will walk arguments correctly for Cell SPU. N.B.: Because neither clang nor llvm-gcc-4.2 can be built for CellSPU, this is still unexorcised code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58415 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a872aae731
commit
d976c21241
@ -188,8 +188,10 @@ namespace {
|
|||||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||||
assert(MO.isImm() &&
|
assert(MO.isImm() &&
|
||||||
"printMemRegImmS10 first operand is not immedate");
|
"printMemRegImmS10 first operand is not immedate");
|
||||||
printS10ImmOperand(MI, OpNo);
|
int64_t value = int64_t(MI->getOperand(OpNo).getImm());
|
||||||
O << "(";
|
assert((value >= -(1 << (9+4)) && value <= (1 << (9+4)) - 1)
|
||||||
|
&& "Invalid dform s10 offset argument");
|
||||||
|
O << value << "(";
|
||||||
printOperand(MI, OpNo+1);
|
printOperand(MI, OpNo+1);
|
||||||
O << ")";
|
O << ")";
|
||||||
}
|
}
|
||||||
|
@ -460,10 +460,7 @@ SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
|
|||||||
|
|
||||||
MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
|
MVT SPUTargetLowering::getSetCCResultType(const SDValue &Op) const {
|
||||||
MVT VT = Op.getValueType();
|
MVT VT = Op.getValueType();
|
||||||
if (VT.isInteger())
|
return (VT.isInteger() ? VT : MVT(MVT::i32));
|
||||||
return VT;
|
|
||||||
else
|
|
||||||
return MVT::i32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -926,7 +923,7 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
|
|||||||
MachineFunction &MF = DAG.getMachineFunction();
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
||||||
SmallVector<SDValue, 8> ArgValues;
|
SmallVector<SDValue, 48> ArgValues;
|
||||||
SDValue Root = Op.getOperand(0);
|
SDValue Root = Op.getOperand(0);
|
||||||
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
|
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
|
||||||
|
|
||||||
@ -942,98 +939,57 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
|
|||||||
// Add DAG nodes to load the arguments or copy them out of registers.
|
// Add DAG nodes to load the arguments or copy them out of registers.
|
||||||
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
|
for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1;
|
||||||
ArgNo != e; ++ArgNo) {
|
ArgNo != e; ++ArgNo) {
|
||||||
SDValue ArgVal;
|
|
||||||
bool needsLoad = false;
|
|
||||||
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
|
MVT ObjectVT = Op.getValue(ArgNo).getValueType();
|
||||||
unsigned ObjSize = ObjectVT.getSizeInBits()/8;
|
unsigned ObjSize = ObjectVT.getSizeInBits()/8;
|
||||||
|
SDValue ArgVal;
|
||||||
|
|
||||||
switch (ObjectVT.getSimpleVT()) {
|
if (ArgRegIdx < NumArgRegs) {
|
||||||
default: {
|
const TargetRegisterClass *ArgRegClass;
|
||||||
cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
|
|
||||||
<< ObjectVT.getMVTString()
|
|
||||||
<< "\n";
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
case MVT::i8:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R8CRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i8);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::i16:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i16);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::i32:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::i64:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64CRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::f32:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32FPRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f32);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::f64:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::R64FPRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::f64);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MVT::v2f64:
|
|
||||||
case MVT::v4f32:
|
|
||||||
case MVT::v2i64:
|
|
||||||
case MVT::v4i32:
|
|
||||||
case MVT::v8i16:
|
|
||||||
case MVT::v16i8:
|
|
||||||
if (!isVarArg && ArgRegIdx < NumArgRegs) {
|
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::VECREGRegClass);
|
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
|
||||||
ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
|
|
||||||
++ArgRegIdx;
|
|
||||||
} else {
|
|
||||||
needsLoad = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to load the argument to a virtual register if we determined above
|
switch (ObjectVT.getSimpleVT()) {
|
||||||
// that we ran out of physical registers of the appropriate type
|
default: {
|
||||||
if (needsLoad) {
|
cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
|
||||||
|
<< ObjectVT.getMVTString()
|
||||||
|
<< "\n";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
case MVT::i8:
|
||||||
|
ArgRegClass = &SPU::R8CRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::i16:
|
||||||
|
ArgRegClass = &SPU::R16CRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::i32:
|
||||||
|
ArgRegClass = &SPU::R32CRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::i64:
|
||||||
|
ArgRegClass = &SPU::R64CRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::f32:
|
||||||
|
ArgRegClass = &SPU::R32FPRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::f64:
|
||||||
|
ArgRegClass = &SPU::R64FPRegClass;
|
||||||
|
break;
|
||||||
|
case MVT::v2f64:
|
||||||
|
case MVT::v4f32:
|
||||||
|
case MVT::v2i64:
|
||||||
|
case MVT::v4i32:
|
||||||
|
case MVT::v8i16:
|
||||||
|
case MVT::v16i8:
|
||||||
|
ArgRegClass = &SPU::VECREGRegClass;
|
||||||
|
++ArgRegIdx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
|
||||||
|
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
||||||
|
ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
|
||||||
|
++ArgRegIdx;
|
||||||
|
} else {
|
||||||
|
// We need to load the argument to a virtual register if we determined
|
||||||
|
// above that we ran out of physical registers of the appropriate type
|
||||||
|
// or we're forced to do vararg
|
||||||
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
|
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
|
||||||
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
|
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
|
||||||
ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
|
ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
|
||||||
@ -1041,30 +997,31 @@ LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG, int &VarArgsFrameIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArgValues.push_back(ArgVal);
|
ArgValues.push_back(ArgVal);
|
||||||
|
// Update the chain
|
||||||
|
Root = ArgVal.getOperand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the function takes variable number of arguments, make a frame index for
|
// vararg handling:
|
||||||
// the start of the first vararg value... for expansion of llvm.va_start.
|
|
||||||
if (isVarArg) {
|
if (isVarArg) {
|
||||||
VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8,
|
// unsigned int ptr_size = PtrVT.getSizeInBits() / 8;
|
||||||
ArgOffset);
|
// We will spill (79-3)+1 registers to the stack
|
||||||
SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
|
SmallVector<SDValue, 79-3+1> MemOps;
|
||||||
// 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
|
// Create the frame slot
|
||||||
// result of va_next.
|
|
||||||
SmallVector<SDValue, 8> MemOps;
|
|
||||||
for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
|
for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
|
||||||
unsigned VReg = RegInfo.createVirtualRegister(&SPU::GPRCRegClass);
|
VarArgsFrameIndex = MFI->CreateFixedObject(StackSlotSize, ArgOffset);
|
||||||
RegInfo.addLiveIn(ArgRegs[ArgRegIdx], VReg);
|
SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
|
||||||
SDValue Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
|
SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8);
|
||||||
SDValue Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
|
SDValue Store = DAG.getStore(Root, ArgVal, FIN, NULL, 0);
|
||||||
|
Root = Store.getOperand(0);
|
||||||
MemOps.push_back(Store);
|
MemOps.push_back(Store);
|
||||||
// Increment the address by four for the next argument to store
|
|
||||||
SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT);
|
// Increment address by stack slot size for the next stored argument
|
||||||
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
|
ArgOffset += StackSlotSize;
|
||||||
}
|
}
|
||||||
if (!MemOps.empty())
|
if (!MemOps.empty())
|
||||||
Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
|
Root = DAG.getNode(ISD::TokenFactor,MVT::Other,&MemOps[0],MemOps.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgValues.push_back(Root);
|
ArgValues.push_back(Root);
|
||||||
@ -1093,10 +1050,6 @@ SDValue
|
|||||||
LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
LowerCALL(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
|
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
|
||||||
SDValue Chain = TheCall->getChain();
|
SDValue Chain = TheCall->getChain();
|
||||||
#if 0
|
|
||||||
bool isVarArg = TheCall->isVarArg();
|
|
||||||
bool isTailCall = TheCall->isTailCall();
|
|
||||||
#endif
|
|
||||||
SDValue Callee = TheCall->getCallee();
|
SDValue Callee = TheCall->getCallee();
|
||||||
unsigned NumOps = TheCall->getNumArgs();
|
unsigned NumOps = TheCall->getNumArgs();
|
||||||
unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
|
unsigned StackSlotSize = SPUFrameInfo::stackSlotSize();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
||||||
; RUN: grep brsl %t1.s | count 1
|
; RUN: grep brsl %t1.s | count 1
|
||||||
; RUN: grep brasl %t1.s | count 1
|
; RUN: grep brasl %t1.s | count 1
|
||||||
|
; RUN: grep stqd %t1.s | count 81
|
||||||
|
|
||||||
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
||||||
target triple = "spu"
|
target triple = "spu"
|
||||||
@ -18,3 +19,10 @@ define i32 @stub_1(i32 %x, float %y) {
|
|||||||
entry:
|
entry:
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; vararg call: ensure that all caller-saved registers are spilled to the
|
||||||
|
; stack:
|
||||||
|
define i32 @stub_2(...) {
|
||||||
|
entry:
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user