1//===-- VEFrameLowering.cpp - VE 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 VE implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "VEFrameLowering.h"
14#include "VEInstrInfo.h"
15#include "VESubtarget.h"
16#include "llvm/CodeGen/MachineFrameInfo.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineModuleInfo.h"
20#include "llvm/CodeGen/MachineRegisterInfo.h"
21#include "llvm/CodeGen/RegisterScavenging.h"
22#include "llvm/IR/DataLayout.h"
23#include "llvm/IR/Function.h"
24#include "llvm/Support/CommandLine.h"
25#include "llvm/Target/TargetOptions.h"
26#include "llvm/Support/MathExtras.h"
27
28using namespace llvm;
29
30VEFrameLowering::VEFrameLowering(const VESubtarget &ST)
31    : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(16), 0,
32                          Align(16)) {}
33
34void VEFrameLowering::emitPrologueInsns(MachineFunction &MF,
35                                        MachineBasicBlock &MBB,
36                                        MachineBasicBlock::iterator MBBI,
37                                        int NumBytes,
38                                        bool RequireFPUpdate) const {
39
40  DebugLoc dl;
41  const VEInstrInfo &TII =
42      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
43  // Insert following codes here as prologue
44  //
45  //    st %fp, 0(,%sp)
46  //    st %lr, 8(,%sp)
47  //    st %got, 24(,%sp)
48  //    st %plt, 32(,%sp)
49  //    or %fp, 0, %sp
50
51  BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
52      .addReg(VE::SX11)
53      .addImm(0)
54      .addReg(VE::SX9);
55  BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
56      .addReg(VE::SX11)
57      .addImm(8)
58      .addReg(VE::SX10);
59  BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
60      .addReg(VE::SX11)
61      .addImm(24)
62      .addReg(VE::SX15);
63  BuildMI(MBB, MBBI, dl, TII.get(VE::STSri))
64      .addReg(VE::SX11)
65      .addImm(32)
66      .addReg(VE::SX16);
67  BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX9)
68      .addReg(VE::SX11)
69      .addImm(0);
70}
71
72void VEFrameLowering::emitEpilogueInsns(MachineFunction &MF,
73                                        MachineBasicBlock &MBB,
74                                        MachineBasicBlock::iterator MBBI,
75                                        int NumBytes,
76                                        bool RequireFPUpdate) const {
77
78  DebugLoc dl;
79  const VEInstrInfo &TII =
80      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
81  // Insert following codes here as epilogue
82  //
83  //    or %sp, 0, %fp
84  //    ld %got, 32(,%sp)
85  //    ld %plt, 24(,%sp)
86  //    ld %lr, 8(,%sp)
87  //    ld %fp, 0(,%sp)
88
89  BuildMI(MBB, MBBI, dl, TII.get(VE::ORri), VE::SX11)
90      .addReg(VE::SX9)
91      .addImm(0);
92  BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX16)
93      .addReg(VE::SX11)
94      .addImm(32);
95  BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX15)
96      .addReg(VE::SX11)
97      .addImm(24);
98  BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX10)
99      .addReg(VE::SX11)
100      .addImm(8);
101  BuildMI(MBB, MBBI, dl, TII.get(VE::LDSri), VE::SX9)
102      .addReg(VE::SX11)
103      .addImm(0);
104}
105
106void VEFrameLowering::emitSPAdjustment(MachineFunction &MF,
107                                       MachineBasicBlock &MBB,
108                                       MachineBasicBlock::iterator MBBI,
109                                       int NumBytes) const {
110  DebugLoc dl;
111  const VEInstrInfo &TII =
112      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
113
114  if (NumBytes >= -64 && NumBytes < 63) {
115    BuildMI(MBB, MBBI, dl, TII.get(VE::ADXri), VE::SX11)
116        .addReg(VE::SX11)
117        .addImm(NumBytes);
118    return;
119  }
120
121  // Emit following codes.  This clobbers SX13 which we always know is
122  // available here.
123  //   lea     %s13,%lo(NumBytes)
124  //   and     %s13,%s13,(32)0
125  //   lea.sl  %sp,%hi(NumBytes)(%sp, %s13)
126  BuildMI(MBB, MBBI, dl, TII.get(VE::LEAzzi), VE::SX13)
127      .addImm(LO32(NumBytes));
128  BuildMI(MBB, MBBI, dl, TII.get(VE::ANDrm0), VE::SX13)
129      .addReg(VE::SX13)
130      .addImm(32);
131  BuildMI(MBB, MBBI, dl, TII.get(VE::LEASLrri), VE::SX11)
132      .addReg(VE::SX11)
133      .addReg(VE::SX13)
134      .addImm(HI32(NumBytes));
135}
136
137void VEFrameLowering::emitSPExtend(MachineFunction &MF, MachineBasicBlock &MBB,
138                                   MachineBasicBlock::iterator MBBI,
139                                   int NumBytes) const {
140  DebugLoc dl;
141  const VEInstrInfo &TII =
142      *static_cast<const VEInstrInfo *>(MF.getSubtarget().getInstrInfo());
143
144  // Emit following codes.  It is not possible to insert multiple
145  // BasicBlocks in PEI pass, so we emit two pseudo instructions here.
146  //
147  //   EXTEND_STACK                     // pseudo instrcution
148  //   EXTEND_STACK_GUARD               // pseudo instrcution
149  //
150  // EXTEND_STACK pseudo will be converted by ExpandPostRA pass into
151  // following instructions with multiple basic blocks later.
152  //
153  // thisBB:
154  //   brge.l.t %sp, %sl, sinkBB
155  // syscallBB:
156  //   ld      %s61, 0x18(, %tp)        // load param area
157  //   or      %s62, 0, %s0             // spill the value of %s0
158  //   lea     %s63, 0x13b              // syscall # of grow
159  //   shm.l   %s63, 0x0(%s61)          // store syscall # at addr:0
160  //   shm.l   %sl, 0x8(%s61)           // store old limit at addr:8
161  //   shm.l   %sp, 0x10(%s61)          // store new limit at addr:16
162  //   monc                             // call monitor
163  //   or      %s0, 0, %s62             // restore the value of %s0
164  // sinkBB:
165  //
166  // EXTEND_STACK_GUARD pseudo will be simply eliminated by ExpandPostRA
167  // pass.  This pseudo is required to be at the next of EXTEND_STACK
168  // pseudo in order to protect iteration loop in ExpandPostRA.
169
170  BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK));
171  BuildMI(MBB, MBBI, dl, TII.get(VE::EXTEND_STACK_GUARD));
172}
173
174void VEFrameLowering::emitPrologue(MachineFunction &MF,
175                                   MachineBasicBlock &MBB) const {
176  assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
177  MachineFrameInfo &MFI = MF.getFrameInfo();
178  const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
179  const VEInstrInfo &TII =
180      *static_cast<const VEInstrInfo *>(Subtarget.getInstrInfo());
181  const VERegisterInfo &RegInfo =
182      *static_cast<const VERegisterInfo *>(Subtarget.getRegisterInfo());
183  MachineBasicBlock::iterator MBBI = MBB.begin();
184  // Debug location must be unknown since the first debug location is used
185  // to determine the end of the prologue.
186  DebugLoc dl;
187  bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF);
188
189  // FIXME: unfortunately, returning false from canRealignStack
190  // actually just causes needsStackRealignment to return false,
191  // rather than reporting an error, as would be sensible. This is
192  // poor, but fixing that bogosity is going to be a large project.
193  // For now, just see if it's lied, and report an error here.
194  if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment())
195    report_fatal_error("Function \"" + Twine(MF.getName()) +
196                       "\" required "
197                       "stack re-alignment, but LLVM couldn't handle it "
198                       "(probably because it has a dynamic alloca).");
199
200  // Get the number of bytes to allocate from the FrameInfo
201  int NumBytes = (int)MFI.getStackSize();
202  // The VE ABI requires a reserved 176-byte area in the user's stack, starting
203  // at %sp + 16. This is for the callee Register Save Area (RSA).
204  //
205  // We therefore need to add that offset to the total stack size
206  // after all the stack objects are placed by
207  // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack
208  // needs to be aligned *after* the extra size is added, we need to disable
209  // calculateFrameObjectOffsets's built-in stack alignment, by having
210  // targetHandlesStackFrameRounding return true.
211
212  // Add the extra call frame stack size, if needed. (This is the same
213  // code as in PrologEpilogInserter, but also gets disabled by
214  // targetHandlesStackFrameRounding)
215  if (MFI.adjustsStack() && hasReservedCallFrame(MF))
216    NumBytes += MFI.getMaxCallFrameSize();
217
218  // Adds the VE subtarget-specific spill area to the stack
219  // size. Also ensures target-required alignment.
220  NumBytes = Subtarget.getAdjustedFrameSize(NumBytes);
221
222  // Finally, ensure that the size is sufficiently aligned for the
223  // data on the stack.
224  if (MFI.getMaxAlignment() > 0) {
225    NumBytes = alignTo(NumBytes, MFI.getMaxAlignment());
226  }
227
228  // Update stack size with corrected value.
229  MFI.setStackSize(NumBytes);
230
231  // Emit Prologue instructions to save %lr
232  emitPrologueInsns(MF, MBB, MBBI, NumBytes, true);
233
234  // Emit stack adjust instructions
235  emitSPAdjustment(MF, MBB, MBBI, -NumBytes);
236
237  // Emit stack extend instructions
238  emitSPExtend(MF, MBB, MBBI, -NumBytes);
239
240  unsigned regFP = RegInfo.getDwarfRegNum(VE::SX9, true);
241
242  // Emit ".cfi_def_cfa_register 30".
243  unsigned CFIIndex =
244      MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP));
245  BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
246      .addCFIIndex(CFIIndex);
247
248  // Emit ".cfi_window_save".
249  CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));
250  BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
251      .addCFIIndex(CFIIndex);
252}
253
254MachineBasicBlock::iterator VEFrameLowering::eliminateCallFramePseudoInstr(
255    MachineFunction &MF, MachineBasicBlock &MBB,
256    MachineBasicBlock::iterator I) const {
257  if (!hasReservedCallFrame(MF)) {
258    MachineInstr &MI = *I;
259    int Size = MI.getOperand(0).getImm();
260    if (MI.getOpcode() == VE::ADJCALLSTACKDOWN)
261      Size = -Size;
262
263    if (Size)
264      emitSPAdjustment(MF, MBB, I, Size);
265  }
266  return MBB.erase(I);
267}
268
269void VEFrameLowering::emitEpilogue(MachineFunction &MF,
270                                   MachineBasicBlock &MBB) const {
271  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
272  DebugLoc dl = MBBI->getDebugLoc();
273  MachineFrameInfo &MFI = MF.getFrameInfo();
274
275  int NumBytes = (int)MFI.getStackSize();
276
277  // Emit Epilogue instructions to restore %lr
278  emitEpilogueInsns(MF, MBB, MBBI, NumBytes, true);
279}
280
281bool VEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
282  // Reserve call frame if there are no variable sized objects on the stack.
283  return !MF.getFrameInfo().hasVarSizedObjects();
284}
285
286// hasFP - Return true if the specified function should have a dedicated frame
287// pointer register.  This is true if the function has variable sized allocas or
288// if frame pointer elimination is disabled.
289bool VEFrameLowering::hasFP(const MachineFunction &MF) const {
290  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
291
292  const MachineFrameInfo &MFI = MF.getFrameInfo();
293  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
294         RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() ||
295         MFI.isFrameAddressTaken();
296}
297
298int VEFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
299                                            unsigned &FrameReg) const {
300  // Addressable stack objects are accessed using neg. offsets from
301  // %fp, or positive offsets from %sp.
302  int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
303  FrameReg = VE::SX11; // %sp
304  return FrameOffset + MF.getFrameInfo().getStackSize();
305}
306
307bool VEFrameLowering::isLeafProc(MachineFunction &MF) const {
308
309  MachineRegisterInfo &MRI = MF.getRegInfo();
310  MachineFrameInfo &MFI = MF.getFrameInfo();
311
312  return !MFI.hasCalls()                 // No calls
313         && !MRI.isPhysRegUsed(VE::SX18) // Registers within limits
314                                         //   (s18 is first CSR)
315         && !MRI.isPhysRegUsed(VE::SX11) // %sp un-used
316         && !hasFP(MF);                  // Don't need %fp
317}
318
319void VEFrameLowering::determineCalleeSaves(MachineFunction &MF,
320                                           BitVector &SavedRegs,
321                                           RegScavenger *RS) const {
322  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
323
324  assert(isLeafProc(MF) && "TODO implement for non-leaf procs");
325}
326