diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2010-12-29 05:37:15 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2010-12-29 05:37:15 +0000 |
commit | 12db7b68b683371a6ae464e76b4c850fa0199eeb (patch) | |
tree | 9053ce53d3d0db8ebb8746dbb5082079c518fba2 /lib/Target | |
parent | 7fb95d4235ad588d4105544b2ae3fa1aa0eba3b1 (diff) | |
download | external_llvm-12db7b68b683371a6ae464e76b4c850fa0199eeb.zip external_llvm-12db7b68b683371a6ae464e76b4c850fa0199eeb.tar.gz external_llvm-12db7b68b683371a6ae464e76b4c850fa0199eeb.tar.bz2 |
SPARC backend fix: correctly passing arguments through stack
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122626 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index cfea8b9..27e78f0 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -365,20 +365,24 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue Val = OutVals[i]; EVT ObjectVT = Outs[i].VT; SDValue ValToStore(0, 0); - unsigned ObjSize; + SDValue ValToStore2(0, 0); + unsigned ArgOffset1 = 0, ArgOffset2 = 0; switch (ObjectVT.getSimpleVT().SimpleTy) { default: llvm_unreachable("Unhandled argument type!"); case MVT::i32: - ObjSize = 4; + ArgOffset1 = ArgOffset; + ArgOffset += 4; if (RegsToPass.size() >= 6) { ValToStore = Val; } else { RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val)); } + break; case MVT::f32: - ObjSize = 4; + ArgOffset1 = ArgOffset; + ArgOffset += 4; if (RegsToPass.size() >= 6) { ValToStore = Val; } else { @@ -388,14 +392,17 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, } break; case MVT::f64: { - ObjSize = 8; + if (RegsToPass.size() >= 6) { - ValToStore = Val; // Whole thing is passed in memory. - break; + 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 - // 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 Store = DAG.getStore(DAG.getEntryNode(), dl, Val, StackPtr, MachinePointerInfo(), @@ -410,22 +417,31 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, MachinePointerInfo(), false, false, 0); - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); - if (RegsToPass.size() >= 6) { - ValToStore = Lo; - ArgOffset += 4; - ObjSize = 4; + ArgOffset1 = ArgOffset; + ValToStore = Hi; + } else { + RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); + } + ArgOffset += 4; + if (RegsToPass.size() >= 6) { + ArgOffset2 = ArgOffset; + ValToStore2 = Lo; } else { RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); } + ArgOffset += 4; break; } case MVT::i64: { - ObjSize = 8; + if (RegsToPass.size() >= 6) { - ValToStore = Val; // Whole thing is passed in memory. - break; + if (ArgOffset % 8 == 0) { + 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. @@ -433,28 +449,40 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, DAG.getConstant(1, MVT::i32)); SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val, DAG.getConstant(0, MVT::i32)); - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); - if (RegsToPass.size() >= 6) { - ValToStore = Lo; - ArgOffset += 4; - ObjSize = 4; + ArgOffset1 = ArgOffset; + ValToStore = Hi; + } else { + RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); + } + ArgOffset += 4; + if (RegsToPass.size() >= 6) { + ArgOffset2 = ArgOffset; + ValToStore2 = Lo; } else { RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); } + ArgOffset += 4; break; } } if (ValToStore.getNode()) { 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); MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore, PtrOff, MachinePointerInfo(), 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 |