261 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9//10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H14#define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H15 16#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"17#include "llvm/CodeGen/TargetFrameLowering.h"18#include "llvm/Support/TypeSize.h"19 20namespace llvm {21 22class TargetLowering;23class AArch64FunctionInfo;24class AArch64PrologueEmitter;25class AArch64EpilogueEmitter;26 27struct SVEStackSizes {28 uint64_t ZPRStackSize{0};29 uint64_t PPRStackSize{0};30};31 32class AArch64FrameLowering : public TargetFrameLowering {33public:34 explicit AArch64FrameLowering()35 : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16),36 true /*StackRealignable*/) {}37 38 void resetCFIToInitialState(MachineBasicBlock &MBB) const override;39 40 MachineBasicBlock::iterator41 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,42 MachineBasicBlock::iterator I) const override;43 44 /// emitProlog/emitEpilog - These methods insert prolog and epilog code into45 /// the function.46 void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;47 void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;48 49 /// Harden the entire function with pac-ret.50 ///51 /// If pac-ret+leaf is requested, we want to harden as much code as possible.52 /// This function inserts pac-ret hardening at the points where prologue and53 /// epilogue are traditionally inserted, ignoring possible shrink-wrapping54 /// optimization.55 void emitPacRetPlusLeafHardening(MachineFunction &MF) const;56 57 bool enableCFIFixup(const MachineFunction &MF) const override;58 59 bool enableFullCFIFixup(const MachineFunction &MF) const override;60 61 bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;62 63 StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,64 Register &FrameReg) const override;65 StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF,66 int FI) const override;67 StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI,68 Register &FrameReg, bool PreferFP,69 bool ForSimm) const;70 StackOffset resolveFrameOffsetReference(const MachineFunction &MF,71 int64_t ObjectOffset, bool isFixed,72 TargetStackID::Value StackID,73 Register &FrameReg, bool PreferFP,74 bool ForSimm) const;75 bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,76 MachineBasicBlock::iterator MI,77 ArrayRef<CalleeSavedInfo> CSI,78 const TargetRegisterInfo *TRI) const override;79 80 bool81 restoreCalleeSavedRegisters(MachineBasicBlock &MBB,82 MachineBasicBlock::iterator MI,83 MutableArrayRef<CalleeSavedInfo> CSI,84 const TargetRegisterInfo *TRI) const override;85 86 /// Can this function use the red zone for local allocations.87 bool canUseRedZone(const MachineFunction &MF) const;88 89 bool hasReservedCallFrame(const MachineFunction &MF) const override;90 91 bool assignCalleeSavedSpillSlots(MachineFunction &MF,92 const TargetRegisterInfo *TRI,93 std::vector<CalleeSavedInfo> &CSI,94 unsigned &MinCSFrameIndex,95 unsigned &MaxCSFrameIndex) const override;96 97 void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,98 RegScavenger *RS) const override;99 100 /// Returns true if the target will correctly handle shrink wrapping.101 bool enableShrinkWrapping(const MachineFunction &MF) const override {102 return true;103 }104 105 bool enableStackSlotScavenging(const MachineFunction &MF) const override;106 TargetStackID::Value getStackIDForScalableVectors() const override;107 108 void processFunctionBeforeFrameFinalized(MachineFunction &MF,109 RegScavenger *RS) const override;110 111 void112 processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF,113 RegScavenger *RS) const override;114 115 unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;116 117 unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const;118 119 StackOffset120 getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,121 Register &FrameReg,122 bool IgnoreSPUpdates) const override;123 StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF,124 int FI) const override;125 int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const;126 127 bool isSupportedStackID(TargetStackID::Value ID) const override {128 switch (ID) {129 default:130 return false;131 case TargetStackID::Default:132 case TargetStackID::ScalableVector:133 case TargetStackID::ScalablePredicateVector:134 case TargetStackID::NoAlloc:135 return true;136 }137 }138 139 bool isStackIdSafeForLocalArea(unsigned StackId) const override {140 // We don't support putting SVE objects into the pre-allocated local141 // frame block at the moment.142 return (StackId != TargetStackID::ScalableVector &&143 StackId != TargetStackID::ScalablePredicateVector);144 }145 146 void147 orderFrameObjects(const MachineFunction &MF,148 SmallVectorImpl<int> &ObjectsToAllocate) const override;149 150 bool isFPReserved(const MachineFunction &MF) const;151 152 bool needsWinCFI(const MachineFunction &MF) const;153 154 bool requiresSaveVG(const MachineFunction &MF) const;155 156 /// Returns the size of the entire ZPR stackframe (calleesaves + spills).157 StackOffset getZPRStackSize(const MachineFunction &MF) const;158 159 /// Returns the size of the entire PPR stackframe (calleesaves + spills +160 /// hazard padding).161 StackOffset getPPRStackSize(const MachineFunction &MF) const;162 163 /// Returns the size of the entire SVE stackframe (PPRs + ZPRs).164 StackOffset getSVEStackSize(const MachineFunction &MF) const {165 return getZPRStackSize(MF) + getPPRStackSize(MF);166 }167 168 friend class AArch64PrologueEpilogueCommon;169 friend class AArch64PrologueEmitter;170 friend class AArch64EpilogueEmitter;171 172protected:173 bool hasFPImpl(const MachineFunction &MF) const override;174 175private:176 /// Returns true if a homogeneous prolog or epilog code can be emitted177 /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo178 /// instructions are emitted in place. When Exit block is given, this check is179 /// for epilog.180 bool homogeneousPrologEpilog(MachineFunction &MF,181 MachineBasicBlock *Exit = nullptr) const;182 183 /// Returns true if CSRs should be paired.184 bool producePairRegisters(MachineFunction &MF) const;185 186 /// Make a determination whether a Hazard slot is used and create it if187 /// needed.188 void determineStackHazardSlot(MachineFunction &MF,189 BitVector &SavedRegs) const;190 191 /// Emit target zero call-used regs.192 void emitZeroCallUsedRegs(BitVector RegsToZero,193 MachineBasicBlock &MBB) const override;194 195 /// Replace a StackProbe stub (if any) with the actual probe code inline196 void inlineStackProbe(MachineFunction &MF,197 MachineBasicBlock &PrologueMBB) const override;198 199 void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI,200 Register ScratchReg, int64_t FrameSize,201 StackOffset CFAOffset) const;202 203 MachineBasicBlock::iterator204 inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI,205 int64_t NegProbeSize,206 Register TargetReg) const;207 208 void emitRemarks(const MachineFunction &MF,209 MachineOptimizationRemarkEmitter *ORE) const override;210 211 bool windowsRequiresStackProbe(const MachineFunction &MF,212 uint64_t StackSizeInBytes) const;213 214 bool shouldSignReturnAddressEverywhere(const MachineFunction &MF) const;215 216 StackOffset getFPOffset(const MachineFunction &MF,217 int64_t ObjectOffset) const;218 219 StackOffset getStackOffset(const MachineFunction &MF,220 int64_t ObjectOffset) const;221 222 // Given a load or a store instruction, generate an appropriate unwinding SEH223 // code on Windows.224 MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI,225 const TargetInstrInfo &TII,226 MachineInstr::MIFlag Flag) const;227 228 /// Returns how much of the incoming argument stack area (in bytes) we should229 /// clean up in an epilogue. For the C calling convention this will be 0, for230 /// guaranteed tail call conventions it can be positive (a normal return or a231 /// tail call to a function that uses less stack space for arguments) or232 /// negative (for a tail call to a function that needs more stack space than233 /// us for arguments).234 int64_t getArgumentStackToRestore(MachineFunction &MF,235 MachineBasicBlock &MBB) const;236 237 // Find a scratch register that we can use at the start of the prologue to238 // re-align the stack pointer. We avoid using callee-save registers since239 // they may appear to be free when this is called from canUseAsPrologue240 // (during shrink wrapping), but then no longer be free when this is called241 // from emitPrologue.242 //243 // FIXME: This is a bit conservative, since in the above case we could use one244 // of the callee-save registers as a scratch temp to re-align the stack245 // pointer, but we would then have to make sure that we were in fact saving at246 // least one callee-save register in the prologue, which is additional247 // complexity that doesn't seem worth the benefit.248 Register findScratchNonCalleeSaveRegister(MachineBasicBlock *MBB,249 bool HasCall = false) const;250 251 /// Returns the size of the fixed object area (allocated next to sp on entry)252 /// On Win64 this may include a var args area and an UnwindHelp object for EH.253 unsigned getFixedObjectSize(const MachineFunction &MF,254 const AArch64FunctionInfo *AFI, bool IsWin64,255 bool IsFunclet) const;256};257 258} // End llvm namespace259 260#endif261