xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64FrameLowering.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //==-- AArch64FrameLowering.h - TargetFrameLowering for AArch64 --*- 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 //
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
14 #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
15 
16 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
17 #include "llvm/CodeGen/TargetFrameLowering.h"
18 #include "llvm/Support/TypeSize.h"
19 
20 namespace llvm {
21 
22 class AArch64FrameLowering : public TargetFrameLowering {
23 public:
AArch64FrameLowering()24   explicit AArch64FrameLowering()
25       : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16),
26                             true /*StackRealignable*/) {}
27 
28   void resetCFIToInitialState(MachineBasicBlock &MBB) const override;
29 
30   MachineBasicBlock::iterator
31   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
32                                 MachineBasicBlock::iterator I) const override;
33 
34   /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
35   /// the function.
36   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
37   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
38 
39   /// Harden the entire function with pac-ret.
40   ///
41   /// If pac-ret+leaf is requested, we want to harden as much code as possible.
42   /// This function inserts pac-ret hardening at the points where prologue and
43   /// epilogue are traditionally inserted, ignoring possible shrink-wrapping
44   /// optimization.
45   void emitPacRetPlusLeafHardening(MachineFunction &MF) const;
46 
47   bool enableCFIFixup(const MachineFunction &MF) const override;
48 
49   bool enableFullCFIFixup(const MachineFunction &MF) const override;
50 
51   bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
52 
53   StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
54                                      Register &FrameReg) const override;
55   StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF,
56                                            int FI) const override;
57   StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI,
58                                          Register &FrameReg, bool PreferFP,
59                                          bool ForSimm) const;
60   StackOffset resolveFrameOffsetReference(const MachineFunction &MF,
61                                           int64_t ObjectOffset, bool isFixed,
62                                           bool isSVE, Register &FrameReg,
63                                           bool PreferFP, bool ForSimm) const;
64   bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
65                                  MachineBasicBlock::iterator MI,
66                                  ArrayRef<CalleeSavedInfo> CSI,
67                                  const TargetRegisterInfo *TRI) const override;
68 
69   bool
70   restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
71                               MachineBasicBlock::iterator MI,
72                               MutableArrayRef<CalleeSavedInfo> CSI,
73                               const TargetRegisterInfo *TRI) const override;
74 
75   /// Can this function use the red zone for local allocations.
76   bool canUseRedZone(const MachineFunction &MF) const;
77 
78   bool hasReservedCallFrame(const MachineFunction &MF) const override;
79 
80   bool assignCalleeSavedSpillSlots(MachineFunction &MF,
81                                    const TargetRegisterInfo *TRI,
82                                    std::vector<CalleeSavedInfo> &CSI,
83                                    unsigned &MinCSFrameIndex,
84                                    unsigned &MaxCSFrameIndex) const override;
85 
86   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
87                             RegScavenger *RS) const override;
88 
89   /// Returns true if the target will correctly handle shrink wrapping.
enableShrinkWrapping(const MachineFunction & MF)90   bool enableShrinkWrapping(const MachineFunction &MF) const override {
91     return true;
92   }
93 
94   bool enableStackSlotScavenging(const MachineFunction &MF) const override;
95   TargetStackID::Value getStackIDForScalableVectors() const override;
96 
97   void processFunctionBeforeFrameFinalized(MachineFunction &MF,
98                                            RegScavenger *RS) const override;
99 
100   void
101   processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,
102                                             RegScavenger *RS) const override;
103 
104   unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
105 
106   unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
107 
108   StackOffset
109   getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
110                                  Register &FrameReg,
111                                  bool IgnoreSPUpdates) const override;
112   StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF,
113                                              int FI) const override;
114   int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const;
115 
isSupportedStackID(TargetStackID::Value ID)116   bool isSupportedStackID(TargetStackID::Value ID) const override {
117     switch (ID) {
118     default:
119       return false;
120     case TargetStackID::Default:
121     case TargetStackID::ScalableVector:
122     case TargetStackID::NoAlloc:
123       return true;
124     }
125   }
126 
isStackIdSafeForLocalArea(unsigned StackId)127   bool isStackIdSafeForLocalArea(unsigned StackId) const override {
128     // We don't support putting SVE objects into the pre-allocated local
129     // frame block at the moment.
130     return StackId != TargetStackID::ScalableVector;
131   }
132 
133   void
134   orderFrameObjects(const MachineFunction &MF,
135                     SmallVectorImpl<int> &ObjectsToAllocate) const override;
136 
137   bool isFPReserved(const MachineFunction &MF) const;
138 
139 protected:
140   bool hasFPImpl(const MachineFunction &MF) const override;
141 
142 private:
143   /// Returns true if a homogeneous prolog or epilog code can be emitted
144   /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo
145   /// instructions are emitted in place. When Exit block is given, this check is
146   /// for epilog.
147   bool homogeneousPrologEpilog(MachineFunction &MF,
148                                MachineBasicBlock *Exit = nullptr) const;
149 
150   /// Returns true if CSRs should be paired.
151   bool producePairRegisters(MachineFunction &MF) const;
152 
153   bool shouldCombineCSRLocalStackBump(MachineFunction &MF,
154                                       uint64_t StackBumpBytes) const;
155 
156   int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const;
157   int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF,
158                                       int &MinCSFrameIndex,
159                                       int &MaxCSFrameIndex) const;
160   bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB,
161                                                 uint64_t StackBumpBytes) const;
162   void emitCalleeSavedGPRLocations(MachineBasicBlock &MBB,
163                                    MachineBasicBlock::iterator MBBI) const;
164   void emitCalleeSavedSVELocations(MachineBasicBlock &MBB,
165                                    MachineBasicBlock::iterator MBBI) const;
166   void emitCalleeSavedGPRRestores(MachineBasicBlock &MBB,
167                                   MachineBasicBlock::iterator MBBI) const;
168   void emitCalleeSavedSVERestores(MachineBasicBlock &MBB,
169                                   MachineBasicBlock::iterator MBBI) const;
170   void allocateStackSpace(MachineBasicBlock &MBB,
171                           MachineBasicBlock::iterator MBBI,
172                           int64_t RealignmentPadding, StackOffset AllocSize,
173                           bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI,
174                           StackOffset InitialOffset, bool FollowupAllocs) const;
175   /// Make a determination whether a Hazard slot is used and create it if
176   /// needed.
177   void determineStackHazardSlot(MachineFunction &MF,
178                                 BitVector &SavedRegs) const;
179 
180   /// Emit target zero call-used regs.
181   void emitZeroCallUsedRegs(BitVector RegsToZero,
182                             MachineBasicBlock &MBB) const override;
183 
184   /// Replace a StackProbe stub (if any) with the actual probe code inline
185   void inlineStackProbe(MachineFunction &MF,
186                         MachineBasicBlock &PrologueMBB) const override;
187 
188   void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI,
189                              Register ScratchReg, int64_t FrameSize,
190                              StackOffset CFAOffset) const;
191 
192   MachineBasicBlock::iterator
193   inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI,
194                                     int64_t NegProbeSize,
195                                     Register TargetReg) const;
196 
197   void emitRemarks(const MachineFunction &MF,
198                    MachineOptimizationRemarkEmitter *ORE) const override;
199 };
200 
201 } // End llvm namespace
202 
203 #endif
204