Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 1 | //===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file contains the ARC implementation of the TargetFrameLowering class. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "ARCFrameLowering.h" |
| 15 | #include "ARCMachineFunctionInfo.h" |
| 16 | #include "ARCSubtarget.h" |
| 17 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
| 18 | #include "llvm/CodeGen/MachineModuleInfo.h" |
| 19 | #include "llvm/CodeGen/RegisterScavenging.h" |
David Blaikie | b3bde2e | 2017-11-17 01:07:10 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 21 | #include "llvm/IR/Function.h" |
| 22 | #include "llvm/Support/Debug.h" |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 23 | |
| 24 | #define DEBUG_TYPE "arc-frame-lowering" |
| 25 | |
| 26 | using namespace llvm; |
| 27 | |
| 28 | static cl::opt<bool> |
| 29 | UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden, |
| 30 | cl::desc("Use arc callee save/restore functions"), |
| 31 | cl::init(true)); |
| 32 | |
| 33 | static const char *store_funclet_name[] = { |
| 34 | "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18", |
| 35 | "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22", |
| 36 | "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25", |
| 37 | }; |
| 38 | |
| 39 | static const char *load_funclet_name[] = { |
| 40 | "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18", |
| 41 | "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22", |
| 42 | "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25", |
| 43 | }; |
| 44 | |
| 45 | static void generateStackAdjustment(MachineBasicBlock &MBB, |
| 46 | MachineBasicBlock::iterator MBBI, |
| 47 | const ARCInstrInfo &TII, DebugLoc dl, |
| 48 | int Amount, int StackPtr) { |
| 49 | unsigned AdjOp; |
| 50 | if (!Amount) |
| 51 | return; |
| 52 | bool Positive; |
| 53 | unsigned AbsAmount; |
| 54 | if (Amount < 0) { |
| 55 | AbsAmount = -Amount; |
| 56 | Positive = false; |
| 57 | } else { |
| 58 | AbsAmount = Amount; |
| 59 | Positive = true; |
| 60 | } |
| 61 | |
| 62 | DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," << AbsAmount |
| 63 | << "\n"); |
| 64 | |
| 65 | assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned."); |
| 66 | if (isUInt<6>(AbsAmount)) |
| 67 | AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6; |
| 68 | else |
| 69 | AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm; |
| 70 | |
| 71 | BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr) |
| 72 | .addReg(StackPtr) |
| 73 | .addImm(AbsAmount); |
| 74 | } |
| 75 | |
| 76 | static unsigned |
| 77 | determineLastCalleeSave(const std::vector<CalleeSavedInfo> &CSI) { |
| 78 | unsigned Last = 0; |
| 79 | for (auto Reg : CSI) { |
| 80 | assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 && |
| 81 | "Unexpected callee saved reg."); |
| 82 | if (Reg.getReg() > Last) |
| 83 | Last = Reg.getReg(); |
| 84 | } |
| 85 | return Last; |
| 86 | } |
| 87 | |
| 88 | void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF, |
| 89 | BitVector &SavedRegs, |
| 90 | RegScavenger *RS) const { |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 91 | DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName() |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 92 | << "\n"); |
| 93 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
| 94 | SavedRegs.set(ARC::BLINK); |
| 95 | } |
| 96 | |
| 97 | void ARCFrameLowering::adjustStackToMatchRecords( |
| 98 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
| 99 | bool Allocate) const { |
| 100 | MachineFunction &MF = *MBB.getParent(); |
| 101 | int ScalarAlloc = MF.getFrameInfo().getStackSize(); |
| 102 | |
| 103 | if (Allocate) { |
| 104 | // Allocate by adjusting by the negative of what the record holder tracked |
| 105 | // it tracked a positive offset in a downward growing stack. |
| 106 | ScalarAlloc = -ScalarAlloc; |
| 107 | } |
| 108 | |
| 109 | generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(), |
| 110 | ScalarAlloc, ARC::SP); |
| 111 | } |
| 112 | |
| 113 | /// Insert prolog code into the function. |
| 114 | /// For ARC, this inserts a call to a function that puts required callee saved |
| 115 | /// registers onto the stack, when enough callee saved registers are required. |
| 116 | void ARCFrameLowering::emitPrologue(MachineFunction &MF, |
| 117 | MachineBasicBlock &MBB) const { |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 118 | DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 119 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
| 120 | MachineModuleInfo &MMI = MF.getMMI(); |
| 121 | MCContext &Context = MMI.getContext(); |
| 122 | const MCRegisterInfo *MRI = Context.getRegisterInfo(); |
| 123 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
| 124 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
| 125 | // Debug location must be unknown since the first debug location is used |
| 126 | // to determine the end of the prologue. |
| 127 | DebugLoc dl; |
| 128 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 129 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
| 130 | unsigned Last = determineLastCalleeSave(CSI); |
| 131 | unsigned StackSlotsUsedByFunclet = 0; |
| 132 | bool SavedBlink = false; |
| 133 | unsigned AlreadyAdjusted = 0; |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 134 | if (MF.getFunction().isVarArg()) { |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 135 | // Add in the varargs area here first. |
| 136 | DEBUG(dbgs() << "Varargs\n"); |
| 137 | unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex()); |
| 138 | BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) |
| 139 | .addReg(ARC::SP) |
| 140 | .addReg(ARC::SP) |
| 141 | .addImm(VarArgsBytes); |
| 142 | } |
| 143 | if (hasFP(MF)) { |
| 144 | DEBUG(dbgs() << "Saving FP\n"); |
| 145 | BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9)) |
| 146 | .addReg(ARC::SP, RegState::Define) |
| 147 | .addReg(ARC::FP) |
| 148 | .addReg(ARC::SP) |
| 149 | .addImm(-4); |
| 150 | AlreadyAdjusted += 4; |
| 151 | } |
| 152 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
| 153 | DEBUG(dbgs() << "Creating store funclet.\n"); |
| 154 | // BL to __save_r13_to_<TRI->getRegAsmName()> |
| 155 | StackSlotsUsedByFunclet = Last - ARC::R12; |
| 156 | BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); |
| 157 | BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) |
| 158 | .addReg(ARC::SP) |
| 159 | .addReg(ARC::SP) |
| 160 | .addImm(4 * StackSlotsUsedByFunclet); |
| 161 | BuildMI(MBB, MBBI, dl, TII->get(ARC::BL)) |
| 162 | .addExternalSymbol(store_funclet_name[Last - ARC::R15]) |
| 163 | .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); |
| 164 | AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1); |
| 165 | SavedBlink = true; |
| 166 | } |
| 167 | // If we haven't saved BLINK, but we need to...do that now. |
| 168 | if (MFI.hasCalls() && !SavedBlink) { |
| 169 | DEBUG(dbgs() << "Creating save blink.\n"); |
| 170 | BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); |
| 171 | AlreadyAdjusted += 4; |
| 172 | } |
| 173 | if (AFI->MaxCallStackReq > 0) |
| 174 | MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq); |
| 175 | // We have already saved some of the stack... |
| 176 | DEBUG(dbgs() << "Adjusting stack by: " |
| 177 | << (MFI.getStackSize() - AlreadyAdjusted) << "\n"); |
| 178 | generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl, |
| 179 | -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP); |
| 180 | |
| 181 | if (hasFP(MF)) { |
| 182 | DEBUG(dbgs() << "Setting FP from SP.\n"); |
| 183 | BuildMI(MBB, MBBI, dl, |
| 184 | TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6 |
| 185 | : ARC::ADD_rrlimm), |
| 186 | ARC::FP) |
| 187 | .addReg(ARC::SP) |
| 188 | .addImm(MFI.getStackSize()); |
| 189 | } |
| 190 | |
| 191 | // Emit CFI records: |
| 192 | // .cfi_def_cfa_offset StackSize |
| 193 | // .cfi_offset fp, -StackSize |
| 194 | // .cfi_offset blink, -StackSize+4 |
| 195 | unsigned CFIIndex = MF.addFrameInst( |
| 196 | MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize())); |
| 197 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
| 198 | .addCFIIndex(CFIIndex) |
| 199 | .setMIFlags(MachineInstr::FrameSetup); |
| 200 | |
| 201 | int CurOffset = -4; |
| 202 | if (hasFP(MF)) { |
| 203 | CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( |
| 204 | nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset)); |
| 205 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
| 206 | .addCFIIndex(CFIIndex) |
| 207 | .setMIFlags(MachineInstr::FrameSetup); |
| 208 | CurOffset -= 4; |
| 209 | } |
| 210 | |
| 211 | if (MFI.hasCalls()) { |
| 212 | CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( |
| 213 | nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset)); |
| 214 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
| 215 | .addCFIIndex(CFIIndex) |
| 216 | .setMIFlags(MachineInstr::FrameSetup); |
| 217 | } |
| 218 | // CFI for the rest of the registers. |
| 219 | for (const auto &Entry : CSI) { |
| 220 | unsigned Reg = Entry.getReg(); |
| 221 | int FI = Entry.getFrameIdx(); |
| 222 | // Skip BLINK and FP. |
| 223 | if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK)) |
| 224 | continue; |
| 225 | CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( |
| 226 | nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); |
| 227 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
| 228 | .addCFIIndex(CFIIndex) |
| 229 | .setMIFlags(MachineInstr::FrameSetup); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | /// Insert epilog code into the function. |
| 234 | /// For ARC, this inserts a call to a function that restores callee saved |
| 235 | /// registers onto the stack, when enough callee saved registers are required. |
| 236 | void ARCFrameLowering::emitEpilogue(MachineFunction &MF, |
| 237 | MachineBasicBlock &MBB) const { |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 238 | DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 239 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
| 240 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
| 241 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
| 242 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 243 | uint64_t StackSize = MF.getFrameInfo().getStackSize(); |
| 244 | bool SavedBlink = false; |
| 245 | unsigned AmountAboveFunclet = 0; |
| 246 | // If we have variable sized frame objects, then we have to move |
| 247 | // the stack pointer to a known spot (fp - StackSize). |
| 248 | // Then, replace the frame pointer by (new) [sp,StackSize-4]. |
| 249 | // Then, move the stack pointer the rest of the way (sp = sp + StackSize). |
| 250 | if (hasFP(MF)) { |
| 251 | BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARC::SUB_rru6), ARC::SP) |
| 252 | .addReg(ARC::FP) |
| 253 | .addImm(StackSize); |
| 254 | AmountAboveFunclet += 4; |
| 255 | } |
| 256 | |
| 257 | // Now, move the stack pointer to the bottom of the save area for the funclet. |
| 258 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
| 259 | unsigned Last = determineLastCalleeSave(CSI); |
| 260 | unsigned StackSlotsUsedByFunclet = 0; |
| 261 | // Now, restore the callee save registers. |
| 262 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
| 263 | // BL to __ld_r13_to_<TRI->getRegAsmName()> |
| 264 | StackSlotsUsedByFunclet = Last - ARC::R12; |
| 265 | AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1); |
| 266 | SavedBlink = true; |
| 267 | } |
| 268 | |
| 269 | if (MFI.hasCalls() && !SavedBlink) { |
| 270 | AmountAboveFunclet += 4; |
| 271 | SavedBlink = true; |
| 272 | } |
| 273 | |
| 274 | // Move the stack pointer up to the point of the funclet. |
| 275 | if (StackSize - AmountAboveFunclet) { |
| 276 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6)) |
| 277 | .addReg(ARC::SP) |
| 278 | .addReg(ARC::SP) |
| 279 | .addImm(StackSize - AmountAboveFunclet); |
| 280 | } |
| 281 | |
| 282 | if (StackSlotsUsedByFunclet) { |
| 283 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL)) |
| 284 | .addExternalSymbol(load_funclet_name[Last - ARC::R15]) |
| 285 | .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); |
| 286 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6)) |
| 287 | .addReg(ARC::SP) |
| 288 | .addReg(ARC::SP) |
| 289 | .addImm(4 * (StackSlotsUsedByFunclet)); |
| 290 | } |
| 291 | // Now, pop blink if necessary. |
| 292 | if (SavedBlink) { |
| 293 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK)); |
| 294 | } |
| 295 | // Now, pop fp if necessary. |
| 296 | if (hasFP(MF)) { |
| 297 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9)) |
| 298 | .addReg(ARC::SP, RegState::Define) |
| 299 | .addReg(ARC::FP, RegState::Define) |
| 300 | .addReg(ARC::SP) |
| 301 | .addImm(4); |
| 302 | } |
| 303 | |
| 304 | // Relieve the varargs area if necessary. |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 305 | if (MF.getFunction().isVarArg()) { |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 306 | // Add in the varargs area here first. |
| 307 | DEBUG(dbgs() << "Varargs\n"); |
| 308 | unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex()); |
| 309 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6)) |
| 310 | .addReg(ARC::SP) |
| 311 | .addReg(ARC::SP) |
| 312 | .addImm(VarArgsBytes); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | static std::vector<CalleeSavedInfo>::iterator |
| 317 | getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) { |
| 318 | for (auto I = V.begin(), E = V.end(); I != E; ++I) { |
| 319 | if (reg == I->getReg()) |
| 320 | return I; |
| 321 | } |
| 322 | return V.end(); |
| 323 | } |
| 324 | |
| 325 | bool ARCFrameLowering::assignCalleeSavedSpillSlots( |
| 326 | MachineFunction &MF, const TargetRegisterInfo *TRI, |
| 327 | std::vector<CalleeSavedInfo> &CSI) const { |
| 328 | // Use this opportunity to assign the spill slots for all of the potential |
| 329 | // callee save registers (blink, fp, r13->r25) that we care about the |
| 330 | // placement for. We can calculate all of that data here. |
| 331 | int CurOffset = -4; |
| 332 | unsigned Last = determineLastCalleeSave(CSI); |
| 333 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 334 | if (hasFP(MF)) { |
| 335 | // Create a fixed slot at for FP |
| 336 | int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true); |
| 337 | DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at " |
| 338 | << CurOffset << "\n"); |
| 339 | (void)StackObj; |
| 340 | CurOffset -= 4; |
| 341 | } |
| 342 | if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) { |
| 343 | // Create a fixed slot for BLINK. |
| 344 | int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true); |
| 345 | DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for BLINK at " |
| 346 | << CurOffset << "\n"); |
| 347 | (void)StackObj; |
| 348 | CurOffset -= 4; |
| 349 | } |
| 350 | |
| 351 | // Create slots for last down to r13. |
| 352 | for (unsigned Which = Last; Which > ARC::R12; Which--) { |
| 353 | auto RegI = getSavedReg(CSI, Which); |
| 354 | if (RegI == CSI.end() || RegI->getFrameIdx() == 0) { |
| 355 | // Always create the stack slot. If for some reason the register isn't in |
| 356 | // the save list, then don't worry about it. |
| 357 | int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true); |
| 358 | if (RegI != CSI.end()) |
| 359 | RegI->setFrameIdx(FI); |
| 360 | } else |
| 361 | MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset); |
| 362 | CurOffset -= 4; |
| 363 | } |
| 364 | for (auto &I : CSI) { |
| 365 | if (I.getReg() > ARC::R12) |
| 366 | continue; |
| 367 | if (I.getFrameIdx() == 0) { |
| 368 | I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true)); |
| 369 | DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx() |
| 370 | << ") for other register at " << CurOffset << "\n"); |
| 371 | } else { |
| 372 | MFI.setObjectOffset(I.getFrameIdx(), CurOffset); |
| 373 | DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx() |
| 374 | << ") for other register at " << CurOffset << "\n"); |
| 375 | } |
| 376 | CurOffset -= 4; |
| 377 | } |
| 378 | return true; |
| 379 | } |
| 380 | |
| 381 | bool ARCFrameLowering::spillCalleeSavedRegisters( |
| 382 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
| 383 | const std::vector<CalleeSavedInfo> &CSI, |
| 384 | const TargetRegisterInfo *TRI) const { |
| 385 | DEBUG(dbgs() << "Spill callee saved registers: " |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 386 | << MBB.getParent()->getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 387 | // There are routines for saving at least 3 registers (r13 to r15, etc.) |
| 388 | unsigned Last = determineLastCalleeSave(CSI); |
| 389 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
| 390 | // Use setObjectOffset for these registers. |
| 391 | // Needs to be in or before processFunctionBeforeFrameFinalized. |
| 392 | // Or, do assignCalleeSaveSpillSlots? |
| 393 | // Will be handled in prolog. |
| 394 | return true; |
| 395 | } |
| 396 | return false; |
| 397 | } |
| 398 | |
| 399 | bool ARCFrameLowering::restoreCalleeSavedRegisters( |
| 400 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
| 401 | std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { |
| 402 | DEBUG(dbgs() << "Restore callee saved registers: " |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 403 | << MBB.getParent()->getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 404 | // There are routines for saving at least 3 registers (r13 to r15, etc.) |
| 405 | unsigned Last = determineLastCalleeSave(CSI); |
| 406 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
| 407 | // Will be handled in epilog. |
| 408 | return true; |
| 409 | } |
| 410 | return false; |
| 411 | } |
| 412 | |
| 413 | // Adjust local variables that are 4-bytes or larger to 4-byte boundary |
| 414 | void ARCFrameLowering::processFunctionBeforeFrameFinalized( |
| 415 | MachineFunction &MF, RegScavenger *RS) const { |
| 416 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); |
| 417 | DEBUG(dbgs() << "Process function before frame finalized: " |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 418 | << MF.getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 419 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
| 420 | DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n"); |
| 421 | const TargetRegisterClass *RC = &ARC::GPR32RegClass; |
| 422 | if (MFI.hasStackObjects()) { |
| 423 | int RegScavFI = MFI.CreateStackObject( |
| 424 | RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false); |
| 425 | RS->addScavengingFrameIndex(RegScavFI); |
| 426 | DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI << "\n"); |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | static void emitRegUpdate(MachineBasicBlock &MBB, |
| 431 | MachineBasicBlock::iterator &MBBI, DebugLoc dl, |
| 432 | unsigned Reg, int NumBytes, bool IsAdd, |
| 433 | const ARCInstrInfo *TII) { |
| 434 | unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6; |
| 435 | BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg) |
| 436 | .addReg(Reg, RegState::Kill) |
| 437 | .addImm(NumBytes); |
| 438 | } |
| 439 | |
| 440 | MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr( |
| 441 | MachineFunction &MF, MachineBasicBlock &MBB, |
| 442 | MachineBasicBlock::iterator I) const { |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 443 | DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n"); |
Pete Couperus | 2d1f6d6 | 2017-08-24 15:40:33 +0000 | [diff] [blame] | 444 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
| 445 | MachineInstr &Old = *I; |
| 446 | DebugLoc dl = Old.getDebugLoc(); |
| 447 | unsigned Amt = Old.getOperand(0).getImm(); |
| 448 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
| 449 | if (!hasFP(MF)) { |
| 450 | if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN) |
| 451 | AFI->MaxCallStackReq = Amt; |
| 452 | } else { |
| 453 | if (Amt != 0) { |
| 454 | assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN || |
| 455 | Old.getOpcode() == ARC::ADJCALLSTACKUP) && |
| 456 | "Unknown Frame Pseudo."); |
| 457 | bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP); |
| 458 | emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII); |
| 459 | } |
| 460 | } |
| 461 | return MBB.erase(I); |
| 462 | } |
| 463 | |
| 464 | bool ARCFrameLowering::hasFP(const MachineFunction &MF) const { |
| 465 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); |
| 466 | bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) || |
| 467 | MF.getFrameInfo().hasVarSizedObjects() || |
| 468 | MF.getFrameInfo().isFrameAddressTaken() || |
| 469 | RegInfo->needsStackRealignment(MF); |
| 470 | return HasFP; |
| 471 | } |