diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-02-01 01:49:46 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-02-01 01:49:46 +0000 |
commit | 9d945f78e5d26dac6778665bd7018a8fb3fd38c5 (patch) | |
tree | 4c813dfd10041c1c292fcffd7b51a2244899f2e1 /lib/Target/ARM/ARMRegisterInfo.cpp | |
parent | 3281528de4755f8f4653bf6ff509ec88d795f975 (diff) |
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
Diffstat (limited to 'lib/Target/ARM/ARMRegisterInfo.cpp')
-rw-r--r-- | lib/Target/ARM/ARMRegisterInfo.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index d76aedb0af..3b8dba3211 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 { |