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