1326938Sdim//===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===// 2326938Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326938Sdim// 7326938Sdim//===----------------------------------------------------------------------===// 8326938Sdim// 9326938Sdim// This file contains the ARC implementation of the TargetFrameLowering class. 10326938Sdim// 11326938Sdim//===----------------------------------------------------------------------===// 12326938Sdim 13326938Sdim#include "ARCFrameLowering.h" 14326938Sdim#include "ARCMachineFunctionInfo.h" 15326938Sdim#include "ARCSubtarget.h" 16326938Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 17326938Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 18326938Sdim#include "llvm/CodeGen/RegisterScavenging.h" 19326938Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 20326938Sdim#include "llvm/IR/Function.h" 21326938Sdim#include "llvm/Support/Debug.h" 22326938Sdim 23326938Sdim#define DEBUG_TYPE "arc-frame-lowering" 24326938Sdim 25326938Sdimusing namespace llvm; 26326938Sdim 27326938Sdimstatic cl::opt<bool> 28326938Sdim UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden, 29326938Sdim cl::desc("Use arc callee save/restore functions"), 30326938Sdim cl::init(true)); 31326938Sdim 32326938Sdimstatic const char *store_funclet_name[] = { 33326938Sdim "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18", 34326938Sdim "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22", 35326938Sdim "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25", 36326938Sdim}; 37326938Sdim 38326938Sdimstatic const char *load_funclet_name[] = { 39326938Sdim "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18", 40326938Sdim "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22", 41326938Sdim "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25", 42326938Sdim}; 43326938Sdim 44326938Sdimstatic void generateStackAdjustment(MachineBasicBlock &MBB, 45326938Sdim MachineBasicBlock::iterator MBBI, 46326938Sdim const ARCInstrInfo &TII, DebugLoc dl, 47326938Sdim int Amount, int StackPtr) { 48326938Sdim unsigned AdjOp; 49326938Sdim if (!Amount) 50326938Sdim return; 51326938Sdim bool Positive; 52326938Sdim unsigned AbsAmount; 53326938Sdim if (Amount < 0) { 54326938Sdim AbsAmount = -Amount; 55326938Sdim Positive = false; 56326938Sdim } else { 57326938Sdim AbsAmount = Amount; 58326938Sdim Positive = true; 59326938Sdim } 60326938Sdim 61341825Sdim LLVM_DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," 62341825Sdim << AbsAmount << "\n"); 63326938Sdim 64326938Sdim assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned."); 65326938Sdim if (isUInt<6>(AbsAmount)) 66326938Sdim AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6; 67353358Sdim else if (isInt<12>(AbsAmount)) 68353358Sdim AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12; 69326938Sdim else 70326938Sdim AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm; 71326938Sdim 72326938Sdim BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr) 73326938Sdim .addReg(StackPtr) 74326938Sdim .addImm(AbsAmount); 75326938Sdim} 76326938Sdim 77326938Sdimstatic unsigned 78326938SdimdetermineLastCalleeSave(const std::vector<CalleeSavedInfo> &CSI) { 79326938Sdim unsigned Last = 0; 80326938Sdim for (auto Reg : CSI) { 81326938Sdim assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 && 82326938Sdim "Unexpected callee saved reg."); 83326938Sdim if (Reg.getReg() > Last) 84326938Sdim Last = Reg.getReg(); 85326938Sdim } 86326938Sdim return Last; 87326938Sdim} 88326938Sdim 89326938Sdimvoid ARCFrameLowering::determineCalleeSaves(MachineFunction &MF, 90326938Sdim BitVector &SavedRegs, 91326938Sdim RegScavenger *RS) const { 92341825Sdim LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName() << "\n"); 93326938Sdim TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 94326938Sdim SavedRegs.set(ARC::BLINK); 95326938Sdim} 96326938Sdim 97326938Sdimvoid ARCFrameLowering::adjustStackToMatchRecords( 98326938Sdim MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 99326938Sdim bool Allocate) const { 100326938Sdim MachineFunction &MF = *MBB.getParent(); 101326938Sdim int ScalarAlloc = MF.getFrameInfo().getStackSize(); 102326938Sdim 103326938Sdim if (Allocate) { 104326938Sdim // Allocate by adjusting by the negative of what the record holder tracked 105326938Sdim // it tracked a positive offset in a downward growing stack. 106326938Sdim ScalarAlloc = -ScalarAlloc; 107326938Sdim } 108326938Sdim 109326938Sdim generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(), 110326938Sdim ScalarAlloc, ARC::SP); 111326938Sdim} 112326938Sdim 113326938Sdim/// Insert prolog code into the function. 114326938Sdim/// For ARC, this inserts a call to a function that puts required callee saved 115326938Sdim/// registers onto the stack, when enough callee saved registers are required. 116326938Sdimvoid ARCFrameLowering::emitPrologue(MachineFunction &MF, 117326938Sdim MachineBasicBlock &MBB) const { 118341825Sdim LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n"); 119326938Sdim auto *AFI = MF.getInfo<ARCFunctionInfo>(); 120326938Sdim MachineModuleInfo &MMI = MF.getMMI(); 121326938Sdim MCContext &Context = MMI.getContext(); 122326938Sdim const MCRegisterInfo *MRI = Context.getRegisterInfo(); 123326938Sdim const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); 124326938Sdim MachineBasicBlock::iterator MBBI = MBB.begin(); 125326938Sdim // Debug location must be unknown since the first debug location is used 126326938Sdim // to determine the end of the prologue. 127326938Sdim DebugLoc dl; 128326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 129326938Sdim const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 130326938Sdim unsigned Last = determineLastCalleeSave(CSI); 131326938Sdim unsigned StackSlotsUsedByFunclet = 0; 132326938Sdim bool SavedBlink = false; 133326938Sdim unsigned AlreadyAdjusted = 0; 134326938Sdim if (MF.getFunction().isVarArg()) { 135326938Sdim // Add in the varargs area here first. 136341825Sdim LLVM_DEBUG(dbgs() << "Varargs\n"); 137326938Sdim unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex()); 138353358Sdim unsigned Opc = ARC::SUB_rrlimm; 139353358Sdim if (isUInt<6>(VarArgsBytes)) 140353358Sdim Opc = ARC::SUB_rru6; 141353358Sdim else if (isInt<12>(VarArgsBytes)) 142353358Sdim Opc = ARC::SUB_rrs12; 143353358Sdim BuildMI(MBB, MBBI, dl, TII->get(Opc), ARC::SP) 144326938Sdim .addReg(ARC::SP) 145326938Sdim .addImm(VarArgsBytes); 146326938Sdim } 147326938Sdim if (hasFP(MF)) { 148341825Sdim LLVM_DEBUG(dbgs() << "Saving FP\n"); 149326938Sdim BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9)) 150326938Sdim .addReg(ARC::SP, RegState::Define) 151326938Sdim .addReg(ARC::FP) 152326938Sdim .addReg(ARC::SP) 153326938Sdim .addImm(-4); 154326938Sdim AlreadyAdjusted += 4; 155326938Sdim } 156326938Sdim if (UseSaveRestoreFunclet && Last > ARC::R14) { 157341825Sdim LLVM_DEBUG(dbgs() << "Creating store funclet.\n"); 158326938Sdim // BL to __save_r13_to_<TRI->getRegAsmName()> 159326938Sdim StackSlotsUsedByFunclet = Last - ARC::R12; 160326938Sdim BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); 161326938Sdim BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) 162326938Sdim .addReg(ARC::SP) 163326938Sdim .addReg(ARC::SP) 164326938Sdim .addImm(4 * StackSlotsUsedByFunclet); 165326938Sdim BuildMI(MBB, MBBI, dl, TII->get(ARC::BL)) 166326938Sdim .addExternalSymbol(store_funclet_name[Last - ARC::R15]) 167326938Sdim .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); 168326938Sdim AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1); 169326938Sdim SavedBlink = true; 170326938Sdim } 171326938Sdim // If we haven't saved BLINK, but we need to...do that now. 172326938Sdim if (MFI.hasCalls() && !SavedBlink) { 173341825Sdim LLVM_DEBUG(dbgs() << "Creating save blink.\n"); 174326938Sdim BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); 175326938Sdim AlreadyAdjusted += 4; 176326938Sdim } 177326938Sdim if (AFI->MaxCallStackReq > 0) 178326938Sdim MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq); 179326938Sdim // We have already saved some of the stack... 180341825Sdim LLVM_DEBUG(dbgs() << "Adjusting stack by: " 181341825Sdim << (MFI.getStackSize() - AlreadyAdjusted) << "\n"); 182326938Sdim generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl, 183326938Sdim -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP); 184326938Sdim 185326938Sdim if (hasFP(MF)) { 186341825Sdim LLVM_DEBUG(dbgs() << "Setting FP from SP.\n"); 187326938Sdim BuildMI(MBB, MBBI, dl, 188326938Sdim TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6 189326938Sdim : ARC::ADD_rrlimm), 190326938Sdim ARC::FP) 191326938Sdim .addReg(ARC::SP) 192326938Sdim .addImm(MFI.getStackSize()); 193326938Sdim } 194326938Sdim 195326938Sdim // Emit CFI records: 196326938Sdim // .cfi_def_cfa_offset StackSize 197326938Sdim // .cfi_offset fp, -StackSize 198326938Sdim // .cfi_offset blink, -StackSize+4 199326938Sdim unsigned CFIIndex = MF.addFrameInst( 200326938Sdim MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize())); 201326938Sdim BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) 202326938Sdim .addCFIIndex(CFIIndex) 203326938Sdim .setMIFlags(MachineInstr::FrameSetup); 204326938Sdim 205326938Sdim int CurOffset = -4; 206326938Sdim if (hasFP(MF)) { 207326938Sdim CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 208326938Sdim nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset)); 209326938Sdim BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) 210326938Sdim .addCFIIndex(CFIIndex) 211326938Sdim .setMIFlags(MachineInstr::FrameSetup); 212326938Sdim CurOffset -= 4; 213326938Sdim } 214326938Sdim 215326938Sdim if (MFI.hasCalls()) { 216326938Sdim CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 217326938Sdim nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset)); 218326938Sdim BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) 219326938Sdim .addCFIIndex(CFIIndex) 220326938Sdim .setMIFlags(MachineInstr::FrameSetup); 221326938Sdim } 222326938Sdim // CFI for the rest of the registers. 223326938Sdim for (const auto &Entry : CSI) { 224326938Sdim unsigned Reg = Entry.getReg(); 225326938Sdim int FI = Entry.getFrameIdx(); 226326938Sdim // Skip BLINK and FP. 227326938Sdim if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK)) 228326938Sdim continue; 229326938Sdim CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 230326938Sdim nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 231326938Sdim BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) 232326938Sdim .addCFIIndex(CFIIndex) 233326938Sdim .setMIFlags(MachineInstr::FrameSetup); 234326938Sdim } 235326938Sdim} 236326938Sdim 237326938Sdim/// Insert epilog code into the function. 238326938Sdim/// For ARC, this inserts a call to a function that restores callee saved 239326938Sdim/// registers onto the stack, when enough callee saved registers are required. 240326938Sdimvoid ARCFrameLowering::emitEpilogue(MachineFunction &MF, 241326938Sdim MachineBasicBlock &MBB) const { 242341825Sdim LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n"); 243326938Sdim auto *AFI = MF.getInfo<ARCFunctionInfo>(); 244326938Sdim const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); 245326938Sdim MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 246326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 247326938Sdim uint64_t StackSize = MF.getFrameInfo().getStackSize(); 248326938Sdim bool SavedBlink = false; 249326938Sdim unsigned AmountAboveFunclet = 0; 250326938Sdim // If we have variable sized frame objects, then we have to move 251326938Sdim // the stack pointer to a known spot (fp - StackSize). 252326938Sdim // Then, replace the frame pointer by (new) [sp,StackSize-4]. 253326938Sdim // Then, move the stack pointer the rest of the way (sp = sp + StackSize). 254326938Sdim if (hasFP(MF)) { 255353358Sdim unsigned Opc = ARC::SUB_rrlimm; 256353358Sdim if (isUInt<6>(StackSize)) 257353358Sdim Opc = ARC::SUB_rru6; 258353358Sdim BuildMI(MBB, MBBI, DebugLoc(), TII->get(Opc), ARC::SP) 259326938Sdim .addReg(ARC::FP) 260326938Sdim .addImm(StackSize); 261326938Sdim AmountAboveFunclet += 4; 262326938Sdim } 263326938Sdim 264326938Sdim // Now, move the stack pointer to the bottom of the save area for the funclet. 265326938Sdim const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 266326938Sdim unsigned Last = determineLastCalleeSave(CSI); 267326938Sdim unsigned StackSlotsUsedByFunclet = 0; 268326938Sdim // Now, restore the callee save registers. 269326938Sdim if (UseSaveRestoreFunclet && Last > ARC::R14) { 270326938Sdim // BL to __ld_r13_to_<TRI->getRegAsmName()> 271326938Sdim StackSlotsUsedByFunclet = Last - ARC::R12; 272326938Sdim AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1); 273326938Sdim SavedBlink = true; 274326938Sdim } 275326938Sdim 276326938Sdim if (MFI.hasCalls() && !SavedBlink) { 277326938Sdim AmountAboveFunclet += 4; 278326938Sdim SavedBlink = true; 279326938Sdim } 280326938Sdim 281326938Sdim // Move the stack pointer up to the point of the funclet. 282353358Sdim if (unsigned MoveAmount = StackSize - AmountAboveFunclet) { 283353358Sdim unsigned Opc = ARC::ADD_rrlimm; 284353358Sdim if (isUInt<6>(MoveAmount)) 285353358Sdim Opc = ARC::ADD_rru6; 286353358Sdim else if (isInt<12>(MoveAmount)) 287353358Sdim Opc = ARC::ADD_rrs12; 288353358Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP) 289326938Sdim .addReg(ARC::SP) 290326938Sdim .addImm(StackSize - AmountAboveFunclet); 291326938Sdim } 292326938Sdim 293326938Sdim if (StackSlotsUsedByFunclet) { 294353358Sdim // This part of the adjustment will always be < 64 bytes. 295326938Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL)) 296326938Sdim .addExternalSymbol(load_funclet_name[Last - ARC::R15]) 297326938Sdim .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); 298353358Sdim unsigned Opc = ARC::ADD_rrlimm; 299353358Sdim if (isUInt<6>(4 * StackSlotsUsedByFunclet)) 300353358Sdim Opc = ARC::ADD_rru6; 301353358Sdim else if (isInt<12>(4 * StackSlotsUsedByFunclet)) 302353358Sdim Opc = ARC::ADD_rrs12; 303353358Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP) 304326938Sdim .addReg(ARC::SP) 305326938Sdim .addImm(4 * (StackSlotsUsedByFunclet)); 306326938Sdim } 307326938Sdim // Now, pop blink if necessary. 308326938Sdim if (SavedBlink) { 309326938Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK)); 310326938Sdim } 311326938Sdim // Now, pop fp if necessary. 312326938Sdim if (hasFP(MF)) { 313326938Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9)) 314353358Sdim .addReg(ARC::FP, RegState::Define) 315326938Sdim .addReg(ARC::SP, RegState::Define) 316326938Sdim .addReg(ARC::SP) 317326938Sdim .addImm(4); 318326938Sdim } 319326938Sdim 320326938Sdim // Relieve the varargs area if necessary. 321326938Sdim if (MF.getFunction().isVarArg()) { 322326938Sdim // Add in the varargs area here first. 323341825Sdim LLVM_DEBUG(dbgs() << "Varargs\n"); 324326938Sdim unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex()); 325353358Sdim unsigned Opc = ARC::ADD_rrlimm; 326353358Sdim if (isUInt<6>(VarArgsBytes)) 327353358Sdim Opc = ARC::ADD_rru6; 328353358Sdim else if (isInt<12>(VarArgsBytes)) 329353358Sdim Opc = ARC::ADD_rrs12; 330353358Sdim BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc)) 331326938Sdim .addReg(ARC::SP) 332326938Sdim .addReg(ARC::SP) 333326938Sdim .addImm(VarArgsBytes); 334326938Sdim } 335326938Sdim} 336326938Sdim 337326938Sdimstatic std::vector<CalleeSavedInfo>::iterator 338326938SdimgetSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) { 339326938Sdim for (auto I = V.begin(), E = V.end(); I != E; ++I) { 340326938Sdim if (reg == I->getReg()) 341326938Sdim return I; 342326938Sdim } 343326938Sdim return V.end(); 344326938Sdim} 345326938Sdim 346326938Sdimbool ARCFrameLowering::assignCalleeSavedSpillSlots( 347326938Sdim MachineFunction &MF, const TargetRegisterInfo *TRI, 348326938Sdim std::vector<CalleeSavedInfo> &CSI) const { 349326938Sdim // Use this opportunity to assign the spill slots for all of the potential 350326938Sdim // callee save registers (blink, fp, r13->r25) that we care about the 351326938Sdim // placement for. We can calculate all of that data here. 352326938Sdim int CurOffset = -4; 353326938Sdim unsigned Last = determineLastCalleeSave(CSI); 354326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 355326938Sdim if (hasFP(MF)) { 356326938Sdim // Create a fixed slot at for FP 357326938Sdim int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true); 358341825Sdim LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at " 359341825Sdim << CurOffset << "\n"); 360326938Sdim (void)StackObj; 361326938Sdim CurOffset -= 4; 362326938Sdim } 363326938Sdim if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) { 364326938Sdim // Create a fixed slot for BLINK. 365326938Sdim int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true); 366341825Sdim LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj 367341825Sdim << ") for BLINK at " << CurOffset << "\n"); 368326938Sdim (void)StackObj; 369326938Sdim CurOffset -= 4; 370326938Sdim } 371326938Sdim 372326938Sdim // Create slots for last down to r13. 373326938Sdim for (unsigned Which = Last; Which > ARC::R12; Which--) { 374326938Sdim auto RegI = getSavedReg(CSI, Which); 375326938Sdim if (RegI == CSI.end() || RegI->getFrameIdx() == 0) { 376326938Sdim // Always create the stack slot. If for some reason the register isn't in 377326938Sdim // the save list, then don't worry about it. 378326938Sdim int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true); 379326938Sdim if (RegI != CSI.end()) 380326938Sdim RegI->setFrameIdx(FI); 381326938Sdim } else 382326938Sdim MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset); 383326938Sdim CurOffset -= 4; 384326938Sdim } 385326938Sdim for (auto &I : CSI) { 386326938Sdim if (I.getReg() > ARC::R12) 387326938Sdim continue; 388326938Sdim if (I.getFrameIdx() == 0) { 389326938Sdim I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true)); 390341825Sdim LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx() 391341825Sdim << ") for other register at " << CurOffset << "\n"); 392326938Sdim } else { 393326938Sdim MFI.setObjectOffset(I.getFrameIdx(), CurOffset); 394341825Sdim LLVM_DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx() 395341825Sdim << ") for other register at " << CurOffset << "\n"); 396326938Sdim } 397326938Sdim CurOffset -= 4; 398326938Sdim } 399326938Sdim return true; 400326938Sdim} 401326938Sdim 402326938Sdimbool ARCFrameLowering::spillCalleeSavedRegisters( 403326938Sdim MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 404326938Sdim const std::vector<CalleeSavedInfo> &CSI, 405326938Sdim const TargetRegisterInfo *TRI) const { 406341825Sdim LLVM_DEBUG(dbgs() << "Spill callee saved registers: " 407341825Sdim << MBB.getParent()->getName() << "\n"); 408326938Sdim // There are routines for saving at least 3 registers (r13 to r15, etc.) 409326938Sdim unsigned Last = determineLastCalleeSave(CSI); 410326938Sdim if (UseSaveRestoreFunclet && Last > ARC::R14) { 411326938Sdim // Use setObjectOffset for these registers. 412326938Sdim // Needs to be in or before processFunctionBeforeFrameFinalized. 413326938Sdim // Or, do assignCalleeSaveSpillSlots? 414326938Sdim // Will be handled in prolog. 415326938Sdim return true; 416326938Sdim } 417326938Sdim return false; 418326938Sdim} 419326938Sdim 420326938Sdimbool ARCFrameLowering::restoreCalleeSavedRegisters( 421326938Sdim MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 422326938Sdim std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { 423341825Sdim LLVM_DEBUG(dbgs() << "Restore callee saved registers: " 424341825Sdim << MBB.getParent()->getName() << "\n"); 425326938Sdim // There are routines for saving at least 3 registers (r13 to r15, etc.) 426326938Sdim unsigned Last = determineLastCalleeSave(CSI); 427326938Sdim if (UseSaveRestoreFunclet && Last > ARC::R14) { 428326938Sdim // Will be handled in epilog. 429326938Sdim return true; 430326938Sdim } 431326938Sdim return false; 432326938Sdim} 433326938Sdim 434326938Sdim// Adjust local variables that are 4-bytes or larger to 4-byte boundary 435326938Sdimvoid ARCFrameLowering::processFunctionBeforeFrameFinalized( 436326938Sdim MachineFunction &MF, RegScavenger *RS) const { 437326938Sdim const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 438341825Sdim LLVM_DEBUG(dbgs() << "Process function before frame finalized: " 439341825Sdim << MF.getName() << "\n"); 440326938Sdim MachineFrameInfo &MFI = MF.getFrameInfo(); 441341825Sdim LLVM_DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n"); 442326938Sdim const TargetRegisterClass *RC = &ARC::GPR32RegClass; 443326938Sdim if (MFI.hasStackObjects()) { 444326938Sdim int RegScavFI = MFI.CreateStackObject( 445326938Sdim RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false); 446326938Sdim RS->addScavengingFrameIndex(RegScavFI); 447341825Sdim LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI 448341825Sdim << "\n"); 449326938Sdim } 450326938Sdim} 451326938Sdim 452326938Sdimstatic void emitRegUpdate(MachineBasicBlock &MBB, 453326938Sdim MachineBasicBlock::iterator &MBBI, DebugLoc dl, 454326938Sdim unsigned Reg, int NumBytes, bool IsAdd, 455326938Sdim const ARCInstrInfo *TII) { 456353358Sdim unsigned Opc; 457353358Sdim if (isUInt<6>(NumBytes)) 458353358Sdim Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6; 459353358Sdim else if (isInt<12>(NumBytes)) 460353358Sdim Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12; 461353358Sdim else 462353358Sdim Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm; 463353358Sdim 464326938Sdim BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg) 465326938Sdim .addReg(Reg, RegState::Kill) 466326938Sdim .addImm(NumBytes); 467326938Sdim} 468326938Sdim 469326938SdimMachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr( 470326938Sdim MachineFunction &MF, MachineBasicBlock &MBB, 471326938Sdim MachineBasicBlock::iterator I) const { 472341825Sdim LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n"); 473326938Sdim const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); 474326938Sdim MachineInstr &Old = *I; 475326938Sdim DebugLoc dl = Old.getDebugLoc(); 476326938Sdim unsigned Amt = Old.getOperand(0).getImm(); 477326938Sdim auto *AFI = MF.getInfo<ARCFunctionInfo>(); 478326938Sdim if (!hasFP(MF)) { 479326938Sdim if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN) 480326938Sdim AFI->MaxCallStackReq = Amt; 481326938Sdim } else { 482326938Sdim if (Amt != 0) { 483326938Sdim assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN || 484326938Sdim Old.getOpcode() == ARC::ADJCALLSTACKUP) && 485326938Sdim "Unknown Frame Pseudo."); 486326938Sdim bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP); 487326938Sdim emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII); 488326938Sdim } 489326938Sdim } 490326938Sdim return MBB.erase(I); 491326938Sdim} 492326938Sdim 493326938Sdimbool ARCFrameLowering::hasFP(const MachineFunction &MF) const { 494326938Sdim const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 495326938Sdim bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) || 496326938Sdim MF.getFrameInfo().hasVarSizedObjects() || 497326938Sdim MF.getFrameInfo().isFrameAddressTaken() || 498326938Sdim RegInfo->needsStackRealignment(MF); 499326938Sdim return HasFP; 500326938Sdim} 501