From: Rafael Espindola Date: Tue, 25 Jul 2006 20:17:20 +0000 (+0000) Subject: implement function calling of functions with up to 4 arguments X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=fac00a93a98d43ac0d4ca514aa5a720debbd6c8b;p=oota-llvm.git 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 --- diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 2eb89b79972..8ca7c0b40c0 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 > 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 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 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 00000000000..cfffa99eb0b --- /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)