brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.1 KiB · f1e3796 Raw
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