| 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 | |