Add a new ISD::CALL node, make the default impl of TargetLowering::LowerCallTo

produce it.

llvm-svn: 28338
This commit is contained in:
Chris Lattner 2006-05-16 22:53:20 +00:00
parent e33580e5b4
commit aaa23d953f
3 changed files with 143 additions and 3 deletions

View File

@ -818,11 +818,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
case ISD::FORMAL_ARGUMENTS:
case ISD::CALL:
// The only option for this is to custom lower it.
Result = TLI.LowerOperation(Result.getValue(0), DAG);
assert(Result.Val && "Target didn't custom lower ISD::FORMAL_ARGUMENTS!");
assert(Result.Val && "Target didn't custom lower this node!");
// Since FORMAL_ARGUMENTS nodes produce multiple values, make sure to
// Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
// remember that we legalized all of them, so it doesn't get relegalized.
for (unsigned i = 0, e = Result.Val->getNumValues(); i != e; ++i) {
Tmp1 = LegalizeOp(Result.getValue(i));

View File

@ -2841,6 +2841,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::INLINEASM: return "inlineasm";
case ISD::HANDLENODE: return "handlenode";
case ISD::FORMAL_ARGUMENTS: return "formal_arguments";
case ISD::CALL: return "call";
// Unary operators
case ISD::FABS: return "fabs";

View File

@ -2344,7 +2344,8 @@ void SelectionDAGLowering::visitVACopy(CallInst &I) {
/// TargetLowering::LowerArguments - This is the default LowerArguments
/// implementation, which just inserts a FORMAL_ARGUMENTS node. FIXME: When all
/// targets are migrated to using FORMAL_ARGUMENTS, this hook should be removed.
/// targets are migrated to using FORMAL_ARGUMENTS, this hook should be
/// integrated into SDISel.
std::vector<SDOperand>
TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
// Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node.
@ -2477,8 +2478,145 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
return Ops;
}
/// TargetLowering::LowerCallTo - This is the default LowerCallTo
/// implementation, which just inserts an ISD::CALL node, which is later custom
/// lowered by the target to something concrete. FIXME: When all targets are
/// migrated to using ISD::CALL, this hook should be integrated into SDISel.
std::pair<SDOperand, SDOperand>
TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
unsigned CallingConv, bool isTailCall,
SDOperand Callee,
ArgListTy &Args, SelectionDAG &DAG) {
std::vector<SDOperand> Ops;
Ops.push_back(Chain); // Op#0 - Chain
Ops.push_back(DAG.getConstant(CallingConv, getPointerTy())); // Op#1 - CC
Ops.push_back(DAG.getConstant(isVarArg, getPointerTy())); // Op#2 - VarArg
Ops.push_back(DAG.getConstant(isTailCall, getPointerTy())); // Op#3 - Tail
Ops.push_back(Callee);
// Handle all of the outgoing arguments.
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
MVT::ValueType VT = getValueType(Args[i].second);
SDOperand Op = Args[i].first;
switch (getTypeAction(VT)) {
default: assert(0 && "Unknown type action!");
case Legal:
Ops.push_back(Op);
break;
case Promote:
if (MVT::isInteger(VT)) {
unsigned ExtOp = Args[i].second->isSigned() ?
ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
Op = DAG.getNode(ExtOp, getTypeToTransformTo(VT), Op);
} else {
assert(MVT::isFloatingPoint(VT) && "Not int or FP?");
Op = DAG.getNode(ISD::FP_EXTEND, getTypeToTransformTo(VT), Op);
}
Ops.push_back(Op);
break;
case Expand:
if (VT != MVT::Vector) {
// If this is a large integer, it needs to be broken down into small
// integers. Figure out what the source elt type is and how many small
// integers it is.
MVT::ValueType NVT = getTypeToTransformTo(VT);
unsigned NumVals = MVT::getSizeInBits(VT)/MVT::getSizeInBits(NVT);
if (NumVals == 2) {
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, NVT, Op,
DAG.getConstant(0, getPointerTy()));
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, NVT, Op,
DAG.getConstant(1, getPointerTy()));
if (!isLittleEndian())
std::swap(Lo, Hi);
Ops.push_back(Lo);
Ops.push_back(Hi);
} else {
// Value scalarized into many values. Unimp for now.
assert(0 && "Cannot expand i64 -> i16 yet!");
}
} else {
assert(0 && "Doesn't handle vectors yet!");
}
break;
}
}
// Figure out the result value types.
std::vector<MVT::ValueType> RetTys;
if (RetTy != Type::VoidTy) {
MVT::ValueType VT = getValueType(RetTy);
switch (getTypeAction(VT)) {
default: assert(0 && "Unknown type action!");
case Legal:
RetTys.push_back(VT);
break;
case Promote:
RetTys.push_back(getTypeToTransformTo(VT));
break;
case Expand:
if (VT != MVT::Vector) {
// If this is a large integer, it needs to be reassembled from small
// integers. Figure out what the source elt type is and how many small
// integers it is.
MVT::ValueType NVT = getTypeToTransformTo(VT);
unsigned NumVals = MVT::getSizeInBits(VT)/MVT::getSizeInBits(NVT);
for (unsigned i = 0; i != NumVals; ++i)
RetTys.push_back(NVT);
} else {
assert(0 && "Doesn't handle vectors yet!");
}
}
}
RetTys.push_back(MVT::Other); // Always has a chain.
// Finally, create the CALL node.
SDOperand Res = DAG.getNode(ISD::CALL, RetTys, Ops);
// This returns a pair of operands. The first element is the
// return value for the function (if RetTy is not VoidTy). The second
// element is the outgoing token chain.
SDOperand ResVal;
if (RetTys.size() != 1) {
MVT::ValueType VT = getValueType(RetTy);
if (RetTys.size() == 2) {
ResVal = Res;
// If this value was promoted, truncate it down.
if (ResVal.getValueType() != VT) {
if (MVT::isInteger(VT)) {
unsigned AssertOp = RetTy->isSigned() ?
ISD::AssertSext : ISD::AssertZext;
ResVal = DAG.getNode(AssertOp, ResVal.getValueType(), ResVal,
DAG.getValueType(VT));
ResVal = DAG.getNode(ISD::TRUNCATE, VT, ResVal);
} else {
assert(MVT::isFloatingPoint(VT));
ResVal = DAG.getNode(ISD::FP_ROUND, VT, ResVal);
}
}
} else if (RetTys.size() == 3) {
ResVal = DAG.getNode(ISD::BUILD_PAIR, VT,
Res.getValue(0), Res.getValue(1));
} else {
assert(0 && "Case not handled yet!");
}
}
return std::make_pair(ResVal, Res.getValue(Res.Val->getNumValues()-1));
}
// It is always conservatively correct for llvm.returnaddress and
// llvm.frameaddress to return 0.
//
// FIXME: Change this to insert a FRAMEADDR/RETURNADDR node, and have that be
// expanded to 0 if the target wants.
std::pair<SDOperand, SDOperand>
TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain,
unsigned Depth, SelectionDAG &DAG) {