aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Sparc
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-02-04 08:31:30 +0000
committerChris Lattner <sabre@nondot.org>2006-02-04 08:31:30 +0000
commitc275dfa72751dc22507c33488a639bda9874e274 (patch)
tree35fe026e1ac01d59049fe1878520a77cdafc81ad /lib/Target/Sparc
parentc4b612ba2a5d9ea400b5a585efba494726e372b3 (diff)
Custom lower VAARG for the case when we are doing vaarg(double). In this
case, the double being loaded may not be 8-byte aligned, so we have to use our standard bit_convert game. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25967 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Sparc')
-rw-r--r--lib/Target/Sparc/SparcISelDAGToDAG.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index c2741059b0..bd5073d897 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -203,11 +203,12 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET , MVT::Other, Custom);
- // VASTART needs to be custom lowered to use the VarArgsFrameIndex
+ // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
setOperationAction(ISD::VASTART , MVT::Other, Custom);
+ // VAARG needs to be lowered to not do unaligned accesses for doubles.
+ setOperationAction(ISD::VAARG , MVT::Other, Custom);
// Use the default implementation.
- setOperationAction(ISD::VAARG , MVT::Other, Expand);
setOperationAction(ISD::VACOPY , MVT::Other, Expand);
setOperationAction(ISD::VAEND , MVT::Other, Expand);
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
@@ -778,10 +779,41 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
// memory location argument.
SDOperand Offset = DAG.getNode(ISD::ADD, MVT::i32,
DAG.getRegister(V8::I6, MVT::i32),
- DAG.getConstant(VarArgsFrameOffset, MVT::i32));
+ DAG.getConstant(VarArgsFrameOffset, MVT::i32));
return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset,
Op.getOperand(1), Op.getOperand(2));
}
+ case ISD::VAARG: {
+ SDNode *Node = Op.Val;
+ MVT::ValueType VT = Node->getValueType(0);
+ SDOperand InChain = Node->getOperand(0);
+ SDOperand VAListPtr = Node->getOperand(1);
+ SDOperand VAList = DAG.getLoad(getPointerTy(), InChain, VAListPtr,
+ Node->getOperand(2));
+ // Increment the pointer, VAList, to the next vaarg
+ SDOperand NextPtr = DAG.getNode(ISD::ADD, getPointerTy(), VAList,
+ DAG.getConstant(MVT::getSizeInBits(VT)/8,
+ getPointerTy()));
+ // Store the incremented VAList to the legalized pointer
+ InChain = DAG.getNode(ISD::STORE, MVT::Other, VAList.getValue(1), NextPtr,
+ VAListPtr, Node->getOperand(2));
+ // Load the actual argument out of the pointer VAList, unless this is an
+ // f64 load.
+ if (VT != MVT::f64) {
+ return DAG.getLoad(VT, InChain, VAList, DAG.getSrcValue(0));
+ } else {
+ // Otherwise, load it as i64, then do a bitconvert.
+ SDOperand V = DAG.getLoad(MVT::i64, InChain, VAList, DAG.getSrcValue(0));
+ std::vector<MVT::ValueType> Tys;
+ Tys.push_back(MVT::f64);
+ Tys.push_back(MVT::Other);
+ std::vector<SDOperand> Ops;
+ // Bit-Convert the value to f64.
+ Ops.push_back(DAG.getNode(ISD::BIT_CONVERT, MVT::f64, V));
+ Ops.push_back(V.getValue(1));
+ return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
+ }
+ }
case ISD::RET: {
SDOperand Copy;