1 | //===-- X86TargetFrameLowering.h - Define frame lowering for X86 -*- 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 | // This class implements X86-specific bits of TargetFrameLowering class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H |
14 | #define LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H |
15 | |
16 | #include "llvm/CodeGen/MachineFunction.h" |
17 | #include "llvm/CodeGen/TargetFrameLowering.h" |
18 | #include "llvm/Support/TypeSize.h" |
19 | |
20 | namespace llvm { |
21 | |
22 | class MachineInstrBuilder; |
23 | class MCCFIInstruction; |
24 | class X86InstrInfo; |
25 | class X86Subtarget; |
26 | class X86RegisterInfo; |
27 | |
28 | class X86FrameLowering : public TargetFrameLowering { |
29 | public: |
30 | X86FrameLowering(const X86Subtarget &STI, MaybeAlign StackAlignOverride); |
31 | |
32 | // Cached subtarget predicates. |
33 | |
34 | const X86Subtarget &STI; |
35 | const X86InstrInfo &TII; |
36 | const X86RegisterInfo *TRI; |
37 | |
38 | unsigned SlotSize; |
39 | |
40 | /// Is64Bit implies that x86_64 instructions are available. |
41 | bool Is64Bit; |
42 | |
43 | bool IsLP64; |
44 | |
45 | /// True if the 64-bit frame or stack pointer should be used. True for most |
46 | /// 64-bit targets with the exception of x32. If this is false, 32-bit |
47 | /// instruction operands should be used to manipulate StackPtr and FramePtr. |
48 | bool Uses64BitFramePtr; |
49 | |
50 | Register StackPtr; |
51 | |
52 | /// Emit target stack probe code. This is required for all |
53 | /// large stack allocations on Windows. The caller is required to materialize |
54 | /// the number of bytes to probe in RAX/EAX. |
55 | /// \p InstrNum optionally contains a debug-info instruction number for the |
56 | /// new stack pointer. |
57 | void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, |
58 | MachineBasicBlock::iterator MBBI, const DebugLoc &DL, |
59 | bool InProlog, |
60 | std::optional<MachineFunction::DebugInstrOperandPair> |
61 | InstrNum = std::nullopt) const; |
62 | |
63 | bool stackProbeFunctionModifiesSP() const override; |
64 | |
65 | /// Replace a StackProbe inline-stub with the actual probe code inline. |
66 | void inlineStackProbe(MachineFunction &MF, |
67 | MachineBasicBlock &PrologMBB) const override; |
68 | |
69 | void emitCalleeSavedFrameMovesFullCFA( |
70 | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override; |
71 | |
72 | void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, |
73 | MachineBasicBlock::iterator MBBI, |
74 | const DebugLoc &DL, bool IsPrologue) const; |
75 | |
76 | /// emitProlog/emitEpilog - These methods insert prolog and epilog code into |
77 | /// the function. |
78 | void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; |
79 | void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; |
80 | |
81 | void adjustForSegmentedStacks(MachineFunction &MF, |
82 | MachineBasicBlock &PrologueMBB) const override; |
83 | |
84 | void adjustForHiPEPrologue(MachineFunction &MF, |
85 | MachineBasicBlock &PrologueMBB) const override; |
86 | |
87 | void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, |
88 | RegScavenger *RS = nullptr) const override; |
89 | |
90 | bool |
91 | assignCalleeSavedSpillSlots(MachineFunction &MF, |
92 | const TargetRegisterInfo *TRI, |
93 | std::vector<CalleeSavedInfo> &CSI) const override; |
94 | |
95 | bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
96 | MachineBasicBlock::iterator MI, |
97 | ArrayRef<CalleeSavedInfo> CSI, |
98 | const TargetRegisterInfo *TRI) const override; |
99 | |
100 | bool |
101 | restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
102 | MachineBasicBlock::iterator MI, |
103 | MutableArrayRef<CalleeSavedInfo> CSI, |
104 | const TargetRegisterInfo *TRI) const override; |
105 | |
106 | void spillFPBP(MachineFunction &MF) const override; |
107 | |
108 | bool hasReservedCallFrame(const MachineFunction &MF) const override; |
109 | bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; |
110 | bool needsFrameIndexResolution(const MachineFunction &MF) const override; |
111 | |
112 | StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, |
113 | Register &FrameReg) const override; |
114 | |
115 | int getWin64EHFrameIndexRef(const MachineFunction &MF, int FI, |
116 | Register &SPReg) const; |
117 | StackOffset getFrameIndexReferenceSP(const MachineFunction &MF, int FI, |
118 | Register &SPReg, int Adjustment) const; |
119 | StackOffset |
120 | getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, |
121 | Register &FrameReg, |
122 | bool IgnoreSPUpdates) const override; |
123 | |
124 | MachineBasicBlock::iterator |
125 | eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, |
126 | MachineBasicBlock::iterator MI) const override; |
127 | |
128 | unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; |
129 | |
130 | void processFunctionBeforeFrameFinalized(MachineFunction &MF, |
131 | RegScavenger *RS) const override; |
132 | |
133 | void |
134 | processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, |
135 | RegScavenger *RS) const override; |
136 | |
137 | private: |
138 | /// Basic Pseudocode: |
139 | /// if (instruction before/after the passed instruction is ADD/SUB/LEA) |
140 | /// Offset = instruction stack adjustment |
141 | /// ... positive value for ADD/LEA and negative for SUB |
142 | /// FoundStackAdjust(instruction, Offset) |
143 | /// erase(instruction) |
144 | /// return CalcNewOffset(Offset) |
145 | /// else |
146 | /// return CalcNewOffset(0) |
147 | /// |
148 | /// It's possible that the selected instruction is not immediately |
149 | /// before/after MBBI for large adjustments that have been split into multiple |
150 | /// instructions. |
151 | /// |
152 | /// FoundStackAdjust should have the signature: |
153 | /// void FoundStackAdjust(MachineBasicBlock::iterator PI, int64_t Offset) |
154 | /// CalcNewOffset should have the signature: |
155 | /// int64_t CalcNewOffset(int64_t Offset) |
156 | template <typename FoundT, typename CalcT> |
157 | int64_t mergeSPUpdates(MachineBasicBlock &MBB, |
158 | MachineBasicBlock::iterator &MBBI, |
159 | FoundT FoundStackAdjust, CalcT CalcNewOffset, |
160 | bool doMergeWithPrevious) const; |
161 | |
162 | template <typename CalcT> |
163 | int64_t mergeSPUpdates(MachineBasicBlock &MBB, |
164 | MachineBasicBlock::iterator &MBBI, CalcT CalcNewOffset, |
165 | bool doMergeWithPrevious) const { |
166 | auto FoundStackAdjust = [](MachineBasicBlock::iterator MBBI, |
167 | int64_t Offset) {}; |
168 | return mergeSPUpdates(MBB, MBBI, FoundStackAdjust, CalcNewOffset, |
169 | doMergeWithPrevious); |
170 | } |
171 | |
172 | public: |
173 | /// Equivalent to: |
174 | /// mergeSPUpdates(MBB, MBBI, |
175 | /// [AddOffset](int64_t Offset) { |
176 | /// return AddOffset + Offset; |
177 | /// }, |
178 | /// doMergeWithPrevious); |
179 | int64_t mergeSPAdd(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
180 | int64_t AddOffset, bool doMergeWithPrevious) const; |
181 | |
182 | /// Emit a series of instructions to increment / decrement the stack |
183 | /// pointer by a constant value. |
184 | void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
185 | const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const; |
186 | |
187 | /// Check that LEA can be used on SP in an epilogue sequence for \p MF. |
188 | bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const; |
189 | |
190 | /// Check whether or not the given \p MBB can be used as a prologue |
191 | /// for the target. |
192 | /// The prologue will be inserted first in this basic block. |
193 | /// This method is used by the shrink-wrapping pass to decide if |
194 | /// \p MBB will be correctly handled by the target. |
195 | /// As soon as the target enable shrink-wrapping without overriding |
196 | /// this method, we assume that each basic block is a valid |
197 | /// prologue. |
198 | bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; |
199 | |
200 | /// Check whether or not the given \p MBB can be used as a epilogue |
201 | /// for the target. |
202 | /// The epilogue will be inserted before the first terminator of that block. |
203 | /// This method is used by the shrink-wrapping pass to decide if |
204 | /// \p MBB will be correctly handled by the target. |
205 | bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override; |
206 | |
207 | /// Returns true if the target will correctly handle shrink wrapping. |
208 | bool enableShrinkWrapping(const MachineFunction &MF) const override; |
209 | |
210 | /// Order the symbols in the local stack. |
211 | /// We want to place the local stack objects in some sort of sensible order. |
212 | /// The heuristic we use is to try and pack them according to static number |
213 | /// of uses and size in order to minimize code size. |
214 | void orderFrameObjects(const MachineFunction &MF, |
215 | SmallVectorImpl<int> &ObjectsToAllocate) const override; |
216 | |
217 | /// Wraps up getting a CFI index and building a MachineInstr for it. |
218 | void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
219 | const DebugLoc &DL, const MCCFIInstruction &CFIInst, |
220 | MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; |
221 | |
222 | /// Sets up EBP and optionally ESI based on the incoming EBP value. Only |
223 | /// needed for 32-bit. Used in funclet prologues and at catchret destinations. |
224 | MachineBasicBlock::iterator |
225 | restoreWin32EHStackPointers(MachineBasicBlock &MBB, |
226 | MachineBasicBlock::iterator MBBI, |
227 | const DebugLoc &DL, bool RestoreSP = false) const; |
228 | |
229 | void restoreWinEHStackPointersInParent(MachineFunction &MF) const; |
230 | |
231 | int getInitialCFAOffset(const MachineFunction &MF) const override; |
232 | |
233 | Register getInitialCFARegister(const MachineFunction &MF) const override; |
234 | |
235 | DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override; |
236 | |
237 | /// Return true if the function has a redzone (accessible bytes past the |
238 | /// frame of the top of stack function) as part of it's ABI. |
239 | bool has128ByteRedZone(const MachineFunction& MF) const; |
240 | |
241 | protected: |
242 | bool hasFPImpl(const MachineFunction &MF) const override; |
243 | |
244 | private: |
245 | bool isWin64Prologue(const MachineFunction &MF) const; |
246 | |
247 | bool needsDwarfCFI(const MachineFunction &MF) const; |
248 | |
249 | uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; |
250 | |
251 | /// Emit target stack probe as a call to a helper function |
252 | void emitStackProbeCall( |
253 | MachineFunction &MF, MachineBasicBlock &MBB, |
254 | MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog, |
255 | std::optional<MachineFunction::DebugInstrOperandPair> InstrNum) const; |
256 | |
257 | /// Emit target stack probe as an inline sequence. |
258 | void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, |
259 | MachineBasicBlock::iterator MBBI, |
260 | const DebugLoc &DL, bool InProlog) const; |
261 | void emitStackProbeInlineWindowsCoreCLR64(MachineFunction &MF, |
262 | MachineBasicBlock &MBB, |
263 | MachineBasicBlock::iterator MBBI, |
264 | const DebugLoc &DL, |
265 | bool InProlog) const; |
266 | void emitStackProbeInlineGeneric(MachineFunction &MF, MachineBasicBlock &MBB, |
267 | MachineBasicBlock::iterator MBBI, |
268 | const DebugLoc &DL, bool InProlog) const; |
269 | |
270 | void emitStackProbeInlineGenericBlock(MachineFunction &MF, |
271 | MachineBasicBlock &MBB, |
272 | MachineBasicBlock::iterator MBBI, |
273 | const DebugLoc &DL, uint64_t Offset, |
274 | uint64_t Align) const; |
275 | |
276 | void emitStackProbeInlineGenericLoop(MachineFunction &MF, |
277 | MachineBasicBlock &MBB, |
278 | MachineBasicBlock::iterator MBBI, |
279 | const DebugLoc &DL, uint64_t Offset, |
280 | uint64_t Align) const; |
281 | |
282 | /// Emit target zero call-used regs. |
283 | void emitZeroCallUsedRegs(BitVector RegsToZero, |
284 | MachineBasicBlock &MBB) const override; |
285 | |
286 | void adjustFrameForMsvcCxxEh(MachineFunction &MF) const; |
287 | |
288 | /// Aligns the stack pointer by ANDing it with -MaxAlign. |
289 | void BuildStackAlignAND(MachineBasicBlock &MBB, |
290 | MachineBasicBlock::iterator MBBI, const DebugLoc &DL, |
291 | Register Reg, uint64_t MaxAlign) const; |
292 | |
293 | /// Make small positive stack adjustments using POPs. |
294 | bool adjustStackWithPops(MachineBasicBlock &MBB, |
295 | MachineBasicBlock::iterator MBBI, const DebugLoc &DL, |
296 | int Offset) const; |
297 | |
298 | /// Adjusts the stack pointer using LEA, SUB, or ADD. |
299 | MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB, |
300 | MachineBasicBlock::iterator MBBI, |
301 | const DebugLoc &DL, int64_t Offset, |
302 | bool InEpilogue) const; |
303 | |
304 | unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const; |
305 | |
306 | unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const; |
307 | |
308 | /// Materialize the catchret target MBB in RAX. |
309 | void emitCatchRetReturnValue(MachineBasicBlock &MBB, |
310 | MachineBasicBlock::iterator MBBI, |
311 | MachineInstr *CatchRet) const; |
312 | |
313 | /// Issue instructions to allocate stack space and spill frame pointer and/or |
314 | /// base pointer to stack using stack pointer register. |
315 | void spillFPBPUsingSP(MachineFunction &MF, |
316 | const MachineBasicBlock::iterator BeforeMI, Register FP, |
317 | Register BP, int SPAdjust) const; |
318 | |
319 | /// Issue instructions to restore frame pointer and/or base pointer from stack |
320 | /// using stack pointer register, and free stack space. |
321 | void restoreFPBPUsingSP(MachineFunction &MF, |
322 | const MachineBasicBlock::iterator AfterMI, |
323 | Register FP, Register BP, int SPAdjust) const; |
324 | |
325 | void saveAndRestoreFPBPUsingSP(MachineFunction &MF, |
326 | MachineBasicBlock::iterator BeforeMI, |
327 | MachineBasicBlock::iterator AfterMI, |
328 | bool SpillFP, bool SpillBP) const; |
329 | |
330 | void checkInterferedAccess(MachineFunction &MF, |
331 | MachineBasicBlock::reverse_iterator DefMI, |
332 | MachineBasicBlock::reverse_iterator KillMI, |
333 | bool SpillFP, bool SpillBP) const; |
334 | |
335 | // If MI uses fp/bp, but target can handle it, and doesn't want to be spilled |
336 | // again, this function should return true, and update MI so we will not check |
337 | // any instructions from related sequence. |
338 | bool skipSpillFPBP(MachineFunction &MF, |
339 | MachineBasicBlock::reverse_iterator &MI) const; |
340 | }; |
341 | |
342 | } // End llvm namespace |
343 | |
344 | #endif |
345 | |