1*fe6060f1SDimitry Andric //===- M68kFrameLowering.h - Define frame lowering for M68k -*- C++ -*-===// 2*fe6060f1SDimitry Andric // 3*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*fe6060f1SDimitry Andric // 7*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8*fe6060f1SDimitry Andric /// 9*fe6060f1SDimitry Andric /// \file 10*fe6060f1SDimitry Andric /// This file contains the M68k declaration of TargetFrameLowering class. 11*fe6060f1SDimitry Andric /// 12*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 13*fe6060f1SDimitry Andric 14*fe6060f1SDimitry Andric #ifndef LLVM_LIB_TARGET_M68K_M68KFRAMELOWERING_H 15*fe6060f1SDimitry Andric #define LLVM_LIB_TARGET_M68K_M68KFRAMELOWERING_H 16*fe6060f1SDimitry Andric 17*fe6060f1SDimitry Andric #include "M68k.h" 18*fe6060f1SDimitry Andric 19*fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 20*fe6060f1SDimitry Andric 21*fe6060f1SDimitry Andric namespace llvm { 22*fe6060f1SDimitry Andric class MachineInstrBuilder; 23*fe6060f1SDimitry Andric class MCCFIInstruction; 24*fe6060f1SDimitry Andric class M68kSubtarget; 25*fe6060f1SDimitry Andric class M68kRegisterInfo; 26*fe6060f1SDimitry Andric struct Align; 27*fe6060f1SDimitry Andric 28*fe6060f1SDimitry Andric class M68kFrameLowering : public TargetFrameLowering { 29*fe6060f1SDimitry Andric // Cached subtarget predicates. 30*fe6060f1SDimitry Andric const M68kSubtarget &STI; 31*fe6060f1SDimitry Andric const TargetInstrInfo &TII; 32*fe6060f1SDimitry Andric const M68kRegisterInfo *TRI; 33*fe6060f1SDimitry Andric 34*fe6060f1SDimitry Andric /// Stack slot size in bytes. 35*fe6060f1SDimitry Andric unsigned SlotSize; 36*fe6060f1SDimitry Andric 37*fe6060f1SDimitry Andric unsigned StackPtr; 38*fe6060f1SDimitry Andric 39*fe6060f1SDimitry Andric /// If we're forcing a stack realignment we can't rely on just the frame 40*fe6060f1SDimitry Andric /// info, we need to know the ABI stack alignment as well in case we have a 41*fe6060f1SDimitry Andric /// call out. Otherwise just make sure we have some alignment - we'll go 42*fe6060f1SDimitry Andric /// with the minimum SlotSize. 43*fe6060f1SDimitry Andric uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; 44*fe6060f1SDimitry Andric 45*fe6060f1SDimitry Andric /// Adjusts the stack pointer using LEA, SUB, or ADD. 46*fe6060f1SDimitry Andric MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB, 47*fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI, 48*fe6060f1SDimitry Andric const DebugLoc &DL, int64_t Offset, 49*fe6060f1SDimitry Andric bool InEpilogue) const; 50*fe6060f1SDimitry Andric 51*fe6060f1SDimitry Andric /// Aligns the stack pointer by ANDing it with -MaxAlign. 52*fe6060f1SDimitry Andric void BuildStackAlignAND(MachineBasicBlock &MBB, 53*fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 54*fe6060f1SDimitry Andric unsigned Reg, uint64_t MaxAlign) const; 55*fe6060f1SDimitry Andric 56*fe6060f1SDimitry Andric /// Wraps up getting a CFI index and building a MachineInstr for it. 57*fe6060f1SDimitry Andric void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 58*fe6060f1SDimitry Andric const DebugLoc &DL, const MCCFIInstruction &CFIInst) const; 59*fe6060f1SDimitry Andric 60*fe6060f1SDimitry Andric void emitPrologueCalleeSavedFrameMoves(MachineBasicBlock &MBB, 61*fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI, 62*fe6060f1SDimitry Andric const DebugLoc &DL) const; 63*fe6060f1SDimitry Andric 64*fe6060f1SDimitry Andric unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const; 65*fe6060f1SDimitry Andric 66*fe6060f1SDimitry Andric public: 67*fe6060f1SDimitry Andric explicit M68kFrameLowering(const M68kSubtarget &sti, Align Alignment); 68*fe6060f1SDimitry Andric 69*fe6060f1SDimitry Andric static const M68kFrameLowering *create(const M68kSubtarget &ST); 70*fe6060f1SDimitry Andric 71*fe6060f1SDimitry Andric /// This method is called during prolog/epilog code insertion to eliminate 72*fe6060f1SDimitry Andric /// call frame setup and destroy pseudo instructions (but only if the Target 73*fe6060f1SDimitry Andric /// is using them). It is responsible for eliminating these instructions, 74*fe6060f1SDimitry Andric /// replacing them with concrete instructions. This method need only be 75*fe6060f1SDimitry Andric /// implemented if using call frame setup/destroy pseudo instructions. 76*fe6060f1SDimitry Andric /// Returns an iterator pointing to the instruction after the replaced one. 77*fe6060f1SDimitry Andric MachineBasicBlock::iterator 78*fe6060f1SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 79*fe6060f1SDimitry Andric MachineBasicBlock::iterator MI) const override; 80*fe6060f1SDimitry Andric 81*fe6060f1SDimitry Andric /// Insert prolog code into the function. 82*fe6060f1SDimitry Andric void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 83*fe6060f1SDimitry Andric 84*fe6060f1SDimitry Andric /// Insert epilog code into the function. 85*fe6060f1SDimitry Andric void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 86*fe6060f1SDimitry Andric 87*fe6060f1SDimitry Andric /// This method determines which of the registers reported by 88*fe6060f1SDimitry Andric /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. 89*fe6060f1SDimitry Andric /// The default implementation checks populates the \p SavedRegs bitset with 90*fe6060f1SDimitry Andric /// all registers which are modified in the function, targets may override 91*fe6060f1SDimitry Andric /// this function to save additional registers. 92*fe6060f1SDimitry Andric /// This method also sets up the register scavenger ensuring there is a free 93*fe6060f1SDimitry Andric /// register or a frameindex available. 94*fe6060f1SDimitry Andric void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, 95*fe6060f1SDimitry Andric RegScavenger *RS = nullptr) const override; 96*fe6060f1SDimitry Andric 97*fe6060f1SDimitry Andric /// Allows target to override spill slot assignment logic. If implemented, 98*fe6060f1SDimitry Andric /// assignCalleeSavedSpillSlots() should assign frame slots to all CSI 99*fe6060f1SDimitry Andric /// entries and return true. If this method returns false, spill slots will 100*fe6060f1SDimitry Andric /// be assigned using generic implementation. assignCalleeSavedSpillSlots() 101*fe6060f1SDimitry Andric /// may add, delete or rearrange elements of CSI. 102*fe6060f1SDimitry Andric bool 103*fe6060f1SDimitry Andric assignCalleeSavedSpillSlots(MachineFunction &MF, 104*fe6060f1SDimitry Andric const TargetRegisterInfo *TRI, 105*fe6060f1SDimitry Andric std::vector<CalleeSavedInfo> &CSI) const override; 106*fe6060f1SDimitry Andric 107*fe6060f1SDimitry Andric /// Issues instruction(s) to spill all callee saved registers and returns 108*fe6060f1SDimitry Andric /// true if it isn't possible / profitable to do so by issuing a series of 109*fe6060f1SDimitry Andric /// store instructions via storeRegToStackSlot(). Returns false otherwise. 110*fe6060f1SDimitry Andric bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, 111*fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 112*fe6060f1SDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 113*fe6060f1SDimitry Andric const TargetRegisterInfo *TRI) const override; 114*fe6060f1SDimitry Andric 115*fe6060f1SDimitry Andric /// Issues instruction(s) to restore all callee saved registers and returns 116*fe6060f1SDimitry Andric /// true if it isn't possible / profitable to do so by issuing a series of 117*fe6060f1SDimitry Andric /// load instructions via loadRegToStackSlot(). Returns false otherwise. 118*fe6060f1SDimitry Andric bool 119*fe6060f1SDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 120*fe6060f1SDimitry Andric MachineBasicBlock::iterator MI, 121*fe6060f1SDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, 122*fe6060f1SDimitry Andric const TargetRegisterInfo *TRI) const override; 123*fe6060f1SDimitry Andric 124*fe6060f1SDimitry Andric /// Return true if the specified function should have a dedicated frame 125*fe6060f1SDimitry Andric /// pointer register. This is true if the function has variable sized 126*fe6060f1SDimitry Andric /// allocas, if it needs dynamic stack realignment, if frame pointer 127*fe6060f1SDimitry Andric /// elimination is disabled, or if the frame address is taken. 128*fe6060f1SDimitry Andric bool hasFP(const MachineFunction &MF) const override; 129*fe6060f1SDimitry Andric 130*fe6060f1SDimitry Andric /// Under normal circumstances, when a frame pointer is not required, we 131*fe6060f1SDimitry Andric /// reserve argument space for call sites in the function immediately on 132*fe6060f1SDimitry Andric /// entry to the current function. This eliminates the need for add/sub sp 133*fe6060f1SDimitry Andric /// brackets around call sites. Returns true if the call frame is included as 134*fe6060f1SDimitry Andric /// part of the stack frame. 135*fe6060f1SDimitry Andric bool hasReservedCallFrame(const MachineFunction &MF) const override; 136*fe6060f1SDimitry Andric 137*fe6060f1SDimitry Andric /// If there is a reserved call frame, the call frame pseudos can be 138*fe6060f1SDimitry Andric /// simplified. Having a FP, as in the default implementation, is not 139*fe6060f1SDimitry Andric /// sufficient here since we can't always use it. Use a more nuanced 140*fe6060f1SDimitry Andric /// condition. 141*fe6060f1SDimitry Andric bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; 142*fe6060f1SDimitry Andric 143*fe6060f1SDimitry Andric // Do we need to perform FI resolution for this function. Normally, this is 144*fe6060f1SDimitry Andric // required only when the function has any stack objects. However, FI 145*fe6060f1SDimitry Andric // resolution actually has another job, not apparent from the title - it 146*fe6060f1SDimitry Andric // resolves callframe setup/destroy that were not simplified earlier. 147*fe6060f1SDimitry Andric // 148*fe6060f1SDimitry Andric // So, this is required for M68k functions that have push sequences even 149*fe6060f1SDimitry Andric // when there are no stack objects. 150*fe6060f1SDimitry Andric bool needsFrameIndexResolution(const MachineFunction &MF) const override; 151*fe6060f1SDimitry Andric 152*fe6060f1SDimitry Andric /// This method should return the base register and offset used to reference 153*fe6060f1SDimitry Andric /// a frame index location. The offset is returned directly, and the base 154*fe6060f1SDimitry Andric /// register is returned via FrameReg. 155*fe6060f1SDimitry Andric StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, 156*fe6060f1SDimitry Andric Register &FrameReg) const override; 157*fe6060f1SDimitry Andric 158*fe6060f1SDimitry Andric /// Check the instruction before/after the passed instruction. If 159*fe6060f1SDimitry Andric /// it is an ADD/SUB/LEA instruction it is deleted argument and the 160*fe6060f1SDimitry Andric /// stack adjustment is returned as a positive value for ADD/LEA and 161*fe6060f1SDimitry Andric /// a negative for SUB. 162*fe6060f1SDimitry Andric int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 163*fe6060f1SDimitry Andric bool doMergeWithPrevious) const; 164*fe6060f1SDimitry Andric 165*fe6060f1SDimitry Andric /// Emit a series of instructions to increment / decrement the stack 166*fe6060f1SDimitry Andric /// pointer by a constant value. 167*fe6060f1SDimitry Andric void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 168*fe6060f1SDimitry Andric int64_t NumBytes, bool InEpilogue) const; 169*fe6060f1SDimitry Andric }; 170*fe6060f1SDimitry Andric } // namespace llvm 171*fe6060f1SDimitry Andric 172*fe6060f1SDimitry Andric #endif 173