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 "X86ReturnProtectorLowering.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/TargetFrameLowering.h"
19#include "llvm/Support/TypeSize.h"
20
21namespace llvm {
22
23class MachineInstrBuilder;
24class MCCFIInstruction;
25class X86InstrInfo;
26class X86Subtarget;
27class X86RegisterInfo;
28class X86ReturnProtectorLowering;
29
30class X86FrameLowering : public TargetFrameLowering {
31public:
32  X86FrameLowering(const X86Subtarget &STI, MaybeAlign StackAlignOverride);
33
34  // Cached subtarget predicates.
35
36  const X86Subtarget &STI;
37  const X86InstrInfo &TII;
38  const X86RegisterInfo *TRI;
39  const X86ReturnProtectorLowering RPL;
40
41  bool SaveArgs;
42
43  unsigned SlotSize;
44
45  /// Is64Bit implies that x86_64 instructions are available.
46  bool Is64Bit;
47
48  bool IsLP64;
49
50  /// True if the 64-bit frame or stack pointer should be used. True for most
51  /// 64-bit targets with the exception of x32. If this is false, 32-bit
52  /// instruction operands should be used to manipulate StackPtr and FramePtr.
53  bool Uses64BitFramePtr;
54
55  unsigned StackPtr;
56
57  /// Emit target stack probe code. This is required for all
58  /// large stack allocations on Windows. The caller is required to materialize
59  /// the number of bytes to probe in RAX/EAX.
60  /// \p InstrNum optionally contains a debug-info instruction number for the
61  ///    new stack pointer.
62  void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB,
63                      MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
64                      bool InProlog,
65                      std::optional<MachineFunction::DebugInstrOperandPair>
66                          InstrNum = std::nullopt) const;
67
68  bool stackProbeFunctionModifiesSP() const override;
69
70  /// Replace a StackProbe inline-stub with the actual probe code inline.
71  void inlineStackProbe(MachineFunction &MF,
72                        MachineBasicBlock &PrologMBB) const override;
73
74  void emitCalleeSavedFrameMovesFullCFA(
75      MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override;
76
77  void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB,
78                                 MachineBasicBlock::iterator MBBI,
79                                 const DebugLoc &DL, bool IsPrologue) const;
80
81  /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
82  /// the function.
83  void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
84  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
85
86  const ReturnProtectorLowering *getReturnProtector() const override;
87
88  void adjustForSegmentedStacks(MachineFunction &MF,
89                                MachineBasicBlock &PrologueMBB) const override;
90
91  void adjustForHiPEPrologue(MachineFunction &MF,
92                             MachineBasicBlock &PrologueMBB) const override;
93
94  void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
95                            RegScavenger *RS = nullptr) const override;
96
97  bool
98  assignCalleeSavedSpillSlots(MachineFunction &MF,
99                              const TargetRegisterInfo *TRI,
100                              std::vector<CalleeSavedInfo> &CSI) const override;
101
102  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
103                                 MachineBasicBlock::iterator MI,
104                                 ArrayRef<CalleeSavedInfo> CSI,
105                                 const TargetRegisterInfo *TRI) const override;
106
107  bool
108  restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
109                              MachineBasicBlock::iterator MI,
110                              MutableArrayRef<CalleeSavedInfo> CSI,
111                              const TargetRegisterInfo *TRI) const override;
112
113  bool hasFP(const MachineFunction &MF) const override;
114  bool hasReservedCallFrame(const MachineFunction &MF) const override;
115  bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
116  bool needsFrameIndexResolution(const MachineFunction &MF) const override;
117
118  StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
119                                     Register &FrameReg) const override;
120
121  int getWin64EHFrameIndexRef(const MachineFunction &MF, int FI,
122                              Register &SPReg) const;
123  StackOffset getFrameIndexReferenceSP(const MachineFunction &MF, int FI,
124                                       Register &SPReg, int Adjustment) const;
125  StackOffset
126  getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
127                                 Register &FrameReg,
128                                 bool IgnoreSPUpdates) const override;
129
130  MachineBasicBlock::iterator
131  eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
132                                MachineBasicBlock::iterator MI) const override;
133
134  unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
135
136  void processFunctionBeforeFrameFinalized(MachineFunction &MF,
137                                           RegScavenger *RS) const override;
138
139  void
140  processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,
141                                            RegScavenger *RS) const override;
142
143  /// Check the instruction before/after the passed instruction. If
144  /// it is an ADD/SUB/LEA instruction it is deleted argument and the
145  /// stack adjustment is returned as a positive value for ADD/LEA and
146  /// a negative for SUB.
147  int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
148                     bool doMergeWithPrevious) const;
149
150  /// Emit a series of instructions to increment / decrement the stack
151  /// pointer by a constant value.
152  void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
153                    const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const;
154
155  /// Check that LEA can be used on SP in an epilogue sequence for \p MF.
156  bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const;
157
158  /// Check whether or not the given \p MBB can be used as a prologue
159  /// for the target.
160  /// The prologue will be inserted first in this basic block.
161  /// This method is used by the shrink-wrapping pass to decide if
162  /// \p MBB will be correctly handled by the target.
163  /// As soon as the target enable shrink-wrapping without overriding
164  /// this method, we assume that each basic block is a valid
165  /// prologue.
166  bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
167
168  /// Check whether or not the given \p MBB can be used as a epilogue
169  /// for the target.
170  /// The epilogue will be inserted before the first terminator of that block.
171  /// This method is used by the shrink-wrapping pass to decide if
172  /// \p MBB will be correctly handled by the target.
173  bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
174
175  /// Returns true if the target will correctly handle shrink wrapping.
176  bool enableShrinkWrapping(const MachineFunction &MF) const override;
177
178  /// Order the symbols in the local stack.
179  /// We want to place the local stack objects in some sort of sensible order.
180  /// The heuristic we use is to try and pack them according to static number
181  /// of uses and size in order to minimize code size.
182  void orderFrameObjects(const MachineFunction &MF,
183                         SmallVectorImpl<int> &ObjectsToAllocate) const override;
184
185  /// Wraps up getting a CFI index and building a MachineInstr for it.
186  void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
187                const DebugLoc &DL, const MCCFIInstruction &CFIInst,
188                MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
189
190  /// Sets up EBP and optionally ESI based on the incoming EBP value.  Only
191  /// needed for 32-bit. Used in funclet prologues and at catchret destinations.
192  MachineBasicBlock::iterator
193  restoreWin32EHStackPointers(MachineBasicBlock &MBB,
194                              MachineBasicBlock::iterator MBBI,
195                              const DebugLoc &DL, bool RestoreSP = false) const;
196
197  void restoreWinEHStackPointersInParent(MachineFunction &MF) const;
198
199  int getInitialCFAOffset(const MachineFunction &MF) const override;
200
201  Register getInitialCFARegister(const MachineFunction &MF) const override;
202
203  /// Return true if the function has a redzone (accessible bytes past the
204  /// frame of the top of stack function) as part of it's ABI.
205  bool has128ByteRedZone(const MachineFunction& MF) const;
206
207private:
208  bool isWin64Prologue(const MachineFunction &MF) const;
209
210  bool needsDwarfCFI(const MachineFunction &MF) const;
211
212  uint64_t calculateMaxStackAlign(const MachineFunction &MF) const;
213
214  /// Emit target stack probe as a call to a helper function
215  void emitStackProbeCall(
216      MachineFunction &MF, MachineBasicBlock &MBB,
217      MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog,
218      std::optional<MachineFunction::DebugInstrOperandPair> InstrNum) const;
219
220  /// Emit target stack probe as an inline sequence.
221  void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB,
222                            MachineBasicBlock::iterator MBBI,
223                            const DebugLoc &DL, bool InProlog) const;
224  void emitStackProbeInlineWindowsCoreCLR64(MachineFunction &MF,
225                                            MachineBasicBlock &MBB,
226                                            MachineBasicBlock::iterator MBBI,
227                                            const DebugLoc &DL,
228                                            bool InProlog) const;
229  void emitStackProbeInlineGeneric(MachineFunction &MF, MachineBasicBlock &MBB,
230                                   MachineBasicBlock::iterator MBBI,
231                                   const DebugLoc &DL, bool InProlog) const;
232
233  void emitStackProbeInlineGenericBlock(MachineFunction &MF,
234                                        MachineBasicBlock &MBB,
235                                        MachineBasicBlock::iterator MBBI,
236                                        const DebugLoc &DL, uint64_t Offset,
237                                        uint64_t Align) const;
238
239  void emitStackProbeInlineGenericLoop(MachineFunction &MF,
240                                       MachineBasicBlock &MBB,
241                                       MachineBasicBlock::iterator MBBI,
242                                       const DebugLoc &DL, uint64_t Offset,
243                                       uint64_t Align) const;
244
245  /// Emit target zero call-used regs.
246  void emitZeroCallUsedRegs(BitVector RegsToZero,
247                            MachineBasicBlock &MBB) const override;
248
249  void adjustFrameForMsvcCxxEh(MachineFunction &MF) const;
250
251  /// Aligns the stack pointer by ANDing it with -MaxAlign.
252  void BuildStackAlignAND(MachineBasicBlock &MBB,
253                          MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
254                          unsigned Reg, uint64_t MaxAlign) const;
255
256  /// Make small positive stack adjustments using POPs.
257  bool adjustStackWithPops(MachineBasicBlock &MBB,
258                           MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
259                           int Offset) const;
260
261  /// Adjusts the stack pointer using LEA, SUB, or ADD.
262  MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB,
263                                           MachineBasicBlock::iterator MBBI,
264                                           const DebugLoc &DL, int64_t Offset,
265                                           bool InEpilogue) const;
266
267  unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const;
268
269  unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
270
271  /// Materialize the catchret target MBB in RAX.
272  void emitCatchRetReturnValue(MachineBasicBlock &MBB,
273                               MachineBasicBlock::iterator MBBI,
274                               MachineInstr *CatchRet) const;
275};
276
277} // End llvm namespace
278
279#endif
280