diff options
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 24 | ||||
-rw-r--r-- | lib/Target/ARM/ARMRegisterInfo.cpp | 25 | ||||
-rw-r--r-- | test/CodeGen/ARM/vargs.ll | 12 |
3 files changed, 49 insertions, 12 deletions
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 915684ad17..1ef5bf48ca 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -79,7 +79,6 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { 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); @@ -89,23 +88,40 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // 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. diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index a9fe705667..719ce321e0 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -124,10 +124,21 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const { //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, @@ -138,13 +149,11 @@ 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 { diff --git a/test/CodeGen/ARM/vargs.ll b/test/CodeGen/ARM/vargs.ll new file mode 100644 index 0000000000..858c463c58 --- /dev/null +++ b/test/CodeGen/ARM/vargs.ll @@ -0,0 +1,12 @@ +; 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*, ...) |