aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp32
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td8
2 files changed, 22 insertions, 18 deletions
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index a021c0e2d7..03e0d38d10 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1041,6 +1041,11 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
}
std::vector<MVT::ValueType> NodeTys;
+ NodeTys.push_back(MVT::Other); // Returns a chain
+ NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
+
+ std::vector<SDOperand> Ops;
+ unsigned CallOpc = PPCISD::CALL;
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
@@ -1055,11 +1060,8 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
else {
// Otherwise, this is an indirect call. We have to use a MTCTR/BCTRL pair
// to do the call, we can't use PPCISD::CALL.
- std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
- NodeTys.push_back(MVT::Other);
- NodeTys.push_back(MVT::Flag);
if (InFlag.Val)
Ops.push_back(InFlag);
@@ -1075,25 +1077,27 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
NodeTys.push_back(MVT::Flag);
Ops.clear();
Ops.push_back(Chain);
- Ops.push_back(InFlag);
- Chain = DAG.getNode(PPCISD::BCTRL, NodeTys, Ops);
- InFlag = Chain.getValue(1);
+ CallOpc = PPCISD::BCTRL;
Callee.Val = 0;
}
- // Create the PPCISD::CALL node itself.
+ // If this is a direct call, pass the chain and the callee.
if (Callee.Val) {
- NodeTys.push_back(MVT::Other); // Returns a chain
- NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
- std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
- if (InFlag.Val)
- Ops.push_back(InFlag);
- Chain = DAG.getNode(PPCISD::CALL, NodeTys, Ops);
- InFlag = Chain.getValue(1);
}
+ // Add argument registers to the end of the list so that they are known live
+ // into the call.
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
+ Ops.push_back(DAG.getRegister(RegsToPass[i].first,
+ RegsToPass[i].second.getValueType()));
+
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
+ Chain = DAG.getNode(CallOpc, NodeTys, Ops);
+ InFlag = Chain.getValue(1);
+
std::vector<SDOperand> ResultVals;
NodeTys.clear();
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index c93e0d4d83..460826b314 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -71,7 +71,7 @@ def PPCstd_32 : SDNode<"PPCISD::STD_32" , SDTStore, [SDNPHasChain]>;
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,[SDNPHasChain]>;
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>;
-def SDT_PPCCall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+def SDT_PPCCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>;
def PPCcall : SDNode<"PPCISD::CALL", SDT_PPCCall,
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
def PPCmtctr : SDNode<"PPCISD::MTCTR", SDT_PPCCall,
@@ -310,11 +310,11 @@ let isCall = 1, noResults = 1, PPC970_Unit = 7,
LR,CTR,
CR0,CR1,CR5,CR6,CR7] in {
// Convenient aliases for call instructions
- def BL : IForm<18, 0, 1, (ops calltarget:$func),
+ def BL : IForm<18, 0, 1, (ops calltarget:$func, variable_ops),
"bl $func", BrB, []>; // See Pat patterns below.
- def BLA : IForm<18, 1, 1, (ops aaddr:$func),
+ def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops),
"bla $func", BrB, [(PPCcall imm:$func)]>;
- def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops), "bctrl", BrB,
+ def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB,
[(PPCbctrl)]>;
}