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