Special epilogue for vararg functions. We cannot do a pop to pc because
authorEvan Cheng <evan.cheng@apple.com>
Thu, 1 Feb 2007 01:49:46 +0000 (01:49 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 1 Feb 2007 01:49:46 +0000 (01:49 +0000)
there follows a sp increment for the va register save region. Instead issue
a separate pop to another register, increment sp, and then return:
        pop {r4, r5, r6, r7}
        pop {r3}
        add sp, #3 * 4
        bx r3

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33739 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/ARMRegisterInfo.cpp

index 5fbd4121c43ce849d5134b6bf9653da68ecaffa8..416d4305037e96506f586db64a23dfbf39a3b3f2 100644 (file)
@@ -165,8 +165,11 @@ def tPICADD : TIt<(ops GPR:$dst, GPR:$lhs, pclabel:$cp),
 //  Control Flow Instructions.
 //
 
-let isReturn = 1, isTerminator = 1 in
+let isReturn = 1, isTerminator = 1 in {
   def tBX_RET : TI<(ops), "bx lr", [(ARMretflag)]>;
+  // Alternative return instruction used by vararg functions.
+  def tBX_RET_vararg : TI<(ops GPR:$dst), "bx $dst", []>;
+}
 
 // FIXME: remove when we have a way to marking a MI with these properties.
 let isLoad = 1, isReturn = 1, isTerminator = 1 in
index d76aedb0afde055a58717ae31d4d1be9c081b021..3b8dba3211b99c5e05deb8a269b02e1ddece3c10 100644 (file)
@@ -104,11 +104,15 @@ bool ARMRegisterInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
   if (!AFI->isThumbFunction() || CSI.empty())
     return false;
 
+  bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
   MachineInstr *PopMI = new MachineInstr(TII.get(ARM::tPOP));
   MBB.insert(MI, PopMI);
   for (unsigned i = CSI.size(); i != 0; --i) {
     unsigned Reg = CSI[i-1].getReg();
     if (Reg == ARM::LR) {
+      // Special epilogue for vararg functions. See emitEpilogue
+      if (isVarArg)
+        continue;
       Reg = ARM::PC;
       PopMI->setInstrDescriptor(TII.get(ARM::tPOP_RET));
       MBB.erase(MI);
@@ -1115,9 +1119,15 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
   NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
                AFI->getGPRCalleeSavedArea2Size() +
                AFI->getDPRCalleeSavedAreaSize());
-  if (isThumb)
-    emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
-  else {
+  if (isThumb) {
+    if (MBBI->getOpcode() == ARM::tBX_RET &&
+        &MBB.front() != MBBI &&
+        prior(MBBI)->getOpcode() == ARM::tPOP) {
+      MachineBasicBlock::iterator PMBBI = prior(MBBI);
+      emitSPUpdate(MBB, PMBBI, NumBytes, isThumb, TII);
+    } else
+      emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
+  } else {
     // Darwin ABI requires FP to point to the stack slot that contains the
     // previous FP.
     if (STI.isTargetDarwin() || hasFP(MF)) {
@@ -1149,8 +1159,14 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
     emitSPUpdate(MBB, MBBI, AFI->getGPRCalleeSavedArea1Size(), false, TII);
   }
 
-  if (VARegSaveSize)
+  if (VARegSaveSize) {
+    // Epilogue for vararg functions: pop LR to R3 and branch off it.
+    // FIXME: Verify this is still ok when R3 is no longer being reserved.
+    BuildMI(MBB, MBBI, TII.get(ARM::tPOP)).addReg(ARM::R3);
     emitSPUpdate(MBB, MBBI, VARegSaveSize, isThumb, TII);
+    BuildMI(MBB, MBBI, TII.get(ARM::tBX_RET_vararg)).addReg(ARM::R3);
+    MBB.erase(MBBI);
+  }
 }
 
 unsigned ARMRegisterInfo::getRARegister() const {