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
20namespace llvm {
21
22class MachineInstrBuilder;
23class MCCFIInstruction;
24class X86InstrInfo;
25class X86Subtarget;
26class X86RegisterInfo;
27
28class X86FrameLowering : public TargetFrameLowering {
29public:
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  unsigned 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  bool hasFP(const MachineFunction &MF) const override;
107  bool hasReservedCallFrame(const MachineFunction &MF) const override;
108  bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
109  bool needsFrameIndexResolution(const MachineFunction &MF) const override;
110
111  StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
112                                     Register &FrameReg) const override;
113
114  int getWin64EHFrameIndexRef(const MachineFunction &MF, int FI,
115                              Register &SPReg) const;
116  StackOffset getFrameIndexReferenceSP(const MachineFunction &MF, int FI,
117                                       Register &SPReg, int Adjustment) const;
118  StackOffset
119  getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
120                                 Register &FrameReg,
121                                 bool IgnoreSPUpdates) const override;
122
123  MachineBasicBlock::iterator
124  eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
125                                MachineBasicBlock::iterator MI) const override;
126
127  unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
128
129  void processFunctionBeforeFrameFinalized(MachineFunction &MF,
130                                           RegScavenger *RS) const override;
131
132  void
133  processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,
134                                            RegScavenger *RS) const override;
135
136  /// Check the instruction before/after the passed instruction. If
137  /// it is an ADD/SUB/LEA instruction it is deleted argument and the
138  /// stack adjustment is returned as a positive value for ADD/LEA and
139  /// a negative for SUB.
140  int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
141                     bool doMergeWithPrevious) const;
142
143  /// Emit a series of instructions to increment / decrement the stack
144  /// pointer by a constant value.
145  void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
146                    const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const;
147
148  /// Check that LEA can be used on SP in an epilogue sequence for \p MF.
149  bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const;
150
151  /// Check whether or not the given \p MBB can be used as a prologue
152  /// for the target.
153  /// The prologue will be inserted first in this basic block.
154  /// This method is used by the shrink-wrapping pass to decide if
155  /// \p MBB will be correctly handled by the target.
156  /// As soon as the target enable shrink-wrapping without overriding
157  /// this method, we assume that each basic block is a valid
158  /// prologue.
159  bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
160
161  /// Check whether or not the given \p MBB can be used as a epilogue
162  /// for the target.
163  /// The epilogue will be inserted before the first terminator of that block.
164  /// This method is used by the shrink-wrapping pass to decide if
165  /// \p MBB will be correctly handled by the target.
166  bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
167
168  /// Returns true if the target will correctly handle shrink wrapping.
169  bool enableShrinkWrapping(const MachineFunction &MF) const override;
170
171  /// Order the symbols in the local stack.
172  /// We want to place the local stack objects in some sort of sensible order.
173  /// The heuristic we use is to try and pack them according to static number
174  /// of uses and size in order to minimize code size.
175  void orderFrameObjects(const MachineFunction &MF,
176                         SmallVectorImpl<int> &ObjectsToAllocate) const override;
177
178  /// Wraps up getting a CFI index and building a MachineInstr for it.
179  void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
180                const DebugLoc &DL, const MCCFIInstruction &CFIInst,
181                MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
182
183  /// Sets up EBP and optionally ESI based on the incoming EBP value.  Only
184  /// needed for 32-bit. Used in funclet prologues and at catchret destinations.
185  MachineBasicBlock::iterator
186  restoreWin32EHStackPointers(MachineBasicBlock &MBB,
187                              MachineBasicBlock::iterator MBBI,
188                              const DebugLoc &DL, bool RestoreSP = false) const;
189
190  void restoreWinEHStackPointersInParent(MachineFunction &MF) const;
191
192  int getInitialCFAOffset(const MachineFunction &MF) const override;
193
194  Register getInitialCFARegister(const MachineFunction &MF) const override;
195
196  DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override;
197
198  /// Return true if the function has a redzone (accessible bytes past the
199  /// frame of the top of stack function) as part of it's ABI.
200  bool has128ByteRedZone(const MachineFunction& MF) const;
201
202private:
203  bool isWin64Prologue(const MachineFunction &MF) const;
204
205  bool needsDwarfCFI(const MachineFunction &MF) const;
206
207  uint64_t calculateMaxStackAlign(const MachineFunction &MF) const;
208
209  /// Emit target stack probe as a call to a helper function
210  void emitStackProbeCall(
211      MachineFunction &MF, MachineBasicBlock &MBB,
212      MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog,
213      std::optional<MachineFunction::DebugInstrOperandPair> InstrNum) const;
214
215  /// Emit target stack probe as an inline sequence.
216  void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB,
217                            MachineBasicBlock::iterator MBBI,
218                            const DebugLoc &DL, bool InProlog) const;
219  void emitStackProbeInlineWindowsCoreCLR64(MachineFunction &MF,
220                                            MachineBasicBlock &MBB,
221                                            MachineBasicBlock::iterator MBBI,
222                                            const DebugLoc &DL,
223                                            bool InProlog) const;
224  void emitStackProbeInlineGeneric(MachineFunction &MF, MachineBasicBlock &MBB,
225                                   MachineBasicBlock::iterator MBBI,
226                                   const DebugLoc &DL, bool InProlog) const;
227
228  void emitStackProbeInlineGenericBlock(MachineFunction &MF,
229                                        MachineBasicBlock &MBB,
230                                        MachineBasicBlock::iterator MBBI,
231                                        const DebugLoc &DL, uint64_t Offset,
232                                        uint64_t Align) const;
233
234  void emitStackProbeInlineGenericLoop(MachineFunction &MF,
235                                       MachineBasicBlock &MBB,
236                                       MachineBasicBlock::iterator MBBI,
237                                       const DebugLoc &DL, uint64_t Offset,
238                                       uint64_t Align) const;
239
240  /// Emit target zero call-used regs.
241  void emitZeroCallUsedRegs(BitVector RegsToZero,
242                            MachineBasicBlock &MBB) const override;
243
244  void adjustFrameForMsvcCxxEh(MachineFunction &MF) const;
245
246  /// Aligns the stack pointer by ANDing it with -MaxAlign.
247  void BuildStackAlignAND(MachineBasicBlock &MBB,
248                          MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
249                          unsigned Reg, uint64_t MaxAlign) const;
250
251  /// Make small positive stack adjustments using POPs.
252  bool adjustStackWithPops(MachineBasicBlock &MBB,
253                           MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
254                           int Offset) const;
255
256  /// Adjusts the stack pointer using LEA, SUB, or ADD.
257  MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB,
258                                           MachineBasicBlock::iterator MBBI,
259                                           const DebugLoc &DL, int64_t Offset,
260                                           bool InEpilogue) const;
261
262  unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const;
263
264  unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
265
266  /// Materialize the catchret target MBB in RAX.
267  void emitCatchRetReturnValue(MachineBasicBlock &MBB,
268                               MachineBasicBlock::iterator MBBI,
269                               MachineInstr *CatchRet) const;
270};
271
272} // End llvm namespace
273
274#endif
275