aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-02-01 01:49:46 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-02-01 01:49:46 +0000
commit9d945f78e5d26dac6778665bd7018a8fb3fd38c5 (patch)
tree4c813dfd10041c1c292fcffd7b51a2244899f2e1
parent3281528de4755f8f4653bf6ff509ec88d795f975 (diff)
downloadexternal_llvm-9d945f78e5d26dac6778665bd7018a8fb3fd38c5.zip
external_llvm-9d945f78e5d26dac6778665bd7018a8fb3fd38c5.tar.gz
external_llvm-9d945f78e5d26dac6778665bd7018a8fb3fd38c5.tar.bz2
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
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td5
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp24
2 files changed, 24 insertions, 5 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 5fbd412..416d430 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 d76aedb..3b8dba3 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 {