1*0b57cec5SDimitry Andric //===-- X86TargetFrameLowering.h - Define frame lowering for X86 -*- C++ -*-==// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This class implements X86-specific bits of TargetFrameLowering class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H 14*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric namespace llvm { 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric class MachineInstrBuilder; 21*0b57cec5SDimitry Andric class MCCFIInstruction; 22*0b57cec5SDimitry Andric class X86InstrInfo; 23*0b57cec5SDimitry Andric class X86Subtarget; 24*0b57cec5SDimitry Andric class X86RegisterInfo; 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric class X86FrameLowering : public TargetFrameLowering { 27*0b57cec5SDimitry Andric public: 28*0b57cec5SDimitry Andric X86FrameLowering(const X86Subtarget &STI, unsigned StackAlignOverride); 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric // Cached subtarget predicates. 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric const X86Subtarget &STI; 33*0b57cec5SDimitry Andric const X86InstrInfo &TII; 34*0b57cec5SDimitry Andric const X86RegisterInfo *TRI; 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric unsigned SlotSize; 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric /// Is64Bit implies that x86_64 instructions are available. 39*0b57cec5SDimitry Andric bool Is64Bit; 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric bool IsLP64; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric /// True if the 64-bit frame or stack pointer should be used. True for most 44*0b57cec5SDimitry Andric /// 64-bit targets with the exception of x32. If this is false, 32-bit 45*0b57cec5SDimitry Andric /// instruction operands should be used to manipulate StackPtr and FramePtr. 46*0b57cec5SDimitry Andric bool Uses64BitFramePtr; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric unsigned StackPtr; 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric /// Emit target stack probe code. This is required for all 51*0b57cec5SDimitry Andric /// large stack allocations on Windows. The caller is required to materialize 52*0b57cec5SDimitry Andric /// the number of bytes to probe in RAX/EAX. 53*0b57cec5SDimitry Andric void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, 54*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 55*0b57cec5SDimitry Andric bool InProlog) const; 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric /// Replace a StackProbe inline-stub with the actual probe code inline. 58*0b57cec5SDimitry Andric void inlineStackProbe(MachineFunction &MF, 59*0b57cec5SDimitry Andric MachineBasicBlock &PrologMBB) const override; 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, 62*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 63*0b57cec5SDimitry Andric const DebugLoc &DL) const; 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric /// emitProlog/emitEpilog - These methods insert prolog and epilog code into 66*0b57cec5SDimitry Andric /// the function. 67*0b57cec5SDimitry Andric void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 68*0b57cec5SDimitry Andric void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric void adjustForSegmentedStacks(MachineFunction &MF, 71*0b57cec5SDimitry Andric MachineBasicBlock &PrologueMBB) const override; 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric void adjustForHiPEPrologue(MachineFunction &MF, 74*0b57cec5SDimitry Andric MachineBasicBlock &PrologueMBB) const override; 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, 77*0b57cec5SDimitry Andric RegScavenger *RS = nullptr) const override; 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric bool 80*0b57cec5SDimitry Andric assignCalleeSavedSpillSlots(MachineFunction &MF, 81*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 82*0b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI) const override; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, 85*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 86*0b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI, 87*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 90*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 91*0b57cec5SDimitry Andric std::vector<CalleeSavedInfo> &CSI, 92*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric bool hasFP(const MachineFunction &MF) const override; 95*0b57cec5SDimitry Andric bool hasReservedCallFrame(const MachineFunction &MF) const override; 96*0b57cec5SDimitry Andric bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; 97*0b57cec5SDimitry Andric bool needsFrameIndexResolution(const MachineFunction &MF) const override; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric int getFrameIndexReference(const MachineFunction &MF, int FI, 100*0b57cec5SDimitry Andric unsigned &FrameReg) const override; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric int getFrameIndexReferenceSP(const MachineFunction &MF, 103*0b57cec5SDimitry Andric int FI, unsigned &SPReg, int Adjustment) const; 104*0b57cec5SDimitry Andric int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, 105*0b57cec5SDimitry Andric unsigned &FrameReg, 106*0b57cec5SDimitry Andric bool IgnoreSPUpdates) const override; 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric MachineBasicBlock::iterator 109*0b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 110*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const override; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric void processFunctionBeforeFrameFinalized(MachineFunction &MF, 115*0b57cec5SDimitry Andric RegScavenger *RS) const override; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric /// Check the instruction before/after the passed instruction. If 118*0b57cec5SDimitry Andric /// it is an ADD/SUB/LEA instruction it is deleted argument and the 119*0b57cec5SDimitry Andric /// stack adjustment is returned as a positive value for ADD/LEA and 120*0b57cec5SDimitry Andric /// a negative for SUB. 121*0b57cec5SDimitry Andric int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 122*0b57cec5SDimitry Andric bool doMergeWithPrevious) const; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric /// Emit a series of instructions to increment / decrement the stack 125*0b57cec5SDimitry Andric /// pointer by a constant value. 126*0b57cec5SDimitry Andric void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 127*0b57cec5SDimitry Andric const DebugLoc &DL, int64_t NumBytes, bool InEpilogue) const; 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric /// Check that LEA can be used on SP in an epilogue sequence for \p MF. 130*0b57cec5SDimitry Andric bool canUseLEAForSPInEpilogue(const MachineFunction &MF) const; 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric /// Check whether or not the given \p MBB can be used as a prologue 133*0b57cec5SDimitry Andric /// for the target. 134*0b57cec5SDimitry Andric /// The prologue will be inserted first in this basic block. 135*0b57cec5SDimitry Andric /// This method is used by the shrink-wrapping pass to decide if 136*0b57cec5SDimitry Andric /// \p MBB will be correctly handled by the target. 137*0b57cec5SDimitry Andric /// As soon as the target enable shrink-wrapping without overriding 138*0b57cec5SDimitry Andric /// this method, we assume that each basic block is a valid 139*0b57cec5SDimitry Andric /// prologue. 140*0b57cec5SDimitry Andric bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric /// Check whether or not the given \p MBB can be used as a epilogue 143*0b57cec5SDimitry Andric /// for the target. 144*0b57cec5SDimitry Andric /// The epilogue will be inserted before the first terminator of that block. 145*0b57cec5SDimitry Andric /// This method is used by the shrink-wrapping pass to decide if 146*0b57cec5SDimitry Andric /// \p MBB will be correctly handled by the target. 147*0b57cec5SDimitry Andric bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override; 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric /// Returns true if the target will correctly handle shrink wrapping. 150*0b57cec5SDimitry Andric bool enableShrinkWrapping(const MachineFunction &MF) const override; 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric /// Order the symbols in the local stack. 153*0b57cec5SDimitry Andric /// We want to place the local stack objects in some sort of sensible order. 154*0b57cec5SDimitry Andric /// The heuristic we use is to try and pack them according to static number 155*0b57cec5SDimitry Andric /// of uses and size in order to minimize code size. 156*0b57cec5SDimitry Andric void orderFrameObjects(const MachineFunction &MF, 157*0b57cec5SDimitry Andric SmallVectorImpl<int> &ObjectsToAllocate) const override; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric /// Wraps up getting a CFI index and building a MachineInstr for it. 160*0b57cec5SDimitry Andric void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 161*0b57cec5SDimitry Andric const DebugLoc &DL, const MCCFIInstruction &CFIInst) const; 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric /// Sets up EBP and optionally ESI based on the incoming EBP value. Only 164*0b57cec5SDimitry Andric /// needed for 32-bit. Used in funclet prologues and at catchret destinations. 165*0b57cec5SDimitry Andric MachineBasicBlock::iterator 166*0b57cec5SDimitry Andric restoreWin32EHStackPointers(MachineBasicBlock &MBB, 167*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 168*0b57cec5SDimitry Andric const DebugLoc &DL, bool RestoreSP = false) const; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric int getInitialCFAOffset(const MachineFunction &MF) const override; 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric unsigned getInitialCFARegister(const MachineFunction &MF) const override; 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric /// Return true if the function has a redzone (accessible bytes past the 175*0b57cec5SDimitry Andric /// frame of the top of stack function) as part of it's ABI. 176*0b57cec5SDimitry Andric bool has128ByteRedZone(const MachineFunction& MF) const; 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric private: 179*0b57cec5SDimitry Andric uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; 180*0b57cec5SDimitry Andric 181*0b57cec5SDimitry Andric /// Emit target stack probe as a call to a helper function 182*0b57cec5SDimitry Andric void emitStackProbeCall(MachineFunction &MF, MachineBasicBlock &MBB, 183*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 184*0b57cec5SDimitry Andric bool InProlog) const; 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric /// Emit target stack probe as an inline sequence. 187*0b57cec5SDimitry Andric void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, 188*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 189*0b57cec5SDimitry Andric const DebugLoc &DL, bool InProlog) const; 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric /// Emit a stub to later inline the target stack probe. 192*0b57cec5SDimitry Andric void emitStackProbeInlineStub(MachineFunction &MF, MachineBasicBlock &MBB, 193*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 194*0b57cec5SDimitry Andric const DebugLoc &DL, bool InProlog) const; 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric /// Aligns the stack pointer by ANDing it with -MaxAlign. 197*0b57cec5SDimitry Andric void BuildStackAlignAND(MachineBasicBlock &MBB, 198*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 199*0b57cec5SDimitry Andric unsigned Reg, uint64_t MaxAlign) const; 200*0b57cec5SDimitry Andric 201*0b57cec5SDimitry Andric /// Make small positive stack adjustments using POPs. 202*0b57cec5SDimitry Andric bool adjustStackWithPops(MachineBasicBlock &MBB, 203*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 204*0b57cec5SDimitry Andric int Offset) const; 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric /// Adjusts the stack pointer using LEA, SUB, or ADD. 207*0b57cec5SDimitry Andric MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB, 208*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 209*0b57cec5SDimitry Andric const DebugLoc &DL, int64_t Offset, 210*0b57cec5SDimitry Andric bool InEpilogue) const; 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const; 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const; 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric /// Materialize the catchret target MBB in RAX. 217*0b57cec5SDimitry Andric void emitCatchRetReturnValue(MachineBasicBlock &MBB, 218*0b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 219*0b57cec5SDimitry Andric MachineInstr *CatchRet) const; 220*0b57cec5SDimitry Andric }; 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric } // End llvm namespace 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric #endif 225