summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2006-08-08 13:02:29 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2006-08-08 13:02:29 +0000
commit1a009468175a6e123cc3f1e847c10e3e126a44db (patch)
tree83118e1b2715b44919b2747fff0486ff369e42de
parentbd564bfc63163e31f320c3da9749db70992dc35e (diff)
downloadllvm-1a009468175a6e123cc3f1e847c10e3e126a44db.tar.gz
llvm-1a009468175a6e123cc3f1e847c10e3e126a44db.tar.bz2
llvm-1a009468175a6e123cc3f1e847c10e3e126a44db.tar.xz
initial support for variable number of arguments
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29567 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp24
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp25
-rw-r--r--test/CodeGen/ARM/vargs.ll12
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*, ...)