| //===-- M68kFrameLowering.h - Define frame lowering for M68k ----*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file contains the M68k declaration of TargetFrameLowering class. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_TARGET_M68K_M68KFRAMELOWERING_H |
| #define LLVM_LIB_TARGET_M68K_M68KFRAMELOWERING_H |
| |
| #include "M68k.h" |
| |
| #include "llvm/CodeGen/TargetFrameLowering.h" |
| |
| namespace llvm { |
| class MachineInstrBuilder; |
| class MCCFIInstruction; |
| class M68kSubtarget; |
| class M68kRegisterInfo; |
| struct Align; |
| |
| class M68kFrameLowering : public TargetFrameLowering { |
| // Cached subtarget predicates. |
| const M68kSubtarget &STI; |
| const TargetInstrInfo &TII; |
| const M68kRegisterInfo *TRI; |
| |
| /// Stack slot size in bytes. |
| unsigned SlotSize; |
| |
| unsigned StackPtr; |
| |
| /// If we're forcing a stack realignment we can't rely on just the frame |
| /// info, we need to know the ABI stack alignment as well in case we have a |
| /// call out. Otherwise just make sure we have some alignment - we'll go |
| /// with the minimum SlotSize. |
| uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; |
| |
| /// Adjusts the stack pointer using LEA, SUB, or ADD. |
| MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| const DebugLoc &DL, int64_t Offset, |
| bool InEpilogue) const; |
| |
| /// Aligns the stack pointer by ANDing it with -MaxAlign. |
| void BuildStackAlignAND(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, const DebugLoc &DL, |
| unsigned Reg, uint64_t MaxAlign) const; |
| |
| /// Wraps up getting a CFI index and building a MachineInstr for it. |
| void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
| const DebugLoc &DL, const MCCFIInstruction &CFIInst) const; |
| |
| void emitPrologueCalleeSavedFrameMoves(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| const DebugLoc &DL) const; |
| |
| unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const; |
| |
| public: |
| explicit M68kFrameLowering(const M68kSubtarget &sti, Align Alignment); |
| |
| static const M68kFrameLowering *create(const M68kSubtarget &ST); |
| |
| /// This method is called during prolog/epilog code insertion to eliminate |
| /// call frame setup and destroy pseudo instructions (but only if the Target |
| /// is using them). It is responsible for eliminating these instructions, |
| /// replacing them with concrete instructions. This method need only be |
| /// implemented if using call frame setup/destroy pseudo instructions. |
| /// Returns an iterator pointing to the instruction after the replaced one. |
| MachineBasicBlock::iterator |
| eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI) const override; |
| |
| /// Insert prolog code into the function. |
| void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; |
| |
| /// Insert epilog code into the function. |
| void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; |
| |
| /// This method determines which of the registers reported by |
| /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. |
| /// The default implementation checks populates the \p SavedRegs bitset with |
| /// all registers which are modified in the function, targets may override |
| /// this function to save additional registers. |
| /// This method also sets up the register scavenger ensuring there is a free |
| /// register or a frameindex available. |
| void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, |
| RegScavenger *RS = nullptr) const override; |
| |
| /// Allows target to override spill slot assignment logic. If implemented, |
| /// assignCalleeSavedSpillSlots() should assign frame slots to all CSI |
| /// entries and return true. If this method returns false, spill slots will |
| /// be assigned using generic implementation. assignCalleeSavedSpillSlots() |
| /// may add, delete or rearrange elements of CSI. |
| bool |
| assignCalleeSavedSpillSlots(MachineFunction &MF, |
| const TargetRegisterInfo *TRI, |
| std::vector<CalleeSavedInfo> &CSI) const override; |
| |
| /// Issues instruction(s) to spill all callee saved registers and returns |
| /// true if it isn't possible / profitable to do so by issuing a series of |
| /// store instructions via storeRegToStackSlot(). Returns false otherwise. |
| bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| ArrayRef<CalleeSavedInfo> CSI, |
| const TargetRegisterInfo *TRI) const override; |
| |
| /// Issues instruction(s) to restore all callee saved registers and returns |
| /// true if it isn't possible / profitable to do so by issuing a series of |
| /// load instructions via loadRegToStackSlot(). Returns false otherwise. |
| bool |
| restoreCalleeSavedRegisters(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| MutableArrayRef<CalleeSavedInfo> CSI, |
| const TargetRegisterInfo *TRI) const override; |
| |
| /// Return true if the specified function should have a dedicated frame |
| /// pointer register. This is true if the function has variable sized |
| /// allocas, if it needs dynamic stack realignment, if frame pointer |
| /// elimination is disabled, or if the frame address is taken. |
| bool hasFP(const MachineFunction &MF) const override; |
| |
| /// Under normal circumstances, when a frame pointer is not required, we |
| /// reserve argument space for call sites in the function immediately on |
| /// entry to the current function. This eliminates the need for add/sub sp |
| /// brackets around call sites. Returns true if the call frame is included as |
| /// part of the stack frame. |
| bool hasReservedCallFrame(const MachineFunction &MF) const override; |
| |
| /// If there is a reserved call frame, the call frame pseudos can be |
| /// simplified. Having a FP, as in the default implementation, is not |
| /// sufficient here since we can't always use it. Use a more nuanced |
| /// condition. |
| bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override; |
| |
| // Do we need to perform FI resolution for this function. Normally, this is |
| // required only when the function has any stack objects. However, FI |
| // resolution actually has another job, not apparent from the title - it |
| // resolves callframe setup/destroy that were not simplified earlier. |
| // |
| // So, this is required for M68k functions that have push sequences even |
| // when there are no stack objects. |
| bool needsFrameIndexResolution(const MachineFunction &MF) const override; |
| |
| /// This method should return the base register and offset used to reference |
| /// a frame index location. The offset is returned directly, and the base |
| /// register is returned via FrameReg. |
| StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, |
| Register &FrameReg) const override; |
| |
| /// Check the instruction before/after the passed instruction. If |
| /// it is an ADD/SUB/LEA instruction it is deleted argument and the |
| /// stack adjustment is returned as a positive value for ADD/LEA and |
| /// a negative for SUB. |
| int mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
| bool doMergeWithPrevious) const; |
| |
| /// Emit a series of instructions to increment / decrement the stack |
| /// pointer by a constant value. |
| void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
| int64_t NumBytes, bool InEpilogue) const; |
| }; |
| } // namespace llvm |
| |
| #endif // LLVM_LIB_TARGET_M68K_M68KFRAMELOWERING_H |