345 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This class implements X86-specific bits of TargetFrameLowering class.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H14#define LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H15 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 most46 /// 64-bit targets with the exception of x32. If this is false, 32-bit47 /// 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 all53 /// large stack allocations on Windows. The caller is required to materialize54 /// the number of bytes to probe in RAX/EAX.55 /// \p InstrNum optionally contains a debug-info instruction number for the56 /// 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 into77 /// 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 bool91 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 bool101 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 StackOffset120 getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,121 Register &FrameReg,122 bool IgnoreSPUpdates) const override;123 124 MachineBasicBlock::iterator125 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 void134 processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,135 RegScavenger *RS) const override;136 137private:138 /// Basic Pseudocode:139 /// if (instruction before/after the passed instruction is ADD/SUB/LEA)140 /// Offset = instruction stack adjustment141 /// ... positive value for ADD/LEA and negative for SUB142 /// FoundStackAdjust(instruction, Offset)143 /// erase(instruction)144 /// return CalcNewOffset(Offset)145 /// else146 /// return CalcNewOffset(0)147 ///148 /// It's possible that the selected instruction is not immediately149 /// before/after MBBI for large adjustments that have been split into multiple150 /// 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 172public: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 stack183 /// 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 prologue191 /// 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 if194 /// \p MBB will be correctly handled by the target.195 /// As soon as the target enable shrink-wrapping without overriding196 /// this method, we assume that each basic block is a valid197 /// prologue.198 bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;199 200 /// Check whether or not the given \p MBB can be used as a epilogue201 /// 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 if204 /// \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 number213 /// 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. Only223 /// needed for 32-bit. Used in funclet prologues and at catchret destinations.224 MachineBasicBlock::iterator225 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 the238 /// frame of the top of stack function) as part of it's ABI.239 bool has128ByteRedZone(const MachineFunction& MF) const;240 241protected:242 bool hasFPImpl(const MachineFunction &MF) const override;243 244private: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 function252 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/or314 /// 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 stack320 /// 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 spilled336 // again, this function should return true, and update MI so we will not check337 // any instructions from related sequence.338 bool skipSpillFPBP(MachineFunction &MF,339 MachineBasicBlock::reverse_iterator &MI) const;340};341 342} // End llvm namespace343 344#endif345