1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

SPARC backend fix: correctly passing arguments through stack

llvm-svn: 122626
This commit is contained in:
Venkatraman Govindaraju 2010-12-29 05:37:15 +00:00
parent 292870da06
commit 1f9ecea940

View File

@ -365,20 +365,24 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
SDValue Val = OutVals[i]; SDValue Val = OutVals[i];
EVT ObjectVT = Outs[i].VT; EVT ObjectVT = Outs[i].VT;
SDValue ValToStore(0, 0); SDValue ValToStore(0, 0);
unsigned ObjSize; SDValue ValToStore2(0, 0);
unsigned ArgOffset1 = 0, ArgOffset2 = 0;
switch (ObjectVT.getSimpleVT().SimpleTy) { switch (ObjectVT.getSimpleVT().SimpleTy) {
default: llvm_unreachable("Unhandled argument type!"); default: llvm_unreachable("Unhandled argument type!");
case MVT::i32: case MVT::i32:
ObjSize = 4; ArgOffset1 = ArgOffset;
ArgOffset += 4;
if (RegsToPass.size() >= 6) { if (RegsToPass.size() >= 6) {
ValToStore = Val; ValToStore = Val;
} else { } else {
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val)); RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val));
} }
break; break;
case MVT::f32: case MVT::f32:
ObjSize = 4; ArgOffset1 = ArgOffset;
ArgOffset += 4;
if (RegsToPass.size() >= 6) { if (RegsToPass.size() >= 6) {
ValToStore = Val; ValToStore = Val;
} else { } else {
@ -388,14 +392,17 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
} }
break; break;
case MVT::f64: { case MVT::f64: {
ObjSize = 8;
if (RegsToPass.size() >= 6) {
ValToStore = Val; // Whole thing is passed in memory.
break;
}
if (RegsToPass.size() >= 6) {
if (ArgOffset % 8 == 0) {
ArgOffset1 = ArgOffset;
ArgOffset += 8;
ValToStore = Val; // Whole thing is passed in memory.
break;
}
}
// Break into top and bottom parts by storing to the stack and loading // Break into top and bottom parts by storing to the stack and loading
// out the parts as integers. Top part goes in a reg. // out the parts as integers.
SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32); SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32);
SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
Val, StackPtr, MachinePointerInfo(), Val, StackPtr, MachinePointerInfo(),
@ -410,22 +417,31 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr,
MachinePointerInfo(), false, false, 0); MachinePointerInfo(), false, false, 0);
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
if (RegsToPass.size() >= 6) { if (RegsToPass.size() >= 6) {
ValToStore = Lo; ArgOffset1 = ArgOffset;
ArgOffset += 4; ValToStore = Hi;
ObjSize = 4; } else {
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
}
ArgOffset += 4;
if (RegsToPass.size() >= 6) {
ArgOffset2 = ArgOffset;
ValToStore2 = Lo;
} else { } else {
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
} }
ArgOffset += 4;
break; break;
} }
case MVT::i64: { case MVT::i64: {
ObjSize = 8;
if (RegsToPass.size() >= 6) { if (RegsToPass.size() >= 6) {
ValToStore = Val; // Whole thing is passed in memory. if (ArgOffset % 8 == 0) {
break; ArgOffset1 = ArgOffset;
ArgOffset += 8;
ValToStore = Val; // Whole thing is passed in memory.
break;
}
} }
// Split the value into top and bottom part. Top part goes in a reg. // Split the value into top and bottom part. Top part goes in a reg.
@ -433,28 +449,40 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
DAG.getConstant(1, MVT::i32)); DAG.getConstant(1, MVT::i32));
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val, SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val,
DAG.getConstant(0, MVT::i32)); DAG.getConstant(0, MVT::i32));
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
if (RegsToPass.size() >= 6) { if (RegsToPass.size() >= 6) {
ValToStore = Lo; ArgOffset1 = ArgOffset;
ArgOffset += 4; ValToStore = Hi;
ObjSize = 4; } else {
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
}
ArgOffset += 4;
if (RegsToPass.size() >= 6) {
ArgOffset2 = ArgOffset;
ValToStore2 = Lo;
} else { } else {
RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
} }
ArgOffset += 4;
break; break;
} }
} }
if (ValToStore.getNode()) { if (ValToStore.getNode()) {
SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
SDValue PtrOff = DAG.getConstant(ArgOffset, MVT::i32); SDValue PtrOff = DAG.getConstant(ArgOffset1, MVT::i32);
PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore, MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore,
PtrOff, MachinePointerInfo(), PtrOff, MachinePointerInfo(),
false, false, 0)); false, false, 0));
} }
ArgOffset += ObjSize; if (ValToStore2.getNode()) {
SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
SDValue PtrOff = DAG.getConstant(ArgOffset2, MVT::i32);
PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore2,
PtrOff, MachinePointerInfo(),
false, false, 0));
}
} }
#endif #endif