OSDN Git Service

initial support for variable number of arguments
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 8 Aug 2006 13:02:29 +0000 (13:02 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 8 Aug 2006 13:02:29 +0000 (13:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29567 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMRegisterInfo.cpp
test/CodeGen/ARM/vargs.ll [new file with mode: 0644]

index 915684a..1ef5bf4 100644 (file)
@@ -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.
index a9fe705..719ce32 100644 (file)
@@ -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 (file)
index 0000000..858c463
--- /dev/null
@@ -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*, ...)