aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/M68k/M68kFrameLowering.h
blob: 0eba9e08d858e9ca4e6221da941785400b4511b6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//===- 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