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> mergeSPUpdates(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI,CalcT CalcNewOffset,bool doMergeWithPrevious)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