xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kFrameLowering.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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