1//==-- AArch64FrameLowering.h - TargetFrameLowering for AArch64 --*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
14#define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H
15
16#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
17#include "llvm/CodeGen/TargetFrameLowering.h"
18#include "llvm/Support/TypeSize.h"
19
20namespace llvm {
21
22class AArch64FrameLowering : public TargetFrameLowering {
23public:
24 explicit AArch64FrameLowering()
25 : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16),
26 true /*StackRealignable*/) {}
27
28 void resetCFIToInitialState(MachineBasicBlock &MBB) const override;
29
30 MachineBasicBlock::iterator
31 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
32 MachineBasicBlock::iterator I) const override;
33
34 /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
35 /// the function.
36 void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
37 void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
38
39 bool enableCFIFixup(const MachineFunction &MF) const override;
40
41 bool enableFullCFIFixup(const MachineFunction &MF) const override;
42
43 bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
44
45 StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
46 Register &FrameReg) const override;
47 StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF,
48 int FI) const override;
49 StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI,
50 Register &FrameReg, bool PreferFP,
51 bool ForSimm) const;
52 StackOffset resolveFrameOffsetReference(const MachineFunction &MF,
53 int64_t ObjectOffset, bool isFixed,
54 bool isSVE, Register &FrameReg,
55 bool PreferFP, bool ForSimm) const;
56 bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
57 MachineBasicBlock::iterator MI,
58 ArrayRef<CalleeSavedInfo> CSI,
59 const TargetRegisterInfo *TRI) const override;
60
61 bool
62 restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
63 MachineBasicBlock::iterator MI,
64 MutableArrayRef<CalleeSavedInfo> CSI,
65 const TargetRegisterInfo *TRI) const override;
66
67 /// Can this function use the red zone for local allocations.
68 bool canUseRedZone(const MachineFunction &MF) const;
69
70 bool hasReservedCallFrame(const MachineFunction &MF) const override;
71
72 bool assignCalleeSavedSpillSlots(MachineFunction &MF,
73 const TargetRegisterInfo *TRI,
74 std::vector<CalleeSavedInfo> &CSI,
75 unsigned &MinCSFrameIndex,
76 unsigned &MaxCSFrameIndex) const override;
77
78 void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
79 RegScavenger *RS) const override;
80
81 /// Returns true if the target will correctly handle shrink wrapping.
82 bool enableShrinkWrapping(const MachineFunction &MF) const override {
83 return true;
84 }
85
86 bool enableStackSlotScavenging(const MachineFunction &MF) const override;
87 TargetStackID::Value getStackIDForScalableVectors() const override;
88
89 void processFunctionBeforeFrameFinalized(MachineFunction &MF,
90 RegScavenger *RS) const override;
91
92 void
93 processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,
94 RegScavenger *RS) const override;
95
96 unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
97
98 unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;
99
100 StackOffset
101 getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,
102 Register &FrameReg,
103 bool IgnoreSPUpdates) const override;
104 StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF,
105 int FI) const override;
106 int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const;
107
108 bool isSupportedStackID(TargetStackID::Value ID) const override {
109 switch (ID) {
110 default:
111 return false;
112 case TargetStackID::Default:
113 case TargetStackID::ScalableVector:
114 case TargetStackID::NoAlloc:
115 return true;
116 }
117 }
118
119 bool isStackIdSafeForLocalArea(unsigned StackId) const override {
120 // We don't support putting SVE objects into the pre-allocated local
121 // frame block at the moment.
122 return StackId != TargetStackID::ScalableVector;
123 }
124
125 void
126 orderFrameObjects(const MachineFunction &MF,
127 SmallVectorImpl<int> &ObjectsToAllocate) const override;
128
129protected:
130 bool hasFPImpl(const MachineFunction &MF) const override;
131
132private:
133 /// Returns true if a homogeneous prolog or epilog code can be emitted
134 /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo
135 /// instructions are emitted in place. When Exit block is given, this check is
136 /// for epilog.
137 bool homogeneousPrologEpilog(MachineFunction &MF,
138 MachineBasicBlock *Exit = nullptr) const;
139
140 /// Returns true if CSRs should be paired.
141 bool producePairRegisters(MachineFunction &MF) const;
142
143 bool shouldCombineCSRLocalStackBump(MachineFunction &MF,
144 uint64_t StackBumpBytes) const;
145
146 int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const;
147 int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF,
148 int &MinCSFrameIndex,
149 int &MaxCSFrameIndex) const;
150 bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB,
151 uint64_t StackBumpBytes) const;
152 void emitCalleeSavedGPRLocations(MachineBasicBlock &MBB,
153 MachineBasicBlock::iterator MBBI) const;
154 void emitCalleeSavedSVELocations(MachineBasicBlock &MBB,
155 MachineBasicBlock::iterator MBBI) const;
156 void emitCalleeSavedGPRRestores(MachineBasicBlock &MBB,
157 MachineBasicBlock::iterator MBBI) const;
158 void emitCalleeSavedSVERestores(MachineBasicBlock &MBB,
159 MachineBasicBlock::iterator MBBI) const;
160 void allocateStackSpace(MachineBasicBlock &MBB,
161 MachineBasicBlock::iterator MBBI,
162 int64_t RealignmentPadding, StackOffset AllocSize,
163 bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI,
164 StackOffset InitialOffset, bool FollowupAllocs) const;
165 /// Make a determination whether a Hazard slot is used and create it if
166 /// needed.
167 void determineStackHazardSlot(MachineFunction &MF,
168 BitVector &SavedRegs) const;
169
170 /// Emit target zero call-used regs.
171 void emitZeroCallUsedRegs(BitVector RegsToZero,
172 MachineBasicBlock &MBB) const override;
173
174 /// Replace a StackProbe stub (if any) with the actual probe code inline
175 void inlineStackProbe(MachineFunction &MF,
176 MachineBasicBlock &PrologueMBB) const override;
177
178 void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI,
179 Register ScratchReg, int64_t FrameSize,
180 StackOffset CFAOffset) const;
181
182 MachineBasicBlock::iterator
183 inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI,
184 int64_t NegProbeSize,
185 Register TargetReg) const;
186
187 void emitRemarks(const MachineFunction &MF,
188 MachineOptimizationRemarkEmitter *ORE) const override;
189};
190
191} // End llvm namespace
192
193#endif
194