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