summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2006-07-25 20:17:20 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2006-07-25 20:17:20 +0000
commitfac00a93a98d43ac0d4ca514aa5a720debbd6c8b (patch)
treee7f2ca93405b27485e02d5936b2d94d9e2434687
parentc152efda47d8c90f540422bb374620b7fb1effbf (diff)
downloadllvm-fac00a93a98d43ac0d4ca514aa5a720debbd6c8b.tar.gz
llvm-fac00a93a98d43ac0d4ca514aa5a720debbd6c8b.tar.bz2
llvm-fac00a93a98d43ac0d4ca514aa5a720debbd6c8b.tar.xz
implement function calling of functions with up to 4 arguments
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29274 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp48
-rw-r--r--test/CodeGen/ARM/call.ll8
2 files changed, 53 insertions, 3 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 2eb89b7997..8ca7c0b40c 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -75,17 +75,38 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
assert(isTailCall == false && "tail call not supported");
SDOperand Callee = Op.getOperand(4);
unsigned NumOps = (Op.getNumOperands() - 5) / 2;
- assert(NumOps == 0);
// Count how many bytes are to be pushed on the stack. Initially
// only the link register.
unsigned NumBytes = 4;
+ assert(NumOps <= 4); //no args on the stack
+
// Adjust the stack pointer for the new arguments...
// These operations are automatically eliminated by the prolog/epilog pass
Chain = DAG.getCALLSEQ_START(Chain,
DAG.getConstant(NumBytes, MVT::i32));
+ static const unsigned regs[] = {
+ ARM::R0, ARM::R1, ARM::R2, ARM::R3
+ };
+
+ std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
+
+ for (unsigned i = 0; i != NumOps; ++i) {
+ SDOperand Arg = Op.getOperand(5+2*i);
+ RegsToPass.push_back(std::make_pair(regs[i], Arg));
+ }
+
+ // Build a sequence of copy-to-reg nodes chained together with token chain
+ // and flag operands which copy the outgoing args into the appropriate regs.
+ SDOperand InFlag;
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+ Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
+ InFlag);
+ InFlag = Chain.getValue(1);
+ }
+
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.
@@ -103,14 +124,35 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
Ops.push_back(Callee);
unsigned CallOpc = ARMISD::CALL;
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
Chain = DAG.getNode(CallOpc, NodeTys, Ops);
+ InFlag = Chain.getValue(1);
+
+ std::vector<SDOperand> ResultVals;
+ NodeTys.clear();
- assert(Op.Val->getValueType(0) == MVT::Other);
+ // If the call has results, copy the values out of the ret val registers.
+ switch (Op.Val->getValueType(0)) {
+ default: assert(0 && "Unexpected ret value!");
+ case MVT::Other:
+ break;
+ case MVT::i32:
+ Chain = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag).getValue(1);
+ ResultVals.push_back(Chain.getValue(0));
+ NodeTys.push_back(MVT::i32);
+ }
Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
DAG.getConstant(NumBytes, MVT::i32));
+ NodeTys.push_back(MVT::Other);
+
+ if (ResultVals.empty())
+ return Chain;
- return Chain;
+ ResultVals.push_back(Chain);
+ SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals);
+ return Res.getValue(Op.ResNo);
}
static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
diff --git a/test/CodeGen/ARM/call.ll b/test/CodeGen/ARM/call.ll
new file mode 100644
index 0000000000..cfffa99eb0
--- /dev/null
+++ b/test/CodeGen/ARM/call.ll
@@ -0,0 +1,8 @@
+; RUN: llvm-as < %s | llc -march=arm
+void %f() {
+entry:
+ call void %g( int 1, int 2, int 3, int 4 )
+ ret void
+}
+
+declare void %g(int, int, int, int)