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(Val: 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 if (isInt<12>(AbsAmount)) |
68 | AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12; |
69 | else |
70 | AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm; |
71 | |
72 | BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr) |
73 | .addReg(StackPtr) |
74 | .addImm(AbsAmount); |
75 | } |
76 | |
77 | static unsigned determineLastCalleeSave(ArrayRef<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 { |
91 | LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName() << "\n" ); |
92 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
93 | SavedRegs.set(ARC::BLINK); |
94 | } |
95 | |
96 | void ARCFrameLowering::adjustStackToMatchRecords( |
97 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
98 | bool Allocate) const { |
99 | MachineFunction &MF = *MBB.getParent(); |
100 | int ScalarAlloc = MF.getFrameInfo().getStackSize(); |
101 | |
102 | if (Allocate) { |
103 | // Allocate by adjusting by the negative of what the record holder tracked |
104 | // it tracked a positive offset in a downward growing stack. |
105 | ScalarAlloc = -ScalarAlloc; |
106 | } |
107 | |
108 | generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(), |
109 | ScalarAlloc, ARC::SP); |
110 | } |
111 | |
112 | /// Insert prolog code into the function. |
113 | /// For ARC, this inserts a call to a function that puts required callee saved |
114 | /// registers onto the stack, when enough callee saved registers are required. |
115 | void ARCFrameLowering::emitPrologue(MachineFunction &MF, |
116 | MachineBasicBlock &MBB) const { |
117 | LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n" ); |
118 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
119 | MachineModuleInfo &MMI = MF.getMMI(); |
120 | MCContext &Context = MMI.getContext(); |
121 | const MCRegisterInfo *MRI = Context.getRegisterInfo(); |
122 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
123 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
124 | // Debug location must be unknown since the first debug location is used |
125 | // to determine the end of the prologue. |
126 | DebugLoc dl; |
127 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
128 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
129 | unsigned Last = determineLastCalleeSave(CSI); |
130 | unsigned StackSlotsUsedByFunclet = 0; |
131 | bool SavedBlink = false; |
132 | unsigned AlreadyAdjusted = 0; |
133 | if (MF.getFunction().isVarArg()) { |
134 | // Add in the varargs area here first. |
135 | LLVM_DEBUG(dbgs() << "Varargs\n" ); |
136 | unsigned VarArgsBytes = MFI.getObjectSize(ObjectIdx: AFI->getVarArgsFrameIndex()); |
137 | unsigned Opc = ARC::SUB_rrlimm; |
138 | if (isUInt<6>(VarArgsBytes)) |
139 | Opc = ARC::SUB_rru6; |
140 | else if (isInt<12>(VarArgsBytes)) |
141 | Opc = ARC::SUB_rrs12; |
142 | BuildMI(MBB, MBBI, dl, TII->get(Opc), ARC::SP) |
143 | .addReg(ARC::SP) |
144 | .addImm(VarArgsBytes); |
145 | } |
146 | if (hasFP(MF)) { |
147 | LLVM_DEBUG(dbgs() << "Saving FP\n" ); |
148 | BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9)) |
149 | .addReg(ARC::SP, RegState::Define) |
150 | .addReg(ARC::FP) |
151 | .addReg(ARC::SP) |
152 | .addImm(-4); |
153 | AlreadyAdjusted += 4; |
154 | } |
155 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
156 | LLVM_DEBUG(dbgs() << "Creating store funclet.\n" ); |
157 | // BL to __save_r13_to_<TRI->getRegAsmName()> |
158 | StackSlotsUsedByFunclet = Last - ARC::R12; |
159 | BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); |
160 | BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6)) |
161 | .addReg(ARC::SP) |
162 | .addReg(ARC::SP) |
163 | .addImm(4 * StackSlotsUsedByFunclet); |
164 | BuildMI(MBB, MBBI, dl, TII->get(ARC::BL)) |
165 | .addExternalSymbol(store_funclet_name[Last - ARC::R15]) |
166 | .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); |
167 | AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1); |
168 | SavedBlink = true; |
169 | } |
170 | // If we haven't saved BLINK, but we need to...do that now. |
171 | if (MFI.hasCalls() && !SavedBlink) { |
172 | LLVM_DEBUG(dbgs() << "Creating save blink.\n" ); |
173 | BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK)); |
174 | AlreadyAdjusted += 4; |
175 | } |
176 | if (AFI->MaxCallStackReq > 0) |
177 | MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq); |
178 | // We have already saved some of the stack... |
179 | LLVM_DEBUG(dbgs() << "Adjusting stack by: " |
180 | << (MFI.getStackSize() - AlreadyAdjusted) << "\n" ); |
181 | generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl, |
182 | -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP); |
183 | |
184 | if (hasFP(MF)) { |
185 | LLVM_DEBUG(dbgs() << "Setting FP from SP.\n" ); |
186 | BuildMI(MBB, MBBI, dl, |
187 | TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6 |
188 | : ARC::ADD_rrlimm), |
189 | ARC::FP) |
190 | .addReg(ARC::SP) |
191 | .addImm(MFI.getStackSize()); |
192 | } |
193 | |
194 | // Emit CFI records: |
195 | // .cfi_def_cfa_offset StackSize |
196 | // .cfi_offset fp, -StackSize |
197 | // .cfi_offset blink, -StackSize+4 |
198 | unsigned CFIIndex = MF.addFrameInst( |
199 | Inst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: MFI.getStackSize())); |
200 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
201 | .addCFIIndex(CFIIndex) |
202 | .setMIFlags(MachineInstr::FrameSetup); |
203 | |
204 | int CurOffset = -4; |
205 | if (hasFP(MF)) { |
206 | CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( |
207 | nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset)); |
208 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
209 | .addCFIIndex(CFIIndex) |
210 | .setMIFlags(MachineInstr::FrameSetup); |
211 | CurOffset -= 4; |
212 | } |
213 | |
214 | if (MFI.hasCalls()) { |
215 | CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( |
216 | nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset)); |
217 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
218 | .addCFIIndex(CFIIndex) |
219 | .setMIFlags(MachineInstr::FrameSetup); |
220 | } |
221 | // CFI for the rest of the registers. |
222 | for (const auto &Entry : CSI) { |
223 | unsigned Reg = Entry.getReg(); |
224 | int FI = Entry.getFrameIdx(); |
225 | // Skip BLINK and FP. |
226 | if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK)) |
227 | continue; |
228 | CFIIndex = MF.addFrameInst(Inst: MCCFIInstruction::createOffset( |
229 | L: nullptr, Register: MRI->getDwarfRegNum(RegNum: Reg, isEH: true), Offset: MFI.getObjectOffset(ObjectIdx: FI))); |
230 | BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
231 | .addCFIIndex(CFIIndex) |
232 | .setMIFlags(MachineInstr::FrameSetup); |
233 | } |
234 | } |
235 | |
236 | /// Insert epilog code into the function. |
237 | /// For ARC, this inserts a call to a function that restores callee saved |
238 | /// registers onto the stack, when enough callee saved registers are required. |
239 | void ARCFrameLowering::emitEpilogue(MachineFunction &MF, |
240 | MachineBasicBlock &MBB) const { |
241 | LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n" ); |
242 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
243 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
244 | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); |
245 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
246 | uint64_t StackSize = MF.getFrameInfo().getStackSize(); |
247 | bool SavedBlink = false; |
248 | unsigned AmountAboveFunclet = 0; |
249 | // If we have variable sized frame objects, then we have to move |
250 | // the stack pointer to a known spot (fp - StackSize). |
251 | // Then, replace the frame pointer by (new) [sp,StackSize-4]. |
252 | // Then, move the stack pointer the rest of the way (sp = sp + StackSize). |
253 | if (hasFP(MF)) { |
254 | unsigned Opc = ARC::SUB_rrlimm; |
255 | if (isUInt<6>(StackSize)) |
256 | Opc = ARC::SUB_rru6; |
257 | BuildMI(MBB, MBBI, DebugLoc(), TII->get(Opc), ARC::SP) |
258 | .addReg(ARC::FP) |
259 | .addImm(StackSize); |
260 | AmountAboveFunclet += 4; |
261 | } |
262 | |
263 | // Now, move the stack pointer to the bottom of the save area for the funclet. |
264 | const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); |
265 | unsigned Last = determineLastCalleeSave(CSI); |
266 | unsigned StackSlotsUsedByFunclet = 0; |
267 | // Now, restore the callee save registers. |
268 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
269 | // BL to __ld_r13_to_<TRI->getRegAsmName()> |
270 | StackSlotsUsedByFunclet = Last - ARC::R12; |
271 | AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1); |
272 | SavedBlink = true; |
273 | } |
274 | |
275 | if (MFI.hasCalls() && !SavedBlink) { |
276 | AmountAboveFunclet += 4; |
277 | SavedBlink = true; |
278 | } |
279 | |
280 | // Move the stack pointer up to the point of the funclet. |
281 | if (unsigned MoveAmount = StackSize - AmountAboveFunclet) { |
282 | unsigned Opc = ARC::ADD_rrlimm; |
283 | if (isUInt<6>(MoveAmount)) |
284 | Opc = ARC::ADD_rru6; |
285 | else if (isInt<12>(MoveAmount)) |
286 | Opc = ARC::ADD_rrs12; |
287 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP) |
288 | .addReg(ARC::SP) |
289 | .addImm(StackSize - AmountAboveFunclet); |
290 | } |
291 | |
292 | if (StackSlotsUsedByFunclet) { |
293 | // This part of the adjustment will always be < 64 bytes. |
294 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL)) |
295 | .addExternalSymbol(load_funclet_name[Last - ARC::R15]) |
296 | .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill); |
297 | unsigned Opc = ARC::ADD_rrlimm; |
298 | if (isUInt<6>(4 * StackSlotsUsedByFunclet)) |
299 | Opc = ARC::ADD_rru6; |
300 | else if (isInt<12>(4 * StackSlotsUsedByFunclet)) |
301 | Opc = ARC::ADD_rrs12; |
302 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP) |
303 | .addReg(ARC::SP) |
304 | .addImm(4 * (StackSlotsUsedByFunclet)); |
305 | } |
306 | // Now, pop blink if necessary. |
307 | if (SavedBlink) { |
308 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK)); |
309 | } |
310 | // Now, pop fp if necessary. |
311 | if (hasFP(MF)) { |
312 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9)) |
313 | .addReg(ARC::FP, RegState::Define) |
314 | .addReg(ARC::SP, RegState::Define) |
315 | .addReg(ARC::SP) |
316 | .addImm(4); |
317 | } |
318 | |
319 | // Relieve the varargs area if necessary. |
320 | if (MF.getFunction().isVarArg()) { |
321 | // Add in the varargs area here first. |
322 | LLVM_DEBUG(dbgs() << "Varargs\n" ); |
323 | unsigned VarArgsBytes = MFI.getObjectSize(ObjectIdx: AFI->getVarArgsFrameIndex()); |
324 | unsigned Opc = ARC::ADD_rrlimm; |
325 | if (isUInt<6>(VarArgsBytes)) |
326 | Opc = ARC::ADD_rru6; |
327 | else if (isInt<12>(VarArgsBytes)) |
328 | Opc = ARC::ADD_rrs12; |
329 | BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc)) |
330 | .addReg(ARC::SP) |
331 | .addReg(ARC::SP) |
332 | .addImm(VarArgsBytes); |
333 | } |
334 | } |
335 | |
336 | static std::vector<CalleeSavedInfo>::iterator |
337 | getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) { |
338 | for (auto I = V.begin(), E = V.end(); I != E; ++I) { |
339 | if (reg == I->getReg()) |
340 | return I; |
341 | } |
342 | return V.end(); |
343 | } |
344 | |
345 | bool ARCFrameLowering::assignCalleeSavedSpillSlots( |
346 | MachineFunction &MF, const TargetRegisterInfo *TRI, |
347 | std::vector<CalleeSavedInfo> &CSI) const { |
348 | // Use this opportunity to assign the spill slots for all of the potential |
349 | // callee save registers (blink, fp, r13->r25) that we care about the |
350 | // placement for. We can calculate all of that data here. |
351 | int CurOffset = -4; |
352 | unsigned Last = determineLastCalleeSave(CSI); |
353 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
354 | if (hasFP(MF)) { |
355 | // Create a fixed slot at for FP |
356 | int StackObj = MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true); |
357 | LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at " |
358 | << CurOffset << "\n" ); |
359 | (void)StackObj; |
360 | CurOffset -= 4; |
361 | } |
362 | if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) { |
363 | // Create a fixed slot for BLINK. |
364 | int StackObj = MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true); |
365 | LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj |
366 | << ") for BLINK at " << CurOffset << "\n" ); |
367 | (void)StackObj; |
368 | CurOffset -= 4; |
369 | } |
370 | |
371 | // Create slots for last down to r13. |
372 | for (unsigned Which = Last; Which > ARC::R12; Which--) { |
373 | auto RegI = getSavedReg(CSI, Which); |
374 | if (RegI == CSI.end() || RegI->getFrameIdx() == 0) { |
375 | // Always create the stack slot. If for some reason the register isn't in |
376 | // the save list, then don't worry about it. |
377 | int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true); |
378 | if (RegI != CSI.end()) |
379 | RegI->setFrameIdx(FI); |
380 | } else |
381 | MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset); |
382 | CurOffset -= 4; |
383 | } |
384 | for (auto &I : CSI) { |
385 | if (I.getReg() > ARC::R12) |
386 | continue; |
387 | if (I.getFrameIdx() == 0) { |
388 | I.setFrameIdx(MFI.CreateFixedSpillStackObject(Size: 4, SPOffset: CurOffset, IsImmutable: true)); |
389 | LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx() |
390 | << ") for other register at " << CurOffset << "\n" ); |
391 | } else { |
392 | MFI.setObjectOffset(ObjectIdx: I.getFrameIdx(), SPOffset: CurOffset); |
393 | LLVM_DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx() |
394 | << ") for other register at " << CurOffset << "\n" ); |
395 | } |
396 | CurOffset -= 4; |
397 | } |
398 | return true; |
399 | } |
400 | |
401 | bool ARCFrameLowering::spillCalleeSavedRegisters( |
402 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
403 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
404 | LLVM_DEBUG(dbgs() << "Spill callee saved registers: " |
405 | << MBB.getParent()->getName() << "\n" ); |
406 | // There are routines for saving at least 3 registers (r13 to r15, etc.) |
407 | unsigned Last = determineLastCalleeSave(CSI); |
408 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
409 | // Use setObjectOffset for these registers. |
410 | // Needs to be in or before processFunctionBeforeFrameFinalized. |
411 | // Or, do assignCalleeSaveSpillSlots? |
412 | // Will be handled in prolog. |
413 | return true; |
414 | } |
415 | return false; |
416 | } |
417 | |
418 | bool ARCFrameLowering::restoreCalleeSavedRegisters( |
419 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
420 | MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
421 | LLVM_DEBUG(dbgs() << "Restore callee saved registers: " |
422 | << MBB.getParent()->getName() << "\n" ); |
423 | // There are routines for saving at least 3 registers (r13 to r15, etc.) |
424 | unsigned Last = determineLastCalleeSave(CSI); |
425 | if (UseSaveRestoreFunclet && Last > ARC::R14) { |
426 | // Will be handled in epilog. |
427 | return true; |
428 | } |
429 | return false; |
430 | } |
431 | |
432 | // Adjust local variables that are 4-bytes or larger to 4-byte boundary |
433 | void ARCFrameLowering::processFunctionBeforeFrameFinalized( |
434 | MachineFunction &MF, RegScavenger *RS) const { |
435 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); |
436 | LLVM_DEBUG(dbgs() << "Process function before frame finalized: " |
437 | << MF.getName() << "\n" ); |
438 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
439 | LLVM_DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n" ); |
440 | const TargetRegisterClass *RC = &ARC::GPR32RegClass; |
441 | if (MFI.hasStackObjects()) { |
442 | int RegScavFI = MFI.CreateStackObject(Size: RegInfo->getSpillSize(RC: *RC), |
443 | Alignment: RegInfo->getSpillAlign(RC: *RC), isSpillSlot: false); |
444 | RS->addScavengingFrameIndex(FI: RegScavFI); |
445 | LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI |
446 | << "\n" ); |
447 | } |
448 | } |
449 | |
450 | static void emitRegUpdate(MachineBasicBlock &MBB, |
451 | MachineBasicBlock::iterator &MBBI, DebugLoc dl, |
452 | unsigned Reg, int NumBytes, bool IsAdd, |
453 | const ARCInstrInfo *TII) { |
454 | unsigned Opc; |
455 | if (isUInt<6>(NumBytes)) |
456 | Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6; |
457 | else if (isInt<12>(NumBytes)) |
458 | Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12; |
459 | else |
460 | Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm; |
461 | |
462 | BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg) |
463 | .addReg(Reg, RegState::Kill) |
464 | .addImm(NumBytes); |
465 | } |
466 | |
467 | MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr( |
468 | MachineFunction &MF, MachineBasicBlock &MBB, |
469 | MachineBasicBlock::iterator I) const { |
470 | LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n" ); |
471 | const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo(); |
472 | MachineInstr &Old = *I; |
473 | DebugLoc dl = Old.getDebugLoc(); |
474 | unsigned Amt = Old.getOperand(i: 0).getImm(); |
475 | auto *AFI = MF.getInfo<ARCFunctionInfo>(); |
476 | if (!hasFP(MF)) { |
477 | if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN) |
478 | AFI->MaxCallStackReq = Amt; |
479 | } else { |
480 | if (Amt != 0) { |
481 | assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN || |
482 | Old.getOpcode() == ARC::ADJCALLSTACKUP) && |
483 | "Unknown Frame Pseudo." ); |
484 | bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP); |
485 | emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII); |
486 | } |
487 | } |
488 | return MBB.erase(I); |
489 | } |
490 | |
491 | bool ARCFrameLowering::hasFP(const MachineFunction &MF) const { |
492 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); |
493 | bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) || |
494 | MF.getFrameInfo().hasVarSizedObjects() || |
495 | MF.getFrameInfo().isFrameAddressTaken() || |
496 | RegInfo->hasStackRealignment(MF); |
497 | return HasFP; |
498 | } |
499 | |