1326938Sdim//===-- llvm/CodeGen/TargetFrameLowering.h ----------------------*- C++ -*-===//
2326938Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326938Sdim//
7326938Sdim//===----------------------------------------------------------------------===//
8326938Sdim//
9326938Sdim// Interface to describe the layout of a stack frame on the target machine.
10326938Sdim//
11326938Sdim//===----------------------------------------------------------------------===//
12326938Sdim
13326938Sdim#ifndef LLVM_CODEGEN_TARGETFRAMELOWERING_H
14326938Sdim#define LLVM_CODEGEN_TARGETFRAMELOWERING_H
15326938Sdim
16326938Sdim#include "llvm/CodeGen/MachineBasicBlock.h"
17353358Sdim#include "llvm/ADT/StringSwitch.h"
18326938Sdim#include <utility>
19326938Sdim#include <vector>
20326938Sdim
21326938Sdimnamespace llvm {
22326938Sdim  class BitVector;
23326938Sdim  class CalleeSavedInfo;
24326938Sdim  class MachineFunction;
25326938Sdim  class RegScavenger;
26326938Sdim
27353358Sdimnamespace TargetStackID {
28353358Sdim  enum Value {
29353358Sdim    Default = 0,
30353358Sdim    SGPRSpill = 1,
31360784Sdim    SVEVector = 2,
32353358Sdim    NoAlloc = 255
33353358Sdim  };
34353358Sdim}
35353358Sdim
36326938Sdim/// Information about stack frame layout on the target.  It holds the direction
37326938Sdim/// of stack growth, the known stack alignment on entry to each function, and
38326938Sdim/// the offset to the locals area.
39326938Sdim///
40326938Sdim/// The offset to the local area is the offset from the stack pointer on
41326938Sdim/// function entry to the first location where function data (local variables,
42326938Sdim/// spill locations) can be stored.
43326938Sdimclass TargetFrameLowering {
44326938Sdimpublic:
45326938Sdim  enum StackDirection {
46326938Sdim    StackGrowsUp,        // Adding to the stack increases the stack address
47326938Sdim    StackGrowsDown       // Adding to the stack decreases the stack address
48326938Sdim  };
49326938Sdim
50326938Sdim  // Maps a callee saved register to a stack slot with a fixed offset.
51326938Sdim  struct SpillSlot {
52326938Sdim    unsigned Reg;
53326938Sdim    int Offset; // Offset relative to stack pointer on function entry.
54326938Sdim  };
55326938Sdimprivate:
56326938Sdim  StackDirection StackDir;
57360784Sdim  Align StackAlignment;
58360784Sdim  Align TransientStackAlignment;
59326938Sdim  int LocalAreaOffset;
60326938Sdim  bool StackRealignable;
61326938Sdimpublic:
62360784Sdim  TargetFrameLowering(StackDirection D, Align StackAl, int LAO,
63360784Sdim                      Align TransAl = Align::None(), bool StackReal = true)
64360784Sdim      : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl),
65360784Sdim        LocalAreaOffset(LAO), StackRealignable(StackReal) {}
66326938Sdim
67326938Sdim  virtual ~TargetFrameLowering();
68326938Sdim
69326938Sdim  // These methods return information that describes the abstract stack layout
70326938Sdim  // of the target machine.
71326938Sdim
72326938Sdim  /// getStackGrowthDirection - Return the direction the stack grows
73326938Sdim  ///
74326938Sdim  StackDirection getStackGrowthDirection() const { return StackDir; }
75326938Sdim
76326938Sdim  /// getStackAlignment - This method returns the number of bytes to which the
77326938Sdim  /// stack pointer must be aligned on entry to a function.  Typically, this
78326938Sdim  /// is the largest alignment for any data object in the target.
79326938Sdim  ///
80360784Sdim  unsigned getStackAlignment() const { return StackAlignment.value(); }
81326938Sdim
82326938Sdim  /// alignSPAdjust - This method aligns the stack adjustment to the correct
83326938Sdim  /// alignment.
84326938Sdim  ///
85326938Sdim  int alignSPAdjust(int SPAdj) const {
86326938Sdim    if (SPAdj < 0) {
87326938Sdim      SPAdj = -alignTo(-SPAdj, StackAlignment);
88326938Sdim    } else {
89326938Sdim      SPAdj = alignTo(SPAdj, StackAlignment);
90326938Sdim    }
91326938Sdim    return SPAdj;
92326938Sdim  }
93326938Sdim
94326938Sdim  /// getTransientStackAlignment - This method returns the number of bytes to
95326938Sdim  /// which the stack pointer must be aligned at all times, even between
96326938Sdim  /// calls.
97326938Sdim  ///
98326938Sdim  unsigned getTransientStackAlignment() const {
99360784Sdim    return TransientStackAlignment.value();
100326938Sdim  }
101326938Sdim
102326938Sdim  /// isStackRealignable - This method returns whether the stack can be
103326938Sdim  /// realigned.
104326938Sdim  bool isStackRealignable() const {
105326938Sdim    return StackRealignable;
106326938Sdim  }
107326938Sdim
108326938Sdim  /// Return the skew that has to be applied to stack alignment under
109326938Sdim  /// certain conditions (e.g. stack was adjusted before function \p MF
110326938Sdim  /// was called).
111326938Sdim  virtual unsigned getStackAlignmentSkew(const MachineFunction &MF) const;
112326938Sdim
113326938Sdim  /// getOffsetOfLocalArea - This method returns the offset of the local area
114326938Sdim  /// from the stack pointer on entrance to a function.
115326938Sdim  ///
116326938Sdim  int getOffsetOfLocalArea() const { return LocalAreaOffset; }
117326938Sdim
118326938Sdim  /// isFPCloseToIncomingSP - Return true if the frame pointer is close to
119326938Sdim  /// the incoming stack pointer, false if it is close to the post-prologue
120326938Sdim  /// stack pointer.
121326938Sdim  virtual bool isFPCloseToIncomingSP() const { return true; }
122326938Sdim
123326938Sdim  /// assignCalleeSavedSpillSlots - Allows target to override spill slot
124326938Sdim  /// assignment logic.  If implemented, assignCalleeSavedSpillSlots() should
125326938Sdim  /// assign frame slots to all CSI entries and return true.  If this method
126326938Sdim  /// returns false, spill slots will be assigned using generic implementation.
127326938Sdim  /// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of
128326938Sdim  /// CSI.
129326938Sdim  virtual bool
130326938Sdim  assignCalleeSavedSpillSlots(MachineFunction &MF,
131326938Sdim                              const TargetRegisterInfo *TRI,
132326938Sdim                              std::vector<CalleeSavedInfo> &CSI) const {
133326938Sdim    return false;
134326938Sdim  }
135326938Sdim
136326938Sdim  /// getCalleeSavedSpillSlots - This method returns a pointer to an array of
137326938Sdim  /// pairs, that contains an entry for each callee saved register that must be
138326938Sdim  /// spilled to a particular stack location if it is spilled.
139326938Sdim  ///
140326938Sdim  /// Each entry in this array contains a <register,offset> pair, indicating the
141326938Sdim  /// fixed offset from the incoming stack pointer that each register should be
142326938Sdim  /// spilled at. If a register is not listed here, the code generator is
143326938Sdim  /// allowed to spill it anywhere it chooses.
144326938Sdim  ///
145326938Sdim  virtual const SpillSlot *
146326938Sdim  getCalleeSavedSpillSlots(unsigned &NumEntries) const {
147326938Sdim    NumEntries = 0;
148326938Sdim    return nullptr;
149326938Sdim  }
150326938Sdim
151326938Sdim  /// targetHandlesStackFrameRounding - Returns true if the target is
152326938Sdim  /// responsible for rounding up the stack frame (probably at emitPrologue
153326938Sdim  /// time).
154326938Sdim  virtual bool targetHandlesStackFrameRounding() const {
155326938Sdim    return false;
156326938Sdim  }
157326938Sdim
158326938Sdim  /// Returns true if the target will correctly handle shrink wrapping.
159326938Sdim  virtual bool enableShrinkWrapping(const MachineFunction &MF) const {
160326938Sdim    return false;
161326938Sdim  }
162326938Sdim
163326938Sdim  /// Returns true if the stack slot holes in the fixed and callee-save stack
164326938Sdim  /// area should be used when allocating other stack locations to reduce stack
165326938Sdim  /// size.
166326938Sdim  virtual bool enableStackSlotScavenging(const MachineFunction &MF) const {
167326938Sdim    return false;
168326938Sdim  }
169326938Sdim
170341825Sdim  /// Returns true if the target can safely skip saving callee-saved registers
171341825Sdim  /// for noreturn nounwind functions.
172341825Sdim  virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const;
173341825Sdim
174326938Sdim  /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
175326938Sdim  /// the function.
176326938Sdim  virtual void emitPrologue(MachineFunction &MF,
177326938Sdim                            MachineBasicBlock &MBB) const = 0;
178326938Sdim  virtual void emitEpilogue(MachineFunction &MF,
179326938Sdim                            MachineBasicBlock &MBB) const = 0;
180326938Sdim
181326938Sdim  /// Replace a StackProbe stub (if any) with the actual probe code inline
182326938Sdim  virtual void inlineStackProbe(MachineFunction &MF,
183326938Sdim                                MachineBasicBlock &PrologueMBB) const {}
184326938Sdim
185326938Sdim  /// Adjust the prologue to have the function use segmented stacks. This works
186326938Sdim  /// by adding a check even before the "normal" function prologue.
187326938Sdim  virtual void adjustForSegmentedStacks(MachineFunction &MF,
188326938Sdim                                        MachineBasicBlock &PrologueMBB) const {}
189326938Sdim
190326938Sdim  /// Adjust the prologue to add Erlang Run-Time System (ERTS) specific code in
191326938Sdim  /// the assembly prologue to explicitly handle the stack.
192326938Sdim  virtual void adjustForHiPEPrologue(MachineFunction &MF,
193326938Sdim                                     MachineBasicBlock &PrologueMBB) const {}
194326938Sdim
195326938Sdim  /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
196326938Sdim  /// saved registers and returns true if it isn't possible / profitable to do
197326938Sdim  /// so by issuing a series of store instructions via
198326938Sdim  /// storeRegToStackSlot(). Returns false otherwise.
199326938Sdim  virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
200326938Sdim                                         MachineBasicBlock::iterator MI,
201326938Sdim                                        const std::vector<CalleeSavedInfo> &CSI,
202326938Sdim                                         const TargetRegisterInfo *TRI) const {
203326938Sdim    return false;
204326938Sdim  }
205326938Sdim
206326938Sdim  /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee
207326938Sdim  /// saved registers and returns true if it isn't possible / profitable to do
208326938Sdim  /// so by issuing a series of load instructions via loadRegToStackSlot().
209326938Sdim  /// If it returns true, and any of the registers in CSI is not restored,
210326938Sdim  /// it sets the corresponding Restored flag in CSI to false.
211326938Sdim  /// Returns false otherwise.
212326938Sdim  virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
213326938Sdim                                           MachineBasicBlock::iterator MI,
214326938Sdim                                           std::vector<CalleeSavedInfo> &CSI,
215326938Sdim                                        const TargetRegisterInfo *TRI) const {
216326938Sdim    return false;
217326938Sdim  }
218326938Sdim
219344779Sdim  /// Return true if the target wants to keep the frame pointer regardless of
220344779Sdim  /// the function attribute "frame-pointer".
221344779Sdim  virtual bool keepFramePointer(const MachineFunction &MF) const {
222344779Sdim    return false;
223344779Sdim  }
224326938Sdim
225326938Sdim  /// hasFP - Return true if the specified function should have a dedicated
226326938Sdim  /// frame pointer register. For most targets this is true only if the function
227326938Sdim  /// has variable sized allocas or if frame pointer elimination is disabled.
228326938Sdim  virtual bool hasFP(const MachineFunction &MF) const = 0;
229326938Sdim
230326938Sdim  /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
231326938Sdim  /// not required, we reserve argument space for call sites in the function
232326938Sdim  /// immediately on entry to the current function. This eliminates the need for
233326938Sdim  /// add/sub sp brackets around call sites. Returns true if the call frame is
234326938Sdim  /// included as part of the stack frame.
235326938Sdim  virtual bool hasReservedCallFrame(const MachineFunction &MF) const {
236326938Sdim    return !hasFP(MF);
237326938Sdim  }
238326938Sdim
239326938Sdim  /// canSimplifyCallFramePseudos - When possible, it's best to simplify the
240326938Sdim  /// call frame pseudo ops before doing frame index elimination. This is
241326938Sdim  /// possible only when frame index references between the pseudos won't
242326938Sdim  /// need adjusting for the call frame adjustments. Normally, that's true
243326938Sdim  /// if the function has a reserved call frame or a frame pointer. Some
244326938Sdim  /// targets (Thumb2, for example) may have more complicated criteria,
245326938Sdim  /// however, and can override this behavior.
246326938Sdim  virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const {
247326938Sdim    return hasReservedCallFrame(MF) || hasFP(MF);
248326938Sdim  }
249326938Sdim
250326938Sdim  // needsFrameIndexResolution - Do we need to perform FI resolution for
251326938Sdim  // this function. Normally, this is required only when the function
252326938Sdim  // has any stack objects. However, targets may want to override this.
253326938Sdim  virtual bool needsFrameIndexResolution(const MachineFunction &MF) const;
254326938Sdim
255326938Sdim  /// getFrameIndexReference - This method should return the base register
256326938Sdim  /// and offset used to reference a frame index location. The offset is
257326938Sdim  /// returned directly, and the base register is returned via FrameReg.
258326938Sdim  virtual int getFrameIndexReference(const MachineFunction &MF, int FI,
259326938Sdim                                     unsigned &FrameReg) const;
260326938Sdim
261326938Sdim  /// Same as \c getFrameIndexReference, except that the stack pointer (as
262326938Sdim  /// opposed to the frame pointer) will be the preferred value for \p
263326938Sdim  /// FrameReg. This is generally used for emitting statepoint or EH tables that
264326938Sdim  /// use offsets from RSP.  If \p IgnoreSPUpdates is true, the returned
265326938Sdim  /// offset is only guaranteed to be valid with respect to the value of SP at
266326938Sdim  /// the end of the prologue.
267326938Sdim  virtual int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
268326938Sdim                                             unsigned &FrameReg,
269326938Sdim                                             bool IgnoreSPUpdates) const {
270326938Sdim    // Always safe to dispatch to getFrameIndexReference.
271326938Sdim    return getFrameIndexReference(MF, FI, FrameReg);
272326938Sdim  }
273326938Sdim
274353358Sdim  /// getNonLocalFrameIndexReference - This method returns the offset used to
275353358Sdim  /// reference a frame index location. The offset can be from either FP/BP/SP
276353358Sdim  /// based on which base register is returned by llvm.localaddress.
277353358Sdim  virtual int getNonLocalFrameIndexReference(const MachineFunction &MF,
278353358Sdim                                       int FI) const {
279353358Sdim    // By default, dispatch to getFrameIndexReference. Interested targets can
280353358Sdim    // override this.
281353358Sdim    unsigned FrameReg;
282353358Sdim    return getFrameIndexReference(MF, FI, FrameReg);
283353358Sdim  }
284353358Sdim
285360784Sdim  /// Returns the callee-saved registers as computed by determineCalleeSaves
286360784Sdim  /// in the BitVector \p SavedRegs.
287360784Sdim  virtual void getCalleeSaves(const MachineFunction &MF,
288360784Sdim                                  BitVector &SavedRegs) const;
289360784Sdim
290326938Sdim  /// This method determines which of the registers reported by
291326938Sdim  /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved.
292326938Sdim  /// The default implementation checks populates the \p SavedRegs bitset with
293326938Sdim  /// all registers which are modified in the function, targets may override
294326938Sdim  /// this function to save additional registers.
295326938Sdim  /// This method also sets up the register scavenger ensuring there is a free
296326938Sdim  /// register or a frameindex available.
297360784Sdim  /// This method should not be called by any passes outside of PEI, because
298360784Sdim  /// it may change state passed in by \p MF and \p RS. The preferred
299360784Sdim  /// interface outside PEI is getCalleeSaves.
300326938Sdim  virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
301326938Sdim                                    RegScavenger *RS = nullptr) const;
302326938Sdim
303326938Sdim  /// processFunctionBeforeFrameFinalized - This method is called immediately
304326938Sdim  /// before the specified function's frame layout (MF.getFrameInfo()) is
305326938Sdim  /// finalized.  Once the frame is finalized, MO_FrameIndex operands are
306326938Sdim  /// replaced with direct constants.  This method is optional.
307326938Sdim  ///
308326938Sdim  virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF,
309326938Sdim                                             RegScavenger *RS = nullptr) const {
310326938Sdim  }
311326938Sdim
312326938Sdim  virtual unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const {
313326938Sdim    report_fatal_error("WinEH not implemented for this target");
314326938Sdim  }
315326938Sdim
316326938Sdim  /// This method is called during prolog/epilog code insertion to eliminate
317326938Sdim  /// call frame setup and destroy pseudo instructions (but only if the Target
318326938Sdim  /// is using them).  It is responsible for eliminating these instructions,
319326938Sdim  /// replacing them with concrete instructions.  This method need only be
320326938Sdim  /// implemented if using call frame setup/destroy pseudo instructions.
321326938Sdim  /// Returns an iterator pointing to the instruction after the replaced one.
322326938Sdim  virtual MachineBasicBlock::iterator
323326938Sdim  eliminateCallFramePseudoInstr(MachineFunction &MF,
324326938Sdim                                MachineBasicBlock &MBB,
325326938Sdim                                MachineBasicBlock::iterator MI) const {
326326938Sdim    llvm_unreachable("Call Frame Pseudo Instructions do not exist on this "
327326938Sdim                     "target!");
328326938Sdim  }
329326938Sdim
330326938Sdim
331326938Sdim  /// Order the symbols in the local stack frame.
332326938Sdim  /// The list of objects that we want to order is in \p objectsToAllocate as
333326938Sdim  /// indices into the MachineFrameInfo. The array can be reordered in any way
334326938Sdim  /// upon return. The contents of the array, however, may not be modified (i.e.
335326938Sdim  /// only their order may be changed).
336326938Sdim  /// By default, just maintain the original order.
337326938Sdim  virtual void
338326938Sdim  orderFrameObjects(const MachineFunction &MF,
339326938Sdim                    SmallVectorImpl<int> &objectsToAllocate) const {
340326938Sdim  }
341326938Sdim
342326938Sdim  /// Check whether or not the given \p MBB can be used as a prologue
343326938Sdim  /// for the target.
344326938Sdim  /// The prologue will be inserted first in this basic block.
345326938Sdim  /// This method is used by the shrink-wrapping pass to decide if
346326938Sdim  /// \p MBB will be correctly handled by the target.
347326938Sdim  /// As soon as the target enable shrink-wrapping without overriding
348326938Sdim  /// this method, we assume that each basic block is a valid
349326938Sdim  /// prologue.
350326938Sdim  virtual bool canUseAsPrologue(const MachineBasicBlock &MBB) const {
351326938Sdim    return true;
352326938Sdim  }
353326938Sdim
354326938Sdim  /// Check whether or not the given \p MBB can be used as a epilogue
355326938Sdim  /// for the target.
356326938Sdim  /// The epilogue will be inserted before the first terminator of that block.
357326938Sdim  /// This method is used by the shrink-wrapping pass to decide if
358326938Sdim  /// \p MBB will be correctly handled by the target.
359326938Sdim  /// As soon as the target enable shrink-wrapping without overriding
360326938Sdim  /// this method, we assume that each basic block is a valid
361326938Sdim  /// epilogue.
362326938Sdim  virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const {
363326938Sdim    return true;
364326938Sdim  }
365326938Sdim
366360784Sdim  /// Returns the StackID that scalable vectors should be associated with.
367360784Sdim  virtual TargetStackID::Value getStackIDForScalableVectors() const {
368360784Sdim    return TargetStackID::Default;
369360784Sdim  }
370360784Sdim
371353358Sdim  virtual bool isSupportedStackID(TargetStackID::Value ID) const {
372353358Sdim    switch (ID) {
373353358Sdim    default:
374353358Sdim      return false;
375353358Sdim    case TargetStackID::Default:
376353358Sdim    case TargetStackID::NoAlloc:
377353358Sdim      return true;
378353358Sdim    }
379353358Sdim  }
380353358Sdim
381326938Sdim  /// Check if given function is safe for not having callee saved registers.
382326938Sdim  /// This is used when interprocedural register allocation is enabled.
383360784Sdim  static bool isSafeForNoCSROpt(const Function &F);
384360784Sdim
385360784Sdim  /// Check if the no-CSR optimisation is profitable for the given function.
386360784Sdim  virtual bool isProfitableForNoCSROpt(const Function &F) const {
387326938Sdim    return true;
388326938Sdim  }
389341825Sdim
390341825Sdim  /// Return initial CFA offset value i.e. the one valid at the beginning of the
391341825Sdim  /// function (before any stack operations).
392341825Sdim  virtual int getInitialCFAOffset(const MachineFunction &MF) const;
393341825Sdim
394341825Sdim  /// Return initial CFA register value i.e. the one valid at the beginning of
395341825Sdim  /// the function (before any stack operations).
396341825Sdim  virtual unsigned getInitialCFARegister(const MachineFunction &MF) const;
397326938Sdim};
398326938Sdim
399326938Sdim} // End llvm namespace
400326938Sdim
401326938Sdim#endif
402