llvm.org GIT mirror llvm / 9d945f7
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 Evan Cheng 13 years ago
2 changed file(s) with 24 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
164164 // Control Flow Instructions.
165165 //
166166
167 let isReturn = 1, isTerminator = 1 in
167 let isReturn = 1, isTerminator = 1 in {
168168 def tBX_RET : TI<(ops), "bx lr", [(ARMretflag)]>;
169 // Alternative return instruction used by vararg functions.
170 def tBX_RET_vararg : TI<(ops GPR:$dst), "bx $dst", []>;
171 }
169172
170173 // FIXME: remove when we have a way to marking a MI with these properties.
171174 let isLoad = 1, isReturn = 1, isTerminator = 1 in
103103 if (!AFI->isThumbFunction() || CSI.empty())
104104 return false;
105105
106 bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
106107 MachineInstr *PopMI = new MachineInstr(TII.get(ARM::tPOP));
107108 MBB.insert(MI, PopMI);
108109 for (unsigned i = CSI.size(); i != 0; --i) {
109110 unsigned Reg = CSI[i-1].getReg();
110111 if (Reg == ARM::LR) {
112 // Special epilogue for vararg functions. See emitEpilogue
113 if (isVarArg)
114 continue;
111115 Reg = ARM::PC;
112116 PopMI->setInstrDescriptor(TII.get(ARM::tPOP_RET));
113117 MBB.erase(MI);
11141118 NumBytes -= (AFI->getGPRCalleeSavedArea1Size() +
11151119 AFI->getGPRCalleeSavedArea2Size() +
11161120 AFI->getDPRCalleeSavedAreaSize());
1117 if (isThumb)
1118 emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
1119 else {
1121 if (isThumb) {
1122 if (MBBI->getOpcode() == ARM::tBX_RET &&
1123 &MBB.front() != MBBI &&
1124 prior(MBBI)->getOpcode() == ARM::tPOP) {
1125 MachineBasicBlock::iterator PMBBI = prior(MBBI);
1126 emitSPUpdate(MBB, PMBBI, NumBytes, isThumb, TII);
1127 } else
1128 emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
1129 } else {
11201130 // Darwin ABI requires FP to point to the stack slot that contains the
11211131 // previous FP.
11221132 if (STI.isTargetDarwin() || hasFP(MF)) {
11481158 emitSPUpdate(MBB, MBBI, AFI->getGPRCalleeSavedArea1Size(), false, TII);
11491159 }
11501160
1151 if (VARegSaveSize)
1161 if (VARegSaveSize) {
1162 // Epilogue for vararg functions: pop LR to R3 and branch off it.
1163 // FIXME: Verify this is still ok when R3 is no longer being reserved.
1164 BuildMI(MBB, MBBI, TII.get(ARM::tPOP)).addReg(ARM::R3);
11521165 emitSPUpdate(MBB, MBBI, VARegSaveSize, isThumb, TII);
1166 BuildMI(MBB, MBBI, TII.get(ARM::tBX_RET_vararg)).addReg(ARM::R3);
1167 MBB.erase(MBBI);
1168 }
11531169 }
11541170
11551171 unsigned ARMRegisterInfo::getRARegister() const {