From e7e966de5e14e2d39ff0ea4ff597aacafab0bb5c 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 llvm-svn: 33739 --- llvm/lib/Target/ARM/ARMInstrThumb.td | 5 ++++- llvm/lib/Target/ARM/ARMRegisterInfo.cpp | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 5fbd4121c43c..416d4305037e 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/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/llvm/lib/Target/ARM/ARMRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterInfo.cpp index d76aedb0afde..3b8dba3211b9 100644 --- a/llvm/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/llvm/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 {