implement function calling of functions with up to 4 arguments

llvm-svn: 29274
This commit is contained in:
Rafael Espindola 2006-07-25 20:17:20 +00:00
parent 238caefaa4
commit 8902fd702b
2 changed files with 53 additions and 3 deletions

View File

@ -75,17 +75,38 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
assert(isTailCall == false && "tail call not supported"); assert(isTailCall == false && "tail call not supported");
SDOperand Callee = Op.getOperand(4); SDOperand Callee = Op.getOperand(4);
unsigned NumOps = (Op.getNumOperands() - 5) / 2; unsigned NumOps = (Op.getNumOperands() - 5) / 2;
assert(NumOps == 0);
// Count how many bytes are to be pushed on the stack. Initially // Count how many bytes are to be pushed on the stack. Initially
// only the link register. // only the link register.
unsigned NumBytes = 4; unsigned NumBytes = 4;
assert(NumOps <= 4); //no args on the stack
// Adjust the stack pointer for the new arguments... // Adjust the stack pointer for the new arguments...
// These operations are automatically eliminated by the prolog/epilog pass // These operations are automatically eliminated by the prolog/epilog pass
Chain = DAG.getCALLSEQ_START(Chain, Chain = DAG.getCALLSEQ_START(Chain,
DAG.getConstant(NumBytes, MVT::i32)); 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; std::vector<MVT::ValueType> NodeTys;
NodeTys.push_back(MVT::Other); // Returns a chain NodeTys.push_back(MVT::Other); // Returns a chain
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. 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); Ops.push_back(Callee);
unsigned CallOpc = ARMISD::CALL; unsigned CallOpc = ARMISD::CALL;
if (InFlag.Val)
Ops.push_back(InFlag);
Chain = DAG.getNode(CallOpc, NodeTys, Ops); Chain = DAG.getNode(CallOpc, NodeTys, Ops);
InFlag = Chain.getValue(1);
assert(Op.Val->getValueType(0) == MVT::Other); std::vector<SDOperand> ResultVals;
NodeTys.clear();
// 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, Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
DAG.getConstant(NumBytes, MVT::i32)); DAG.getConstant(NumBytes, MVT::i32));
NodeTys.push_back(MVT::Other);
return Chain; if (ResultVals.empty())
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) { static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {

View File

@ -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)