10b57cec5SDimitry Andric //==-- AArch64FrameLowering.h - TargetFrameLowering for AArch64 --*- C++ -*-==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H 150b57cec5SDimitry Andric 16*62987288SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 18*62987288SDimitry Andric #include "llvm/Support/TypeSize.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class AArch64FrameLowering : public TargetFrameLowering { 230b57cec5SDimitry Andric public: AArch64FrameLowering()240b57cec5SDimitry Andric explicit AArch64FrameLowering() 258bcb0991SDimitry Andric : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16), 260b57cec5SDimitry Andric true /*StackRealignable*/) {} 270b57cec5SDimitry Andric 2881ad6265SDimitry Andric void resetCFIToInitialState(MachineBasicBlock &MBB) const override; 2981ad6265SDimitry Andric 300b57cec5SDimitry Andric MachineBasicBlock::iterator 310b57cec5SDimitry Andric eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, 320b57cec5SDimitry Andric MachineBasicBlock::iterator I) const override; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric /// emitProlog/emitEpilog - These methods insert prolog and epilog code into 350b57cec5SDimitry Andric /// the function. 360b57cec5SDimitry Andric void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 370b57cec5SDimitry Andric void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; 380b57cec5SDimitry Andric 3906c3fb27SDimitry Andric bool enableCFIFixup(MachineFunction &MF) const override; 4006c3fb27SDimitry Andric 410b57cec5SDimitry Andric bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; 420b57cec5SDimitry Andric 43e8d8bef9SDimitry Andric StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, 445ffd83dbSDimitry Andric Register &FrameReg) const override; 4552418fc2SDimitry Andric StackOffset getFrameIndexReferenceFromSP(const MachineFunction &MF, 4652418fc2SDimitry Andric int FI) const override; 478bcb0991SDimitry Andric StackOffset resolveFrameIndexReference(const MachineFunction &MF, int FI, 485ffd83dbSDimitry Andric Register &FrameReg, bool PreferFP, 490b57cec5SDimitry Andric bool ForSimm) const; 508bcb0991SDimitry Andric StackOffset resolveFrameOffsetReference(const MachineFunction &MF, 51480093f4SDimitry Andric int64_t ObjectOffset, bool isFixed, 525ffd83dbSDimitry Andric bool isSVE, Register &FrameReg, 530b57cec5SDimitry Andric bool PreferFP, bool ForSimm) const; 540b57cec5SDimitry Andric bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, 550b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 565ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 570b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 580b57cec5SDimitry Andric 595ffd83dbSDimitry Andric bool 605ffd83dbSDimitry Andric restoreCalleeSavedRegisters(MachineBasicBlock &MBB, 610b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 625ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, 630b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// Can this function use the red zone for local allocations. 660b57cec5SDimitry Andric bool canUseRedZone(const MachineFunction &MF) const; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric bool hasFP(const MachineFunction &MF) const override; 690b57cec5SDimitry Andric bool hasReservedCallFrame(const MachineFunction &MF) const override; 700b57cec5SDimitry Andric 71fe6060f1SDimitry Andric bool assignCalleeSavedSpillSlots(MachineFunction &MF, 72e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI, 73fe6060f1SDimitry Andric std::vector<CalleeSavedInfo> &CSI, 74fe6060f1SDimitry Andric unsigned &MinCSFrameIndex, 75fe6060f1SDimitry Andric unsigned &MaxCSFrameIndex) const override; 76e8d8bef9SDimitry Andric 770b57cec5SDimitry Andric void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, 780b57cec5SDimitry Andric RegScavenger *RS) const override; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /// Returns true if the target will correctly handle shrink wrapping. enableShrinkWrapping(const MachineFunction & MF)810b57cec5SDimitry Andric bool enableShrinkWrapping(const MachineFunction &MF) const override { 820b57cec5SDimitry Andric return true; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric bool enableStackSlotScavenging(const MachineFunction &MF) const override; 86480093f4SDimitry Andric TargetStackID::Value getStackIDForScalableVectors() const override; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void processFunctionBeforeFrameFinalized(MachineFunction &MF, 890b57cec5SDimitry Andric RegScavenger *RS) const override; 900b57cec5SDimitry Andric 915ffd83dbSDimitry Andric void 925ffd83dbSDimitry Andric processFunctionBeforeFrameIndicesReplaced(MachineFunction &MF, 935ffd83dbSDimitry Andric RegScavenger *RS) const override; 945ffd83dbSDimitry Andric 950b57cec5SDimitry Andric unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const; 980b57cec5SDimitry Andric 99e8d8bef9SDimitry Andric StackOffset 100e8d8bef9SDimitry Andric getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, 1015ffd83dbSDimitry Andric Register &FrameReg, 1020b57cec5SDimitry Andric bool IgnoreSPUpdates) const override; 103e8d8bef9SDimitry Andric StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, 1040b57cec5SDimitry Andric int FI) const override; 1050b57cec5SDimitry Andric int getSEHFrameIndexOffset(const MachineFunction &MF, int FI) const; 1060b57cec5SDimitry Andric isSupportedStackID(TargetStackID::Value ID)1078bcb0991SDimitry Andric bool isSupportedStackID(TargetStackID::Value ID) const override { 1088bcb0991SDimitry Andric switch (ID) { 1098bcb0991SDimitry Andric default: 1108bcb0991SDimitry Andric return false; 1118bcb0991SDimitry Andric case TargetStackID::Default: 112e8d8bef9SDimitry Andric case TargetStackID::ScalableVector: 1138bcb0991SDimitry Andric case TargetStackID::NoAlloc: 1148bcb0991SDimitry Andric return true; 1158bcb0991SDimitry Andric } 1168bcb0991SDimitry Andric } 1178bcb0991SDimitry Andric isStackIdSafeForLocalArea(unsigned StackId)118979e22ffSDimitry Andric bool isStackIdSafeForLocalArea(unsigned StackId) const override { 119979e22ffSDimitry Andric // We don't support putting SVE objects into the pre-allocated local 120979e22ffSDimitry Andric // frame block at the moment. 121e8d8bef9SDimitry Andric return StackId != TargetStackID::ScalableVector; 122979e22ffSDimitry Andric } 123979e22ffSDimitry Andric 124e8d8bef9SDimitry Andric void 125e8d8bef9SDimitry Andric orderFrameObjects(const MachineFunction &MF, 126e8d8bef9SDimitry Andric SmallVectorImpl<int> &ObjectsToAllocate) const override; 127e8d8bef9SDimitry Andric 1280b57cec5SDimitry Andric private: 129fe6060f1SDimitry Andric /// Returns true if a homogeneous prolog or epilog code can be emitted 130fe6060f1SDimitry Andric /// for the size optimization. If so, HOM_Prolog/HOM_Epilog pseudo 131fe6060f1SDimitry Andric /// instructions are emitted in place. When Exit block is given, this check is 132fe6060f1SDimitry Andric /// for epilog. 133fe6060f1SDimitry Andric bool homogeneousPrologEpilog(MachineFunction &MF, 134fe6060f1SDimitry Andric MachineBasicBlock *Exit = nullptr) const; 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric /// Returns true if CSRs should be paired. 137fe6060f1SDimitry Andric bool producePairRegisters(MachineFunction &MF) const; 138fe6060f1SDimitry Andric 1390b57cec5SDimitry Andric bool shouldCombineCSRLocalStackBump(MachineFunction &MF, 140480093f4SDimitry Andric uint64_t StackBumpBytes) const; 141480093f4SDimitry Andric 142480093f4SDimitry Andric int64_t estimateSVEStackObjectOffsets(MachineFrameInfo &MF) const; 143480093f4SDimitry Andric int64_t assignSVEStackObjectOffsets(MachineFrameInfo &MF, 144480093f4SDimitry Andric int &MinCSFrameIndex, 145480093f4SDimitry Andric int &MaxCSFrameIndex) const; 1465ffd83dbSDimitry Andric bool shouldCombineCSRLocalStackBumpInEpilogue(MachineBasicBlock &MBB, 1475ffd83dbSDimitry Andric unsigned StackBumpBytes) const; 14881ad6265SDimitry Andric void emitCalleeSavedGPRLocations(MachineBasicBlock &MBB, 14981ad6265SDimitry Andric MachineBasicBlock::iterator MBBI) const; 15081ad6265SDimitry Andric void emitCalleeSavedSVELocations(MachineBasicBlock &MBB, 15181ad6265SDimitry Andric MachineBasicBlock::iterator MBBI) const; 15281ad6265SDimitry Andric void emitCalleeSavedGPRRestores(MachineBasicBlock &MBB, 15381ad6265SDimitry Andric MachineBasicBlock::iterator MBBI) const; 15481ad6265SDimitry Andric void emitCalleeSavedSVERestores(MachineBasicBlock &MBB, 15581ad6265SDimitry Andric MachineBasicBlock::iterator MBBI) const; 1565f757f3fSDimitry Andric void allocateStackSpace(MachineBasicBlock &MBB, 1575f757f3fSDimitry Andric MachineBasicBlock::iterator MBBI, 1585f757f3fSDimitry Andric int64_t RealignmentPadding, StackOffset AllocSize, 1595f757f3fSDimitry Andric bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI, 1605f757f3fSDimitry Andric StackOffset InitialOffset, bool FollowupAllocs) const; 1610fca6ea1SDimitry Andric /// Make a determination whether a Hazard slot is used and create it if 1620fca6ea1SDimitry Andric /// needed. 1630fca6ea1SDimitry Andric void determineStackHazardSlot(MachineFunction &MF, 1640fca6ea1SDimitry Andric BitVector &SavedRegs) const; 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric /// Emit target zero call-used regs. 16781ad6265SDimitry Andric void emitZeroCallUsedRegs(BitVector RegsToZero, 16881ad6265SDimitry Andric MachineBasicBlock &MBB) const override; 1695f757f3fSDimitry Andric 1705f757f3fSDimitry Andric /// Replace a StackProbe stub (if any) with the actual probe code inline 1715f757f3fSDimitry Andric void inlineStackProbe(MachineFunction &MF, 1725f757f3fSDimitry Andric MachineBasicBlock &PrologueMBB) const override; 1735f757f3fSDimitry Andric 1745f757f3fSDimitry Andric void inlineStackProbeFixed(MachineBasicBlock::iterator MBBI, 1755f757f3fSDimitry Andric Register ScratchReg, int64_t FrameSize, 1765f757f3fSDimitry Andric StackOffset CFAOffset) const; 1775f757f3fSDimitry Andric 1785f757f3fSDimitry Andric MachineBasicBlock::iterator 1795f757f3fSDimitry Andric inlineStackProbeLoopExactMultiple(MachineBasicBlock::iterator MBBI, 1805f757f3fSDimitry Andric int64_t NegProbeSize, 1815f757f3fSDimitry Andric Register TargetReg) const; 182*62987288SDimitry Andric 183*62987288SDimitry Andric void emitRemarks(const MachineFunction &MF, 184*62987288SDimitry Andric MachineOptimizationRemarkEmitter *ORE) const override; 1850b57cec5SDimitry Andric }; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric } // End llvm namespace 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric #endif 190