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: |
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 | bool enableCFIFixup(const MachineFunction &MF) const override; |
40 | |
41 | bool enableFullCFIFixup(const MachineFunction &MF) const override; |
42 | |
43 | bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; |
44 | |
45 | StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, |
46 | Register &FrameReg) const override; |
47 | StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF, |
48 | int FI) const override; |
49 | StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI, |
50 | Register &FrameReg, bool PreferFP, |
51 | bool ForSimm) const; |
52 | StackOffset resolveFrameOffsetReference(const MachineFunction &MF, |
53 | int64_t ObjectOffset, bool isFixed, |
54 | bool isSVE, Register &FrameReg, |
55 | bool PreferFP, bool ForSimm) const; |
56 | bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
57 | MachineBasicBlock::iterator MI, |
58 | ArrayRef<CalleeSavedInfo> CSI, |
59 | const TargetRegisterInfo *TRI) const override; |
60 | |
61 | bool |
62 | restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
63 | MachineBasicBlock::iterator MI, |
64 | MutableArrayRef<CalleeSavedInfo> CSI, |
65 | const TargetRegisterInfo *TRI) const override; |
66 | |
67 | /// Can this function use the red zone for local allocations. |
68 | bool canUseRedZone(const MachineFunction &MF) const; |
69 | |
70 | bool hasReservedCallFrame(const MachineFunction &MF) const override; |
71 | |
72 | bool assignCalleeSavedSpillSlots(MachineFunction &MF, |
73 | const TargetRegisterInfo *TRI, |
74 | std::vector<CalleeSavedInfo> &CSI, |
75 | unsigned &MinCSFrameIndex, |
76 | unsigned &MaxCSFrameIndex) const override; |
77 | |
78 | void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, |
79 | RegScavenger *RS) const override; |
80 | |
81 | /// Returns true if the target will correctly handle shrink wrapping. |
82 | bool enableShrinkWrapping(const MachineFunction &MF) const override { |
83 | return true; |
84 | } |
85 | |
86 | bool enableStackSlotScavenging(const MachineFunction &MF) const override; |
87 | TargetStackID::Value getStackIDForScalableVectors() const override; |
88 | |
89 | void processFunctionBeforeFrameFinalized(MachineFunction &MF, |
90 | RegScavenger *RS) const override; |
91 | |
92 | void |
93 | processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, |
94 | RegScavenger *RS) const override; |
95 | |
96 | unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; |
97 | |
98 | unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const; |
99 | |
100 | StackOffset |
101 | getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, |
102 | Register &FrameReg, |
103 | bool IgnoreSPUpdates) const override; |
104 | StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, |
105 | int FI) const override; |
106 | int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const; |
107 | |
108 | bool isSupportedStackID(TargetStackID::Value ID) const override { |
109 | switch (ID) { |
110 | default: |
111 | return false; |
112 | case TargetStackID::Default: |
113 | case TargetStackID::ScalableVector: |
114 | case TargetStackID::NoAlloc: |
115 | return true; |
116 | } |
117 | } |
118 | |
119 | bool isStackIdSafeForLocalArea(unsigned StackId) const override { |
120 | // We don't support putting SVE objects into the pre-allocated local |
121 | // frame block at the moment. |
122 | return StackId != TargetStackID::ScalableVector; |
123 | } |
124 | |
125 | void |
126 | orderFrameObjects(const MachineFunction &MF, |
127 | SmallVectorImpl<int> &ObjectsToAllocate) const override; |
128 | |
129 | protected: |
130 | bool hasFPImpl(const MachineFunction &MF) const override; |
131 | |
132 | private: |
133 | /// Returns true if a homogeneous prolog or epilog code can be emitted |
134 | /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo |
135 | /// instructions are emitted in place. When Exit block is given, this check is |
136 | /// for epilog. |
137 | bool homogeneousPrologEpilog(MachineFunction &MF, |
138 | MachineBasicBlock *Exit = nullptr) const; |
139 | |
140 | /// Returns true if CSRs should be paired. |
141 | bool producePairRegisters(MachineFunction &MF) const; |
142 | |
143 | bool shouldCombineCSRLocalStackBump(MachineFunction &MF, |
144 | uint64_t StackBumpBytes) const; |
145 | |
146 | int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const; |
147 | int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF, |
148 | int &MinCSFrameIndex, |
149 | int &MaxCSFrameIndex) const; |
150 | bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB, |
151 | uint64_t StackBumpBytes) const; |
152 | void emitCalleeSavedGPRLocations(MachineBasicBlock &MBB, |
153 | MachineBasicBlock::iterator MBBI) const; |
154 | void emitCalleeSavedSVELocations(MachineBasicBlock &MBB, |
155 | MachineBasicBlock::iterator MBBI) const; |
156 | void emitCalleeSavedGPRRestores(MachineBasicBlock &MBB, |
157 | MachineBasicBlock::iterator MBBI) const; |
158 | void emitCalleeSavedSVERestores(MachineBasicBlock &MBB, |
159 | MachineBasicBlock::iterator MBBI) const; |
160 | void allocateStackSpace(MachineBasicBlock &MBB, |
161 | MachineBasicBlock::iterator MBBI, |
162 | int64_t RealignmentPadding, StackOffset AllocSize, |
163 | bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI, |
164 | StackOffset InitialOffset, bool FollowupAllocs) const; |
165 | /// Make a determination whether a Hazard slot is used and create it if |
166 | /// needed. |
167 | void determineStackHazardSlot(MachineFunction &MF, |
168 | BitVector &SavedRegs) const; |
169 | |
170 | /// Emit target zero call-used regs. |
171 | void emitZeroCallUsedRegs(BitVector RegsToZero, |
172 | MachineBasicBlock &MBB) const override; |
173 | |
174 | /// Replace a StackProbe stub (if any) with the actual probe code inline |
175 | void inlineStackProbe(MachineFunction &MF, |
176 | MachineBasicBlock &PrologueMBB) const override; |
177 | |
178 | void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI, |
179 | Register ScratchReg, int64_t FrameSize, |
180 | StackOffset CFAOffset) const; |
181 | |
182 | MachineBasicBlock::iterator |
183 | inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI, |
184 | int64_t NegProbeSize, |
185 | Register TargetReg) const; |
186 | |
187 | void (const MachineFunction &MF, |
188 | MachineOptimizationRemarkEmitter *ORE) const override; |
189 | }; |
190 | |
191 | } // End llvm namespace |
192 | |
193 | #endif |
194 | |