From 9d945f78e5d26dac6778665bd7018a8fb3fd38c5 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 1 Feb 2007 01:49:46 +0000 Subject: [PATCH] Special epilogue for vararg functions. We cannot do a pop to pc because 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 | 5 ++++- lib/Target/ARM/ARMRegisterInfo.cpp | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 5fbd4121c43..416d4305037 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -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 diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index d76aedb0afd..3b8dba3211b 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -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 { -- 2.34.1