unsigned CallConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
assert(CallConv == CallingConv::C && "unknown calling convention");
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- assert(isVarArg == false && "VarArg not supported");
bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
assert(isTailCall == false && "tail call not supported");
SDOperand Callee = Op.getOperand(4);
// only the link register.
unsigned NumBytes = 4;
- assert(NumOps <= 4); //no args on the stack
+ // Add up all the space actually used.
+ for (unsigned i = 4; i < NumOps; ++i)
+ NumBytes += MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
// 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[] = {
+ SDOperand StackPtr = DAG.getRegister(ARM::R13, MVT::i32);
+
+ static const unsigned int num_regs = 4;
+ static const unsigned regs[num_regs] = {
ARM::R0, ARM::R1, ARM::R2, ARM::R3
};
std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
+ std::vector<SDOperand> MemOpChains;
for (unsigned i = 0; i != NumOps; ++i) {
SDOperand Arg = Op.getOperand(5+2*i);
- RegsToPass.push_back(std::make_pair(regs[i], Arg));
+ assert(Arg.getValueType() == MVT::i32);
+ if (i < num_regs)
+ RegsToPass.push_back(std::make_pair(regs[i], Arg));
+ else {
+ unsigned ArgOffset = (i - num_regs) * 4;
+ SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
+ PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
+ MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+ Arg, PtrOff, DAG.getSrcValue(NULL)));
+ }
}
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOpChains);
// 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.
//hack
assert(NumBytes == 0);
- //sub sp, sp, #4
- BuildMI(MBB, MBBI, ARM::subri, 2, ARM::R13).addReg(ARM::R13).addImm(4);
- //str lr, [sp]
- BuildMI(MBB, MBBI, ARM::str, 1, ARM::R14).addReg(ARM::R13);
+ if (MFI->hasCalls()) {
+ // We reserve argument space for call sites in the function immediately on
+ // entry to the current function. This eliminates the need for add/sub
+ // brackets around call sites.
+ NumBytes += MFI->getMaxCallFrameSize();
+ }
+
+ MFI->setStackSize(NumBytes);
+
+ //sub sp, sp, #NumBytes
+ BuildMI(MBB, MBBI, ARM::subri, 2, ARM::R13).addReg(ARM::R13).addImm(NumBytes);
+ //add ip, sp, #NumBytes - 4
+ BuildMI(MBB, MBBI, ARM::addri, 2, ARM::R12).addReg(ARM::R13).addImm(NumBytes - 4);
+ //str lr, [ip]
+ BuildMI(MBB, MBBI, ARM::str, 1, ARM::R14).addReg(ARM::R12);
}
void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
MachineFrameInfo *MFI = MF.getFrameInfo();
int NumBytes = (int) MFI->getStackSize();
- //hack
- assert(NumBytes == 0);
//ldr lr, [sp]
BuildMI(MBB, MBBI, ARM::ldr, 2, ARM::R14).addImm(0).addReg(ARM::R13);
- //add sp, sp, #4
- BuildMI(MBB, MBBI, ARM::addri, 2, ARM::R13).addReg(ARM::R13).addImm(4);
+ //add sp, sp, #NumBytes
+ BuildMI(MBB, MBBI, ARM::addri, 2, ARM::R13).addReg(ARM::R13).addImm(NumBytes);
}
unsigned ARMRegisterInfo::getRARegister() const {
--- /dev/null
+; RUN: llvm-as < %s | llc -march=arm
+%str = internal constant [43 x sbyte] c"Hello World %d %d %d %d %d %d %d %d %d %d\0A\00" ; <[43 x sbyte]*> [#uses=1]
+
+implementation ; Functions:
+
+int %main() {
+entry:
+ %tmp = call int (sbyte*, ...)* %printf( sbyte* getelementptr ([43 x sbyte]* %str, int 0, uint 0), int 1, int 2, int 3, int 4, int 5, int 6, int 7, int 8, int 9, int 10 ) ; <int> [#uses=0]
+ ret int 0
+}
+
+declare int %printf(sbyte*, ...)