Remove TLI.LowerReturnTo, and just let targets custom lower ISD::RET for

the same functionality.  This addresses another piece of bug 680.  Next,
on to fixing Alpha VAARG, which I broke last time.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25696 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2006-01-27 21:09:22 +00:00
parent da427fa5da
commit ee625573b5
10 changed files with 203 additions and 259 deletions

View File

@ -360,12 +360,6 @@ public:
unsigned CallingConv, bool isTailCall, SDOperand Callee, unsigned CallingConv, bool isTailCall, SDOperand Callee,
ArgListTy &Args, SelectionDAG &DAG) = 0; 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 /// LowerFrameReturnAddress - This hook lowers a call to llvm.returnaddress or
/// llvm.frameaddress (depending on the value of the first argument). The /// llvm.frameaddress (depending on the value of the first argument). The
/// return values are the result pointer and the resultant token chain. If /// return values are the result pointer and the resultant token chain. If

View File

@ -496,40 +496,30 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) {
DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getRoot())); DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getRoot()));
return; return;
} }
std::vector<SDOperand> 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)); if (I.getOperand(i)->getType()->isSigned())
MVT::ValueType TmpVT; RetOp = DAG.getNode(ISD::SIGN_EXTEND, TmpVT, RetOp);
else
switch (Op1.getValueType()) { RetOp = DAG.getNode(ISD::ZERO_EXTEND, TmpVT, RetOp);
default: assert(0 && "Unknown value type!"); }
case MVT::i1: NewValues.push_back(RetOp);
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!
} }
// Allow targets to lower this further to meet ABI requirements DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, NewValues));
DAG.setRoot(TLI.LowerReturnTo(getRoot(), Op1, DAG));
} }
void SelectionDAGLowering::visitBr(BranchInst &I) { void SelectionDAGLowering::visitBr(BranchInst &I) {
@ -1249,11 +1239,6 @@ MachineBasicBlock *TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
return 0; 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) { void SelectionDAGLowering::visitVAStart(CallInst &I) {
DAG.setRoot(DAG.getNode(ISD::VASTART, MVT::Other, getRoot(), DAG.setRoot(DAG.getNode(ISD::VASTART, MVT::Other, getRoot(),
getValue(I.getOperand(1)), getValue(I.getOperand(1)),

View File

@ -537,44 +537,6 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
return std::make_pair(RetVal, 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<MVT::ValueType> NodeTys;
std::vector<SDOperand> 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<SDOperand, SDOperand> IA64TargetLowering:: std::pair<SDOperand, SDOperand> IA64TargetLowering::
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) { SelectionDAG &DAG) {
@ -586,21 +548,38 @@ SDOperand IA64TargetLowering::
LowerOperation(SDOperand Op, SelectionDAG &DAG) { LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) { switch (Op.getOpcode()) {
default: assert(0 && "Should not custom lower this!"); default: assert(0 && "Should not custom lower this!");
case ISD::RET: { // the DAGgy stuff takes care of case ISD::RET: {
// restoring ar.pfs before adding a br.ret for functions SDOperand AR_PFSVal, Copy;
// 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)");
SDOperand Chain = Op.getOperand(0); switch(Op.getNumOperands()) {
SDOperand AR_PFSVal = DAG.getCopyFromReg(Chain, this->VirtGPR, default:
MVT::i64); assert(0 && "Do not know how to return this many arguments!");
Chain = AR_PFSVal.getValue(1); abort();
Chain = DAG.getCopyToReg(Chain, IA64::AR_PFS, AR_PFSVal); 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 AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64);
return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, Chain); 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<MVT::ValueType> NodeTys;
std::vector<SDOperand> 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: { case ISD::VAARG: {
MVT::ValueType VT = getPointerTy(); MVT::ValueType VT = getPointerTy();

View File

@ -48,10 +48,6 @@ namespace llvm {
unsigned VirtGPR; // this is public so it can be accessed in the selector unsigned VirtGPR; // this is public so it can be accessed in the selector
// for ISD::RET. add an accessor instead? FIXME // 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; const char *getTargetNodeName(unsigned Opcode) const;
/// LowerArguments - This hook must be implemented to indicate how we should /// LowerArguments - This hook must be implemented to indicate how we should
@ -67,11 +63,6 @@ namespace llvm {
bool isTailCall, SDOperand Callee, ArgListTy &Args, bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG); 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 /// LowerOperation - for custom lowering specific ops
/// (currently, only "ret void") /// (currently, only "ret void")
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);

View File

@ -110,6 +110,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, 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 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VASTART , MVT::Other, Custom); 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, return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR,
Op.getOperand(1), Op.getOperand(2)); 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(); return SDOperand();
} }
@ -835,30 +862,6 @@ PPCTargetLowering::LowerCallTo(SDOperand Chain,
return std::make_pair(RetVal, 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<SDOperand, SDOperand> PPCTargetLowering:: std::pair<SDOperand, SDOperand> PPCTargetLowering::
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) { SelectionDAG &DAG) {

View File

@ -91,9 +91,6 @@ namespace llvm {
bool isTailCall, SDOperand Callee, ArgListTy &Args, bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG); SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand> virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG); SelectionDAG &DAG);

View File

@ -63,9 +63,6 @@ namespace {
unsigned CC, unsigned CC,
bool isTailCall, SDOperand Callee, ArgListTy &Args, bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG); SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand> virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG); SelectionDAG &DAG);
@ -156,6 +153,9 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
setOperationAction(ISD::DEBUG_LABEL, 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 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VASTART , MVT::Other, Custom); setOperationAction(ISD::VASTART , MVT::Other, Custom);
@ -576,32 +576,6 @@ SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
return std::make_pair(RetVal, Chain); 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<SDOperand, SDOperand> SparcV8TargetLowering:: std::pair<SDOperand, SDOperand> SparcV8TargetLowering::
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) { SelectionDAG &DAG) {
@ -694,6 +668,35 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset, return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset,
Op.getOperand(1), Op.getOperand(2)); 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));
}
} }
} }

View File

@ -63,9 +63,6 @@ namespace {
unsigned CC, unsigned CC,
bool isTailCall, SDOperand Callee, ArgListTy &Args, bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG); SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand> virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG); SelectionDAG &DAG);
@ -156,6 +153,9 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
setOperationAction(ISD::DEBUG_LABEL, 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 // VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VASTART , MVT::Other, Custom); setOperationAction(ISD::VASTART , MVT::Other, Custom);
@ -576,32 +576,6 @@ SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
return std::make_pair(RetVal, Chain); 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<SDOperand, SDOperand> SparcV8TargetLowering:: std::pair<SDOperand, SDOperand> SparcV8TargetLowering::
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG) { SelectionDAG &DAG) {
@ -694,6 +668,35 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset, return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset,
Op.getOperand(1), Op.getOperand(2)); 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));
}
} }
} }

View File

@ -269,69 +269,6 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
return LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG); 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<MVT::ValueType> Tys;
Tys.push_back(MVT::Other);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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<MVT::ValueType> Tys;
Tys.push_back(MVT::f64);
Tys.push_back(MVT::Other);
std::vector<SDOperand> 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 // C Calling Convention implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1766,11 +1703,6 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return DAG.getNode(X86ISD::BRCOND, Op.getValueType(), return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
Op.getOperand(0), Op.getOperand(2), CC, Cond); 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: { case ISD::MEMSET: {
SDOperand InFlag; SDOperand InFlag;
SDOperand Chain = Op.getOperand(0); 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, return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR,
Op.getOperand(1), Op.getOperand(2)); 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<MVT::ValueType> Tys;
Tys.push_back(MVT::Other);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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<MVT::ValueType> Tys;
Tys.push_back(MVT::f64);
Tys.push_back(MVT::Other);
std::vector<SDOperand> 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));
}
} }
} }

View File

@ -193,9 +193,6 @@ namespace llvm {
bool isTailCall, SDOperand Callee, ArgListTy &Args, bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG); SelectionDAG &DAG);
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand> virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG); SelectionDAG &DAG);