1 | //===-- CSKYFrameLowering.cpp - CSKY Frame Information ------------------===// |
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 CSKY implementation of TargetFrameLowering class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "CSKYFrameLowering.h" |
14 | #include "CSKYMachineFunctionInfo.h" |
15 | #include "CSKYSubtarget.h" |
16 | #include "llvm/CodeGen/MachineConstantPool.h" |
17 | #include "llvm/CodeGen/MachineFrameInfo.h" |
18 | #include "llvm/CodeGen/MachineFunction.h" |
19 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
20 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
21 | #include "llvm/CodeGen/RegisterScavenging.h" |
22 | #include "llvm/IR/DiagnosticInfo.h" |
23 | #include "llvm/MC/MCDwarf.h" |
24 | |
25 | using namespace llvm; |
26 | |
27 | #define DEBUG_TYPE "csky-frame-lowering" |
28 | |
29 | // Returns the register used to hold the frame pointer. |
30 | static Register getFPReg(const CSKYSubtarget &STI) { return CSKY::R8; } |
31 | |
32 | // To avoid the BP value clobbered by a function call, we need to choose a |
33 | // callee saved register to save the value. |
34 | static Register getBPReg(const CSKYSubtarget &STI) { return CSKY::R7; } |
35 | |
36 | bool CSKYFrameLowering::hasFP(const MachineFunction &MF) const { |
37 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); |
38 | |
39 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
40 | return MF.getTarget().Options.DisableFramePointerElim(MF) || |
41 | RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || |
42 | MFI.isFrameAddressTaken(); |
43 | } |
44 | |
45 | bool CSKYFrameLowering::hasBP(const MachineFunction &MF) const { |
46 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
47 | |
48 | return MFI.hasVarSizedObjects(); |
49 | } |
50 | |
51 | // Determines the size of the frame and maximum call frame size. |
52 | void CSKYFrameLowering::determineFrameLayout(MachineFunction &MF) const { |
53 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
54 | const CSKYRegisterInfo *RI = STI.getRegisterInfo(); |
55 | |
56 | // Get the number of bytes to allocate from the FrameInfo. |
57 | uint64_t FrameSize = MFI.getStackSize(); |
58 | |
59 | // Get the alignment. |
60 | Align StackAlign = getStackAlign(); |
61 | if (RI->hasStackRealignment(MF)) { |
62 | Align MaxStackAlign = std::max(a: StackAlign, b: MFI.getMaxAlign()); |
63 | FrameSize += (MaxStackAlign.value() - StackAlign.value()); |
64 | StackAlign = MaxStackAlign; |
65 | } |
66 | |
67 | // Set Max Call Frame Size |
68 | uint64_t MaxCallSize = alignTo(Size: MFI.getMaxCallFrameSize(), A: StackAlign); |
69 | MFI.setMaxCallFrameSize(MaxCallSize); |
70 | |
71 | // Make sure the frame is aligned. |
72 | FrameSize = alignTo(Size: FrameSize, A: StackAlign); |
73 | |
74 | // Update frame info. |
75 | MFI.setStackSize(FrameSize); |
76 | } |
77 | |
78 | void CSKYFrameLowering::emitPrologue(MachineFunction &MF, |
79 | MachineBasicBlock &MBB) const { |
80 | CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
81 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
82 | const CSKYRegisterInfo *RI = STI.getRegisterInfo(); |
83 | const CSKYInstrInfo *TII = STI.getInstrInfo(); |
84 | MachineBasicBlock::iterator MBBI = MBB.begin(); |
85 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
86 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
87 | |
88 | Register FPReg = getFPReg(STI); |
89 | Register SPReg = CSKY::R14; |
90 | Register BPReg = getBPReg(STI); |
91 | |
92 | // Debug location must be unknown since the first debug location is used |
93 | // to determine the end of the prologue. |
94 | DebugLoc DL; |
95 | |
96 | if (MF.getFunction().hasFnAttribute("interrupt" )) |
97 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::NIE)); |
98 | |
99 | // Determine the correct frame layout |
100 | determineFrameLayout(MF); |
101 | |
102 | // FIXME (note copied from Lanai): This appears to be overallocating. Needs |
103 | // investigation. Get the number of bytes to allocate from the FrameInfo. |
104 | uint64_t StackSize = MFI.getStackSize(); |
105 | |
106 | // Early exit if there is no need to allocate on the stack |
107 | if (StackSize == 0 && !MFI.adjustsStack()) |
108 | return; |
109 | |
110 | const auto &CSI = MFI.getCalleeSavedInfo(); |
111 | |
112 | unsigned spillAreaSize = CFI->getCalleeSaveAreaSize(); |
113 | |
114 | uint64_t ActualSize = spillAreaSize + CFI->getVarArgsSaveSize(); |
115 | |
116 | // First part stack allocation. |
117 | adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: -(static_cast<int64_t>(ActualSize)), |
118 | Flag: MachineInstr::NoFlags); |
119 | |
120 | // Emit ".cfi_def_cfa_offset FirstSPAdjustAmount" |
121 | unsigned CFIIndex = |
122 | MF.addFrameInst(Inst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: ActualSize)); |
123 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
124 | .addCFIIndex(CFIIndex); |
125 | |
126 | // The frame pointer is callee-saved, and code has been generated for us to |
127 | // save it to the stack. We need to skip over the storing of callee-saved |
128 | // registers as the frame pointer must be modified after it has been saved |
129 | // to the stack, not before. |
130 | // FIXME: assumes exactly one instruction is used to save each callee-saved |
131 | // register. |
132 | std::advance(i&: MBBI, n: CSI.size()); |
133 | |
134 | // Iterate over list of callee-saved registers and emit .cfi_offset |
135 | // directives. |
136 | for (const auto &Entry : CSI) { |
137 | int64_t Offset = MFI.getObjectOffset(ObjectIdx: Entry.getFrameIdx()); |
138 | Register Reg = Entry.getReg(); |
139 | |
140 | unsigned Num = TRI->getRegSizeInBits(Reg, MRI) / 32; |
141 | for (unsigned i = 0; i < Num; i++) { |
142 | unsigned CFIIndex = MF.addFrameInst(Inst: MCCFIInstruction::createOffset( |
143 | L: nullptr, Register: RI->getDwarfRegNum(Reg, true) + i, Offset: Offset + i * 4)); |
144 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
145 | .addCFIIndex(CFIIndex); |
146 | } |
147 | } |
148 | |
149 | // Generate new FP. |
150 | if (hasFP(MF)) { |
151 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), FPReg) |
152 | .addReg(SPReg) |
153 | .setMIFlag(MachineInstr::FrameSetup); |
154 | |
155 | // Emit ".cfi_def_cfa_register $fp" |
156 | unsigned CFIIndex = MF.addFrameInst(Inst: MCCFIInstruction::createDefCfaRegister( |
157 | L: nullptr, Register: RI->getDwarfRegNum(FPReg, true))); |
158 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
159 | .addCFIIndex(CFIIndex); |
160 | |
161 | // Second part stack allocation. |
162 | adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, |
163 | Val: -(static_cast<int64_t>(StackSize - ActualSize)), |
164 | Flag: MachineInstr::NoFlags); |
165 | |
166 | // Realign Stack |
167 | const CSKYRegisterInfo *RI = STI.getRegisterInfo(); |
168 | if (RI->hasStackRealignment(MF)) { |
169 | Align MaxAlignment = MFI.getMaxAlign(); |
170 | |
171 | const CSKYInstrInfo *TII = STI.getInstrInfo(); |
172 | if (STI.hasE2() && isUInt<12>(x: ~(-(int)MaxAlignment.value()))) { |
173 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::ANDNI32), SPReg) |
174 | .addReg(SPReg) |
175 | .addImm(~(-(int)MaxAlignment.value())); |
176 | } else { |
177 | unsigned ShiftAmount = Log2(A: MaxAlignment); |
178 | |
179 | if (STI.hasE2()) { |
180 | Register VR = |
181 | MF.getRegInfo().createVirtualRegister(&CSKY::GPRRegClass); |
182 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSRI32), VR) |
183 | .addReg(SPReg) |
184 | .addImm(ShiftAmount); |
185 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSLI32), SPReg) |
186 | .addReg(VR) |
187 | .addImm(ShiftAmount); |
188 | } else { |
189 | Register VR = |
190 | MF.getRegInfo().createVirtualRegister(&CSKY::mGPRRegClass); |
191 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::MOV16), VR).addReg(SPReg); |
192 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSRI16), VR) |
193 | .addReg(VR) |
194 | .addImm(ShiftAmount); |
195 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::LSLI16), VR) |
196 | .addReg(VR) |
197 | .addImm(ShiftAmount); |
198 | BuildMI(MBB, MBBI, DL, TII->get(CSKY::MOV16), SPReg).addReg(VR); |
199 | } |
200 | } |
201 | } |
202 | |
203 | // FP will be used to restore the frame in the epilogue, so we need |
204 | // another base register BP to record SP after re-alignment. SP will |
205 | // track the current stack after allocating variable sized objects. |
206 | if (hasBP(MF)) { |
207 | // move BP, SP |
208 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::COPY), BPReg).addReg(SPReg); |
209 | } |
210 | |
211 | } else { |
212 | adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, |
213 | Val: -(static_cast<int64_t>(StackSize - ActualSize)), |
214 | Flag: MachineInstr::NoFlags); |
215 | // Emit ".cfi_def_cfa_offset StackSize" |
216 | unsigned CFIIndex = MF.addFrameInst( |
217 | Inst: MCCFIInstruction::cfiDefCfaOffset(L: nullptr, Offset: MFI.getStackSize())); |
218 | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) |
219 | .addCFIIndex(CFIIndex); |
220 | } |
221 | } |
222 | |
223 | void CSKYFrameLowering::emitEpilogue(MachineFunction &MF, |
224 | MachineBasicBlock &MBB) const { |
225 | CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
226 | |
227 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
228 | Register FPReg = getFPReg(STI); |
229 | Register SPReg = CSKY::R14; |
230 | |
231 | // Get the insert location for the epilogue. If there were no terminators in |
232 | // the block, get the last instruction. |
233 | MachineBasicBlock::iterator MBBI = MBB.end(); |
234 | DebugLoc DL; |
235 | if (!MBB.empty()) { |
236 | MBBI = MBB.getFirstTerminator(); |
237 | if (MBBI == MBB.end()) |
238 | MBBI = MBB.getLastNonDebugInstr(); |
239 | DL = MBBI->getDebugLoc(); |
240 | |
241 | // If this is not a terminator, the actual insert location should be after |
242 | // the last instruction. |
243 | if (!MBBI->isTerminator()) |
244 | MBBI = std::next(x: MBBI); |
245 | } |
246 | |
247 | const auto &CSI = MFI.getCalleeSavedInfo(); |
248 | uint64_t StackSize = MFI.getStackSize(); |
249 | |
250 | uint64_t ActualSize = |
251 | CFI->getCalleeSaveAreaSize() + CFI->getVarArgsSaveSize(); |
252 | |
253 | // Skip to before the restores of callee-saved registers |
254 | // FIXME: assumes exactly one instruction is used to restore each |
255 | // callee-saved register. |
256 | auto LastFrameDestroy = MBBI; |
257 | if (!CSI.empty()) |
258 | LastFrameDestroy = std::prev(x: MBBI, n: CSI.size()); |
259 | |
260 | if (hasFP(MF)) { |
261 | const CSKYInstrInfo *TII = STI.getInstrInfo(); |
262 | BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::COPY), SPReg) |
263 | .addReg(FPReg) |
264 | .setMIFlag(MachineInstr::NoFlags); |
265 | } else { |
266 | adjustReg(MBB, MBBI: LastFrameDestroy, DL, DestReg: SPReg, SrcReg: SPReg, Val: (StackSize - ActualSize), |
267 | Flag: MachineInstr::FrameDestroy); |
268 | } |
269 | |
270 | adjustReg(MBB, MBBI, DL, DestReg: SPReg, SrcReg: SPReg, Val: ActualSize, |
271 | Flag: MachineInstr::FrameDestroy); |
272 | } |
273 | |
274 | static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, |
275 | const CSKYInstrInfo &TII) { |
276 | unsigned FnSize = 0; |
277 | for (auto &MBB : MF) { |
278 | for (auto &MI : MBB) |
279 | FnSize += TII.getInstSizeInBytes(MI); |
280 | } |
281 | FnSize += MF.getConstantPool()->getConstants().size() * 4; |
282 | return FnSize; |
283 | } |
284 | |
285 | static unsigned (MachineFunction &MF, |
286 | const CSKYSubtarget &STI) { |
287 | unsigned Limit = (1 << 12) - 1; |
288 | |
289 | for (auto &MBB : MF) { |
290 | for (auto &MI : MBB) { |
291 | if (MI.isDebugInstr()) |
292 | continue; |
293 | |
294 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
295 | if (!MI.getOperand(i).isFI()) |
296 | continue; |
297 | |
298 | if (MI.getOpcode() == CSKY::SPILL_CARRY || |
299 | MI.getOpcode() == CSKY::RESTORE_CARRY || |
300 | MI.getOpcode() == CSKY::STORE_PAIR || |
301 | MI.getOpcode() == CSKY::LOAD_PAIR) { |
302 | Limit = std::min(a: Limit, b: ((1U << 12) - 1) * 4); |
303 | break; |
304 | } |
305 | |
306 | if (MI.getOpcode() == CSKY::ADDI32) { |
307 | Limit = std::min(a: Limit, b: (1U << 12)); |
308 | break; |
309 | } |
310 | |
311 | if (MI.getOpcode() == CSKY::ADDI16XZ) { |
312 | Limit = std::min(a: Limit, b: (1U << 3)); |
313 | break; |
314 | } |
315 | |
316 | // ADDI16 will not require an extra register, |
317 | // it can reuse the destination. |
318 | if (MI.getOpcode() == CSKY::ADDI16) |
319 | break; |
320 | |
321 | // Otherwise check the addressing mode. |
322 | switch (MI.getDesc().TSFlags & CSKYII::AddrModeMask) { |
323 | default: |
324 | LLVM_DEBUG(MI.dump()); |
325 | llvm_unreachable( |
326 | "Unhandled addressing mode in stack size limit calculation" ); |
327 | case CSKYII::AddrMode32B: |
328 | Limit = std::min(a: Limit, b: (1U << 12) - 1); |
329 | break; |
330 | case CSKYII::AddrMode32H: |
331 | Limit = std::min(a: Limit, b: ((1U << 12) - 1) * 2); |
332 | break; |
333 | case CSKYII::AddrMode32WD: |
334 | Limit = std::min(a: Limit, b: ((1U << 12) - 1) * 4); |
335 | break; |
336 | case CSKYII::AddrMode16B: |
337 | Limit = std::min(a: Limit, b: (1U << 5) - 1); |
338 | break; |
339 | case CSKYII::AddrMode16H: |
340 | Limit = std::min(a: Limit, b: ((1U << 5) - 1) * 2); |
341 | break; |
342 | case CSKYII::AddrMode16W: |
343 | Limit = std::min(a: Limit, b: ((1U << 5) - 1) * 4); |
344 | break; |
345 | case CSKYII::AddrMode32SDF: |
346 | Limit = std::min(a: Limit, b: ((1U << 8) - 1) * 4); |
347 | break; |
348 | } |
349 | break; // At most one FI per instruction |
350 | } |
351 | } |
352 | } |
353 | |
354 | return Limit; |
355 | } |
356 | |
357 | void CSKYFrameLowering::determineCalleeSaves(MachineFunction &MF, |
358 | BitVector &SavedRegs, |
359 | RegScavenger *RS) const { |
360 | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); |
361 | |
362 | CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
363 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
364 | const CSKYInstrInfo *TII = STI.getInstrInfo(); |
365 | const MachineRegisterInfo &MRI = MF.getRegInfo(); |
366 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
367 | |
368 | if (hasFP(MF)) |
369 | SavedRegs.set(CSKY::R8); |
370 | |
371 | // Mark BP as used if function has dedicated base pointer. |
372 | if (hasBP(MF)) |
373 | SavedRegs.set(CSKY::R7); |
374 | |
375 | // If interrupt is enabled and there are calls in the handler, |
376 | // unconditionally save all Caller-saved registers and |
377 | // all FP registers, regardless whether they are used. |
378 | if (MF.getFunction().hasFnAttribute(Kind: "interrupt" ) && MFI.hasCalls()) { |
379 | |
380 | static const MCPhysReg CSRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3, |
381 | CSKY::R12, CSKY::R13, 0}; |
382 | |
383 | for (unsigned i = 0; CSRegs[i]; ++i) |
384 | SavedRegs.set(CSRegs[i]); |
385 | |
386 | if (STI.hasHighRegisters()) { |
387 | |
388 | static const MCPhysReg CSHRegs[] = {CSKY::R18, CSKY::R19, CSKY::R20, |
389 | CSKY::R21, CSKY::R22, CSKY::R23, |
390 | CSKY::R24, CSKY::R25, 0}; |
391 | |
392 | for (unsigned i = 0; CSHRegs[i]; ++i) |
393 | SavedRegs.set(CSHRegs[i]); |
394 | } |
395 | |
396 | static const MCPhysReg CSF32Regs[] = { |
397 | CSKY::F8_32, CSKY::F9_32, CSKY::F10_32, |
398 | CSKY::F11_32, CSKY::F12_32, CSKY::F13_32, |
399 | CSKY::F14_32, CSKY::F15_32, 0}; |
400 | static const MCPhysReg CSF64Regs[] = { |
401 | CSKY::F8_64, CSKY::F9_64, CSKY::F10_64, |
402 | CSKY::F11_64, CSKY::F12_64, CSKY::F13_64, |
403 | CSKY::F14_64, CSKY::F15_64, 0}; |
404 | |
405 | const MCPhysReg *FRegs = NULL; |
406 | if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) |
407 | FRegs = CSF64Regs; |
408 | else if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) |
409 | FRegs = CSF32Regs; |
410 | |
411 | if (FRegs != NULL) { |
412 | const MCPhysReg *Regs = MF.getRegInfo().getCalleeSavedRegs(); |
413 | |
414 | for (unsigned i = 0; Regs[i]; ++i) |
415 | if (CSKY::FPR32RegClass.contains(Regs[i]) || |
416 | CSKY::FPR64RegClass.contains(Regs[i])) { |
417 | unsigned x = 0; |
418 | for (; FRegs[x]; ++x) |
419 | if (FRegs[x] == Regs[i]) |
420 | break; |
421 | if (FRegs[x] == 0) |
422 | SavedRegs.set(Regs[i]); |
423 | } |
424 | } |
425 | } |
426 | |
427 | unsigned CSStackSize = 0; |
428 | for (unsigned Reg : SavedRegs.set_bits()) { |
429 | auto RegSize = TRI->getRegSizeInBits(Reg, MRI) / 8; |
430 | CSStackSize += RegSize; |
431 | } |
432 | |
433 | CFI->setCalleeSaveAreaSize(CSStackSize); |
434 | |
435 | uint64_t Limit = estimateRSStackSizeLimit(MF, STI); |
436 | |
437 | bool BigFrame = (MFI.estimateStackSize(MF) + CSStackSize >= Limit); |
438 | |
439 | if (BigFrame || CFI->isCRSpilled() || !STI.hasE2()) { |
440 | const TargetRegisterClass *RC = &CSKY::GPRRegClass; |
441 | unsigned size = TRI->getSpillSize(RC: *RC); |
442 | Align align = TRI->getSpillAlign(RC: *RC); |
443 | |
444 | RS->addScavengingFrameIndex(FI: MFI.CreateStackObject(Size: size, Alignment: align, isSpillSlot: false)); |
445 | } |
446 | |
447 | unsigned FnSize = EstimateFunctionSizeInBytes(MF, TII: *TII); |
448 | // Force R15 to be spilled if the function size is > 65534. This enables |
449 | // use of BSR to implement far jump. |
450 | if (FnSize >= ((1 << (16 - 1)) * 2)) |
451 | SavedRegs.set(CSKY::R15); |
452 | |
453 | CFI->setLRIsSpilled(SavedRegs.test(CSKY::R15)); |
454 | } |
455 | |
456 | // Not preserve stack space within prologue for outgoing variables when the |
457 | // function contains variable size objects and let eliminateCallFramePseudoInstr |
458 | // preserve stack space for it. |
459 | bool CSKYFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { |
460 | return !MF.getFrameInfo().hasVarSizedObjects(); |
461 | } |
462 | |
463 | bool CSKYFrameLowering::spillCalleeSavedRegisters( |
464 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
465 | ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
466 | if (CSI.empty()) |
467 | return true; |
468 | |
469 | MachineFunction *MF = MBB.getParent(); |
470 | const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); |
471 | DebugLoc DL; |
472 | if (MI != MBB.end() && !MI->isDebugInstr()) |
473 | DL = MI->getDebugLoc(); |
474 | |
475 | for (auto &CS : CSI) { |
476 | // Insert the spill to the stack frame. |
477 | Register Reg = CS.getReg(); |
478 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
479 | TII.storeRegToStackSlot(MBB, MI, SrcReg: Reg, isKill: true, FrameIndex: CS.getFrameIdx(), RC, TRI, |
480 | VReg: Register()); |
481 | } |
482 | |
483 | return true; |
484 | } |
485 | |
486 | bool CSKYFrameLowering::restoreCalleeSavedRegisters( |
487 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
488 | MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { |
489 | if (CSI.empty()) |
490 | return true; |
491 | |
492 | MachineFunction *MF = MBB.getParent(); |
493 | const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); |
494 | DebugLoc DL; |
495 | if (MI != MBB.end() && !MI->isDebugInstr()) |
496 | DL = MI->getDebugLoc(); |
497 | |
498 | for (auto &CS : reverse(C&: CSI)) { |
499 | Register Reg = CS.getReg(); |
500 | const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); |
501 | TII.loadRegFromStackSlot(MBB, MI, DestReg: Reg, FrameIndex: CS.getFrameIdx(), RC, TRI, |
502 | VReg: Register()); |
503 | assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!" ); |
504 | } |
505 | |
506 | return true; |
507 | } |
508 | |
509 | // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions. |
510 | MachineBasicBlock::iterator CSKYFrameLowering::eliminateCallFramePseudoInstr( |
511 | MachineFunction &MF, MachineBasicBlock &MBB, |
512 | MachineBasicBlock::iterator MI) const { |
513 | Register SPReg = CSKY::R14; |
514 | DebugLoc DL = MI->getDebugLoc(); |
515 | |
516 | if (!hasReservedCallFrame(MF)) { |
517 | // If space has not been reserved for a call frame, ADJCALLSTACKDOWN and |
518 | // ADJCALLSTACKUP must be converted to instructions manipulating the stack |
519 | // pointer. This is necessary when there is a variable length stack |
520 | // allocation (e.g. alloca), which means it's not possible to allocate |
521 | // space for outgoing arguments from within the function prologue. |
522 | int64_t Amount = MI->getOperand(i: 0).getImm(); |
523 | |
524 | if (Amount != 0) { |
525 | // Ensure the stack remains aligned after adjustment. |
526 | Amount = alignSPAdjust(SPAdj: Amount); |
527 | |
528 | if (MI->getOpcode() == CSKY::ADJCALLSTACKDOWN) |
529 | Amount = -Amount; |
530 | |
531 | adjustReg(MBB, MBBI: MI, DL, DestReg: SPReg, SrcReg: SPReg, Val: Amount, Flag: MachineInstr::NoFlags); |
532 | } |
533 | } |
534 | |
535 | return MBB.erase(I: MI); |
536 | } |
537 | |
538 | void CSKYFrameLowering::adjustReg(MachineBasicBlock &MBB, |
539 | MachineBasicBlock::iterator MBBI, |
540 | const DebugLoc &DL, Register DestReg, |
541 | Register SrcReg, int64_t Val, |
542 | MachineInstr::MIFlag Flag) const { |
543 | const CSKYInstrInfo *TII = STI.getInstrInfo(); |
544 | |
545 | if (DestReg == SrcReg && Val == 0) |
546 | return; |
547 | |
548 | // TODO: Add 16-bit instruction support with immediate num |
549 | if (STI.hasE2() && isUInt<12>(x: std::abs(i: Val) - 1)) { |
550 | BuildMI(MBB, MBBI, DL, TII->get(Val < 0 ? CSKY::SUBI32 : CSKY::ADDI32), |
551 | DestReg) |
552 | .addReg(SrcReg) |
553 | .addImm(std::abs(Val)) |
554 | .setMIFlag(Flag); |
555 | } else if (!STI.hasE2() && isShiftedUInt<7, 2>(x: std::abs(i: Val))) { |
556 | BuildMI(MBB, MBBI, DL, |
557 | TII->get(Val < 0 ? CSKY::SUBI16SPSP : CSKY::ADDI16SPSP), CSKY::R14) |
558 | .addReg(CSKY::R14, RegState::Kill) |
559 | .addImm(std::abs(Val)) |
560 | .setMIFlag(Flag); |
561 | } else { |
562 | |
563 | unsigned Op = 0; |
564 | |
565 | if (STI.hasE2()) { |
566 | Op = Val < 0 ? CSKY::SUBU32 : CSKY::ADDU32; |
567 | } else { |
568 | assert(SrcReg == DestReg); |
569 | Op = Val < 0 ? CSKY::SUBU16XZ : CSKY::ADDU16XZ; |
570 | } |
571 | |
572 | Register ScratchReg = TII->movImm(MBB, MBBI, DL, Val: std::abs(i: Val), Flag); |
573 | |
574 | BuildMI(MBB, MBBI, DL, TII->get(Op), DestReg) |
575 | .addReg(SrcReg) |
576 | .addReg(ScratchReg, RegState::Kill) |
577 | .setMIFlag(Flag); |
578 | } |
579 | } |
580 | |
581 | StackOffset |
582 | CSKYFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, |
583 | Register &FrameReg) const { |
584 | const CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
585 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
586 | const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); |
587 | const auto &CSI = MFI.getCalleeSavedInfo(); |
588 | |
589 | int MinCSFI = 0; |
590 | int MaxCSFI = -1; |
591 | |
592 | int Offset = MFI.getObjectOffset(ObjectIdx: FI) + MFI.getOffsetAdjustment(); |
593 | |
594 | if (CSI.size()) { |
595 | MinCSFI = CSI[0].getFrameIdx(); |
596 | MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); |
597 | } |
598 | |
599 | if (FI >= MinCSFI && FI <= MaxCSFI) { |
600 | FrameReg = CSKY::R14; |
601 | Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize(); |
602 | } else if (RI->hasStackRealignment(MF)) { |
603 | assert(hasFP(MF)); |
604 | if (!MFI.isFixedObjectIndex(ObjectIdx: FI)) { |
605 | FrameReg = hasBP(MF) ? getBPReg(STI) : CSKY::R14; |
606 | Offset += MFI.getStackSize(); |
607 | } else { |
608 | FrameReg = getFPReg(STI); |
609 | Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize(); |
610 | } |
611 | } else { |
612 | if (MFI.isFixedObjectIndex(ObjectIdx: FI) && hasFP(MF)) { |
613 | FrameReg = getFPReg(STI); |
614 | Offset += CFI->getVarArgsSaveSize() + CFI->getCalleeSaveAreaSize(); |
615 | } else { |
616 | FrameReg = hasBP(MF) ? getBPReg(STI) : CSKY::R14; |
617 | Offset += MFI.getStackSize(); |
618 | } |
619 | } |
620 | |
621 | return StackOffset::getFixed(Fixed: Offset); |
622 | } |
623 | |