diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index b2524d5b710..d3837eb9c64 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -360,12 +360,6 @@ public: unsigned CallingConv, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) = 0; - /// LowerReturnTo - This hook lowers a return instruction into the appropriate - /// legal ISD::RET node for the target's current ABI. This method is optional - /// and is intended for targets that need non-standard behavior. - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); - /// LowerFrameReturnAddress - This hook lowers a call to llvm.returnaddress or /// llvm.frameaddress (depending on the value of the first argument). The /// return values are the result pointer and the resultant token chain. If diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 5f16af6571c..d6cdb32e1d2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -496,40 +496,30 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) { DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getRoot())); return; } + std::vector NewValues; + NewValues.push_back(getRoot()); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { + SDOperand RetOp = getValue(I.getOperand(i)); + + // If this is an integer return value, we need to promote it ourselves to + // the full width of a register, since LegalizeOp will use ANY_EXTEND rather + // than sign/zero. + if (MVT::isInteger(RetOp.getValueType()) && + RetOp.getValueType() < MVT::i64) { + MVT::ValueType TmpVT; + if (TLI.getTypeAction(MVT::i32) == TargetLowering::Promote) + TmpVT = TLI.getTypeToTransformTo(MVT::i32); + else + TmpVT = MVT::i32; - SDOperand Op1 = getValue(I.getOperand(0)); - MVT::ValueType TmpVT; - - switch (Op1.getValueType()) { - default: assert(0 && "Unknown value type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - // If this is a machine where 32-bits is legal or expanded, promote to - // 32-bits, otherwise, promote to 64-bits. - if (TLI.getTypeAction(MVT::i32) == TargetLowering::Promote) - TmpVT = TLI.getTypeToTransformTo(MVT::i32); - else - TmpVT = MVT::i32; - - // Extend integer types to result type. - if (I.getOperand(0)->getType()->isSigned()) - Op1 = DAG.getNode(ISD::SIGN_EXTEND, TmpVT, Op1); - else - Op1 = DAG.getNode(ISD::ZERO_EXTEND, TmpVT, Op1); - break; - case MVT::f32: - // If this is a machine where f32 is promoted to f64, do so now. - if (TLI.getTypeAction(MVT::f32) == TargetLowering::Promote) - Op1 = DAG.getNode(ISD::FP_EXTEND, TLI.getTypeToTransformTo(MVT::f32),Op1); - break; - case MVT::i64: - case MVT::f64: - break; // No extension needed! + if (I.getOperand(i)->getType()->isSigned()) + RetOp = DAG.getNode(ISD::SIGN_EXTEND, TmpVT, RetOp); + else + RetOp = DAG.getNode(ISD::ZERO_EXTEND, TmpVT, RetOp); + } + NewValues.push_back(RetOp); } - // Allow targets to lower this further to meet ABI requirements - DAG.setRoot(TLI.LowerReturnTo(getRoot(), Op1, DAG)); + DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, NewValues)); } void SelectionDAGLowering::visitBr(BranchInst &I) { @@ -1249,11 +1239,6 @@ MachineBasicBlock *TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, return 0; } -SDOperand TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - return DAG.getNode(ISD::RET, MVT::Other, Chain, Op); -} - void SelectionDAGLowering::visitVAStart(CallInst &I) { DAG.setRoot(DAG.getNode(ISD::VASTART, MVT::Other, getRoot(), getValue(I.getOperand(1)), diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp index b6cd9b08f7f..780cb08dd23 100644 --- a/lib/Target/IA64/IA64ISelLowering.cpp +++ b/lib/Target/IA64/IA64ISelLowering.cpp @@ -537,44 +537,6 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain, return std::make_pair(RetVal, Chain); } -SDOperand IA64TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - SDOperand Copy, InFlag; - SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR, - MVT::i64); - Chain = AR_PFSVal.getValue(1); - - switch (Op.getValueType()) { - default: assert(0 && "Unknown type to return! (promote?)"); - case MVT::i64: - Copy = DAG.getCopyToReg(Chain, IA64::r8, Op, InFlag); - break; - case MVT::f64: - Copy = DAG.getCopyToReg(Chain, IA64::F8, Op, InFlag); - break; - } - - Chain = Copy.getValue(0); - InFlag = Copy.getValue(1); - // we need to copy VirtGPR (the vreg (to become a real reg)) that holds - // the output of this function's alloc instruction back into ar.pfs - // before we return. this copy must not float up above the last - // outgoing call in this function - we flag this to the ret instruction - Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal, InFlag); - InFlag = Chain.getValue(1); - - // and then just emit a 'ret' instruction - std::vector NodeTys; - std::vector RetOperands; - NodeTys.push_back(MVT::Other); - NodeTys.push_back(MVT::Flag); - RetOperands.push_back(Chain); - RetOperands.push_back(InFlag); - - return DAG.getNode(IA64ISD::RET_FLAG, NodeTys, RetOperands); -// return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, MVT::Other, Copy, Chain, InFlag); -} - std::pair IA64TargetLowering:: LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, SelectionDAG &DAG) { @@ -586,21 +548,38 @@ SDOperand IA64TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); - case ISD::RET: { // the DAGgy stuff takes care of - // restoring ar.pfs before adding a br.ret for functions - // that return something, but we need to take care of stuff - // that returns void manually, so here it is: - assert(Op.getNumOperands()==1 && - "trying to custom lower a return other than void! (numops!=1)"); + case ISD::RET: { + SDOperand AR_PFSVal, Copy; - SDOperand Chain = Op.getOperand(0); - SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR, - MVT::i64); - Chain = AR_PFSVal.getValue(1); - Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal); + switch(Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); + AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), IA64::AR_PFS, + AR_PFSVal); + return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal); + case 2: { + // Copy the result into the output register & restore ar.pfs + MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); + unsigned ArgReg = MVT::isInteger(ArgVT) ? IA64::r8 : IA64::F8; - // and then just emit a 'ret' instruction - return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, Chain); + AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64); + Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), ArgReg, Op.getOperand(1), + SDOperand()); + AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), IA64::AR_PFS, AR_PFSVal, + Copy.getValue(1)); + std::vector NodeTys; + std::vector RetOperands; + NodeTys.push_back(MVT::Other); + NodeTys.push_back(MVT::Flag); + RetOperands.push_back(AR_PFSVal); + RetOperands.push_back(AR_PFSVal.getValue(1)); + return DAG.getNode(IA64ISD::RET_FLAG, NodeTys, RetOperands); + } + } + return SDOperand(); } case ISD::VAARG: { MVT::ValueType VT = getPointerTy(); diff --git a/lib/Target/IA64/IA64ISelLowering.h b/lib/Target/IA64/IA64ISelLowering.h index bd63be15721..704e3589301 100644 --- a/lib/Target/IA64/IA64ISelLowering.h +++ b/lib/Target/IA64/IA64ISelLowering.h @@ -48,10 +48,6 @@ namespace llvm { unsigned VirtGPR; // this is public so it can be accessed in the selector // for ISD::RET. add an accessor instead? FIXME - /// LowerOperation - Provide custom lowering hooks for some operations. - /// -// XXX virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); - const char *getTargetNodeName(unsigned Opcode) const; /// LowerArguments - This hook must be implemented to indicate how we should @@ -67,11 +63,6 @@ namespace llvm { bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); - /// LowerReturnTo - This spits out restore-previous-frame-state+br.ret - /// instructions - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); - /// LowerOperation - for custom lowering specific ops /// (currently, only "ret void") virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index b9949590a29..f1c1735c5ad 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -110,6 +110,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + // 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 setOperationAction(ISD::VASTART , MVT::Other, Custom); @@ -440,6 +443,30 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR, Op.getOperand(1), Op.getOperand(2)); } + case ISD::RET: { + SDOperand Copy; + + switch(Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return SDOperand(); // ret void is legal + case 2: { + MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); + unsigned ArgReg = MVT::isInteger(ArgVT) ? PPC::R3 : PPC::F1; + Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), + SDOperand()); + break; + } + case 3: + Copy = DAG.getCopyToReg(Op.getOperand(0), PPC::R3, Op.getOperand(2), + SDOperand()); + Copy = DAG.getCopyToReg(Copy, PPC::R4, Op.getOperand(1),Copy.getValue(1)); + break; + } + return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); + } } return SDOperand(); } @@ -835,30 +862,6 @@ PPCTargetLowering::LowerCallTo(SDOperand Chain, return std::make_pair(RetVal, Chain); } -SDOperand PPCTargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - SDOperand Copy; - switch (Op.getValueType()) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: - Copy = DAG.getCopyToReg(Chain, PPC::R3, Op, SDOperand()); - break; - case MVT::f32: - case MVT::f64: - Copy = DAG.getCopyToReg(Chain, PPC::F1, Op, SDOperand()); - break; - case MVT::i64: - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(1, MVT::i32)); - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(0, MVT::i32)); - Copy = DAG.getCopyToReg(Chain, PPC::R3, Hi, SDOperand()); - Copy = DAG.getCopyToReg(Copy, PPC::R4, Lo, Copy.getValue(1)); - break; - } - return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); -} - std::pair PPCTargetLowering:: LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, SelectionDAG &DAG) { diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 4be2b71a784..fe4a8214df5 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -91,9 +91,6 @@ namespace llvm { bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); - virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 6485ad2a2f5..4a6eebb1e6b 100644 --- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -63,9 +63,6 @@ namespace { unsigned CC, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); - - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); @@ -156,6 +153,9 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand); + // 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 setOperationAction(ISD::VASTART , MVT::Other, Custom); @@ -576,32 +576,6 @@ SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, return std::make_pair(RetVal, Chain); } -SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - SDOperand Copy; - switch (Op.getValueType()) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: - Copy = DAG.getCopyToReg(Chain, V8::I0, Op, SDOperand()); - break; - case MVT::f32: - Copy = DAG.getCopyToReg(Chain, V8::F0, Op, SDOperand()); - break; - case MVT::f64: - Copy = DAG.getCopyToReg(Chain, V8::D0, Op, SDOperand()); - break; - case MVT::i64: - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(1, MVT::i32)); - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(0, MVT::i32)); - Copy = DAG.getCopyToReg(Chain, V8::I0, Hi, SDOperand()); - Copy = DAG.getCopyToReg(Copy, V8::I1, Lo, Copy.getValue(1)); - break; - } - return DAG.getNode(V8ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); -} - std::pair SparcV8TargetLowering:: LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG) { @@ -694,6 +668,35 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset, Op.getOperand(1), Op.getOperand(2)); } + case ISD::RET: { + SDOperand Copy; + + switch(Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return SDOperand(); // ret void is legal + case 2: { + unsigned ArgReg; + switch(Op.getOperand(1).getValueType()) { + default: assert(0 && "Unknown type to return!"); + case MVT::i32: ArgReg = V8::I0; break; + case MVT::f32: ArgReg = V8::F0; break; + case MVT::f64: ArgReg = V8::D0; break; + } + Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), + SDOperand()); + break; + } + case 3: + Copy = DAG.getCopyToReg(Op.getOperand(0), V8::I0, Op.getOperand(2), + SDOperand()); + Copy = DAG.getCopyToReg(Copy, V8::I1, Op.getOperand(1), Copy.getValue(1)); + break; + } + return DAG.getNode(V8ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); + } } } diff --git a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp index 6485ad2a2f5..4a6eebb1e6b 100644 --- a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp +++ b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp @@ -63,9 +63,6 @@ namespace { unsigned CC, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); - - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG); @@ -156,6 +153,9 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand); + // 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 setOperationAction(ISD::VASTART , MVT::Other, Custom); @@ -576,32 +576,6 @@ SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, return std::make_pair(RetVal, Chain); } -SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - SDOperand Copy; - switch (Op.getValueType()) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: - Copy = DAG.getCopyToReg(Chain, V8::I0, Op, SDOperand()); - break; - case MVT::f32: - Copy = DAG.getCopyToReg(Chain, V8::F0, Op, SDOperand()); - break; - case MVT::f64: - Copy = DAG.getCopyToReg(Chain, V8::D0, Op, SDOperand()); - break; - case MVT::i64: - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(1, MVT::i32)); - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(0, MVT::i32)); - Copy = DAG.getCopyToReg(Chain, V8::I0, Hi, SDOperand()); - Copy = DAG.getCopyToReg(Copy, V8::I1, Lo, Copy.getValue(1)); - break; - } - return DAG.getNode(V8ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); -} - std::pair SparcV8TargetLowering:: LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG) { @@ -694,6 +668,35 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset, Op.getOperand(1), Op.getOperand(2)); } + case ISD::RET: { + SDOperand Copy; + + switch(Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return SDOperand(); // ret void is legal + case 2: { + unsigned ArgReg; + switch(Op.getOperand(1).getValueType()) { + default: assert(0 && "Unknown type to return!"); + case MVT::i32: ArgReg = V8::I0; break; + case MVT::f32: ArgReg = V8::F0; break; + case MVT::f64: ArgReg = V8::D0; break; + } + Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), + SDOperand()); + break; + } + case 3: + Copy = DAG.getCopyToReg(Op.getOperand(0), V8::I0, Op.getOperand(2), + SDOperand()); + Copy = DAG.getCopyToReg(Copy, V8::I1, Op.getOperand(1), Copy.getValue(1)); + break; + } + return DAG.getNode(V8ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); + } } } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index cd014aa3319..8a72f2618fb 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -269,69 +269,6 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, return LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG); } -SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG) { - if (!X86DAGIsel) - return DAG.getNode(ISD::RET, MVT::Other, Chain, Op); - - SDOperand Copy; - MVT::ValueType OpVT = Op.getValueType(); - switch (OpVT) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: - Copy = DAG.getCopyToReg(Chain, X86::EAX, Op, SDOperand()); - break; - case MVT::i64: { - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(1, MVT::i32)); - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, - DAG.getConstant(0, MVT::i32)); - Copy = DAG.getCopyToReg(Chain, X86::EDX, Hi, SDOperand()); - Copy = DAG.getCopyToReg(Copy, X86::EAX, Lo, Copy.getValue(1)); - break; - } - case MVT::f32: - case MVT::f64: - if (!X86ScalarSSE) { - std::vector Tys; - Tys.push_back(MVT::Other); - Tys.push_back(MVT::Flag); - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(Op); - Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops); - } else { - // Spill the value to memory and reload it into top of stack. - unsigned Size = MVT::getSizeInBits(OpVT)/8; - MachineFunction &MF = DAG.getMachineFunction(); - int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size); - SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); - Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Op, - StackSlot, DAG.getSrcValue(NULL)); - std::vector Tys; - Tys.push_back(MVT::f64); - Tys.push_back(MVT::Other); - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(StackSlot); - Ops.push_back(DAG.getValueType(OpVT)); - Copy = DAG.getNode(X86ISD::FLD, Tys, Ops); - Tys.clear(); - Tys.push_back(MVT::Other); - Tys.push_back(MVT::Flag); - Ops.clear(); - Ops.push_back(Copy.getValue(1)); - Ops.push_back(Copy); - Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops); - } - break; - } - - return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, - Copy, DAG.getConstant(getBytesToPopOnReturn(), MVT::i16), - Copy.getValue(1)); -} - //===----------------------------------------------------------------------===// // C Calling Convention implementation //===----------------------------------------------------------------------===// @@ -1766,11 +1703,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(X86ISD::BRCOND, Op.getValueType(), Op.getOperand(0), Op.getOperand(2), CC, Cond); } - case ISD::RET: { - // Can only be return void. - return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Op.getOperand(0), - DAG.getConstant(getBytesToPopOnReturn(), MVT::i16)); - } case ISD::MEMSET: { SDOperand InFlag; SDOperand Chain = Op.getOperand(0); @@ -1897,6 +1829,66 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR, Op.getOperand(1), Op.getOperand(2)); } + case ISD::RET: { + SDOperand Copy; + + switch(Op.getNumOperands()) { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Op.getOperand(0), + DAG.getConstant(getBytesToPopOnReturn(), MVT::i16)); + case 2: { + MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); + if (MVT::isInteger(ArgVT)) + Copy = DAG.getCopyToReg(Op.getOperand(0), X86::EAX, Op.getOperand(1), + SDOperand()); + else if (!X86ScalarSSE) { + std::vector Tys; + Tys.push_back(MVT::Other); + Tys.push_back(MVT::Flag); + std::vector Ops; + Ops.push_back(Op.getOperand(0)); + Ops.push_back(Op.getOperand(1)); + Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops); + } else { + // Spill the value to memory and reload it into top of stack. + unsigned Size = MVT::getSizeInBits(ArgVT)/8; + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size); + SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + SDOperand Chain = DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), + Op.getOperand(1), StackSlot, + DAG.getSrcValue(0)); + std::vector Tys; + Tys.push_back(MVT::f64); + Tys.push_back(MVT::Other); + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(StackSlot); + Ops.push_back(DAG.getValueType(ArgVT)); + Copy = DAG.getNode(X86ISD::FLD, Tys, Ops); + Tys.clear(); + Tys.push_back(MVT::Other); + Tys.push_back(MVT::Flag); + Ops.clear(); + Ops.push_back(Copy.getValue(1)); + Ops.push_back(Copy); + Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops); + } + break; + } + case 3: + Copy = DAG.getCopyToReg(Op.getOperand(0), X86::EDX, Op.getOperand(2), + SDOperand()); + Copy = DAG.getCopyToReg(Copy, X86::EAX,Op.getOperand(1),Copy.getValue(1)); + break; + } + return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, + Copy, DAG.getConstant(getBytesToPopOnReturn(), MVT::i16), + Copy.getValue(1)); + } } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 5787962ba0c..fc601702d5c 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -193,9 +193,6 @@ namespace llvm { bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); - virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op, - SelectionDAG &DAG); - virtual std::pair LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, SelectionDAG &DAG);