213 lines · c
1//===----------------------------------------------------------------------===//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/// \file10/// This file contains the declaration of the AArch64PrologueEmitter and11/// AArch64EpilogueEmitter classes, which are is used to emit the prologue and12/// epilogue on AArch64.13///14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64PROLOGUEEPILOGUE_H17#define LLVM_LIB_TARGET_AARCH64_AARCH64PROLOGUEEPILOGUE_H18 19#include "AArch64RegisterInfo.h"20#include "llvm/CodeGen/LivePhysRegs.h"21#include "llvm/CodeGen/MachineFunction.h"22 23namespace llvm {24 25class TargetLowering;26class AArch64Subtarget;27class AArch64FunctionInfo;28class AArch64FrameLowering;29 30struct SVEFrameSizes {31 struct {32 StackOffset CalleeSavesSize, LocalsSize;33 } PPR, ZPR;34};35 36struct SVEStackAllocations {37 StackOffset BeforePPRs, AfterPPRs, AfterZPRs;38 StackOffset totalSize() const { return BeforePPRs + AfterPPRs + AfterZPRs; }39};40 41class AArch64PrologueEpilogueCommon {42public:43 AArch64PrologueEpilogueCommon(MachineFunction &MF, MachineBasicBlock &MBB,44 const AArch64FrameLowering &AFL);45 46 enum class SVEStackLayout {47 Default,48 Split,49 CalleeSavesAboveFrameRecord,50 };51 52protected:53 bool requiresGetVGCall() const;54 55 bool isVGInstruction(MachineBasicBlock::iterator MBBI,56 const TargetLowering &TLI) const;57 58 // Convert callee-save register save/restore instruction to do stack pointer59 // decrement/increment to allocate/deallocate the callee-save stack area by60 // converting store/load to use pre/post increment version.61 MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec(62 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int CSStackSizeInc,63 bool EmitCFI, MachineInstr::MIFlag FrameFlag = MachineInstr::FrameSetup,64 int CFAOffset = 0) const;65 66 // Fixup callee-save register save/restore instructions to take into account67 // combined SP bump by adding the local stack size to the stack offsets.68 void fixupCalleeSaveRestoreStackOffset(MachineInstr &MI,69 uint64_t LocalStackSize) const;70 71 bool shouldCombineCSRLocalStackBump(uint64_t StackBumpBytes) const;72 73 SVEFrameSizes getSVEStackFrameSizes() const;74 SVEStackAllocations getSVEStackAllocations(SVEFrameSizes const &);75 76 MachineFunction &MF;77 MachineBasicBlock &MBB;78 79 const MachineFrameInfo &MFI;80 const AArch64Subtarget &Subtarget;81 const AArch64FrameLowering &AFL;82 const AArch64RegisterInfo &RegInfo;83 84 // Common flags. These generally should not change outside of the (possibly85 // derived) constructor.86 bool HasFP = false;87 bool EmitCFI = false; // Note: Set in derived constructors.88 bool IsFunclet = false; // Note: Set in derived constructors.89 bool NeedsWinCFI = false; // Note: Can be changed in emitFramePointerSetup.90 bool HomPrologEpilog = false; // Note: Set in derived constructors.91 SVEStackLayout SVELayout = SVEStackLayout::Default;92 93 // Note: "HasWinCFI" is mutable as it can change in any "emit" function.94 mutable bool HasWinCFI = false;95 96 const TargetInstrInfo *TII = nullptr;97 AArch64FunctionInfo *AFI = nullptr;98};99 100/// A helper class for emitting the prologue. Substantial new functionality101/// should be factored into a new method. Where possible "emit*" methods should102/// be const, and any flags that change how the prologue is emitted should be103/// set in the constructor.104class AArch64PrologueEmitter final : public AArch64PrologueEpilogueCommon {105public:106 AArch64PrologueEmitter(MachineFunction &MF, MachineBasicBlock &MBB,107 const AArch64FrameLowering &AFL);108 109 /// Emit the prologue.110 void emitPrologue();111 112 ~AArch64PrologueEmitter() {113 MF.setHasWinCFI(HasWinCFI);114#ifndef NDEBUG115 verifyPrologueClobbers();116#endif117 }118 119private:120 void allocateStackSpace(MachineBasicBlock::iterator MBBI,121 int64_t RealignmentPadding, StackOffset AllocSize,122 bool EmitCFI, StackOffset InitialOffset,123 bool FollowupAllocs);124 125 void emitShadowCallStackPrologue(MachineBasicBlock::iterator MBBI,126 const DebugLoc &DL) const;127 128 void emitSwiftAsyncContextFramePointer(MachineBasicBlock::iterator MBBI,129 const DebugLoc &DL) const;130 131 void emitEmptyStackFramePrologue(int64_t NumBytes,132 MachineBasicBlock::iterator MBBI,133 const DebugLoc &DL) const;134 135 void emitFramePointerSetup(MachineBasicBlock::iterator MBBI,136 const DebugLoc &DL, unsigned FixedObject);137 138 void emitDefineCFAWithFP(MachineBasicBlock::iterator MBBI,139 unsigned FixedObject) const;140 141 void emitWindowsStackProbe(MachineBasicBlock::iterator MBBI,142 const DebugLoc &DL, int64_t &NumBytes,143 int64_t RealignmentPadding) const;144 145 void emitCalleeSavedGPRLocations(MachineBasicBlock::iterator MBBI) const;146 void emitCalleeSavedSVELocations(MachineBasicBlock::iterator MBBI) const;147 148 void determineLocalsStackSize(uint64_t StackSize, uint64_t PrologueSaveSize);149 150 const Function &F;151 152#ifndef NDEBUG153 mutable LivePhysRegs LiveRegs{RegInfo};154 MachineBasicBlock::iterator PrologueEndI;155 156 void collectBlockLiveins();157 void verifyPrologueClobbers() const;158#endif159 160 // Prologue flags. These generally should not change outside of the161 // constructor.162 bool EmitAsyncCFI = false;163 bool CombineSPBump = false; // Note: This is set in determineLocalsStackSize.164};165 166/// A helper class for emitting the epilogue. Substantial new functionality167/// should be factored into a new method. Where possible "emit*" methods should168/// be const, and any flags that change how the epilogue is emitted should be169/// set in the constructor.170class AArch64EpilogueEmitter final : public AArch64PrologueEpilogueCommon {171public:172 AArch64EpilogueEmitter(MachineFunction &MF, MachineBasicBlock &MBB,173 const AArch64FrameLowering &AFL);174 175 /// Emit the epilogue.176 void emitEpilogue();177 178 ~AArch64EpilogueEmitter() { finalizeEpilogue(); }179 180private:181 bool shouldCombineCSRLocalStackBump(uint64_t StackBumpBytes) const;182 183 /// A helper for moving the SP to a negative offset from the FP, without184 /// deallocating any stack in the range FP to FP + Offset.185 void moveSPBelowFP(MachineBasicBlock::iterator MBBI, StackOffset Offset);186 187 void emitSwiftAsyncContextFramePointer(MachineBasicBlock::iterator MBBI,188 const DebugLoc &DL) const;189 190 void emitShadowCallStackEpilogue(MachineBasicBlock::iterator MBBI,191 const DebugLoc &DL) const;192 193 void emitCalleeSavedRestores(MachineBasicBlock::iterator MBBI,194 bool SVE) const;195 196 void emitCalleeSavedGPRRestores(MachineBasicBlock::iterator MBBI) const {197 emitCalleeSavedRestores(MBBI, /*SVE=*/false);198 }199 200 void emitCalleeSavedSVERestores(MachineBasicBlock::iterator MBBI) const {201 emitCalleeSavedRestores(MBBI, /*SVE=*/true);202 }203 204 void finalizeEpilogue() const;205 206 MachineBasicBlock::iterator SEHEpilogueStartI;207 DebugLoc DL;208};209 210} // namespace llvm211 212#endif213