summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-05-16 22:53:20 +0000
committerChris Lattner <sabre@nondot.org>2006-05-16 22:53:20 +0000
commitf4ec817299a4187044a6162c2f520772b3ad69a0 (patch)
treef0fa7e226d0d4762dabf6f09734c7b5cad1657bd /lib/CodeGen/SelectionDAG
parent6c0bfc723779366698d3936b63dcddc6164c2d33 (diff)
downloadllvm-f4ec817299a4187044a6162c2f520772b3ad69a0.tar.gz
llvm-f4ec817299a4187044a6162c2f520772b3ad69a0.tar.bz2
llvm-f4ec817299a4187044a6162c2f520772b3ad69a0.tar.xz
Add a new ISD::CALL node, make the default impl of TargetLowering::LowerCallTo
produce it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28338 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp140
3 files changed, 143 insertions, 3 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index f63a09248b..9f8b999b56 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -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));
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index cf1d41f705..41c1193b02 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -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";
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index b647232370..105eb9ba12 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -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) {