Path: blob/main/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
35267 views
//=- AArch64MachineFunctionInfo.h - AArch64 machine function info -*- C++ -*-=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file declares AArch64-specific per-machine-function information.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H13#define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H1415#include "AArch64Subtarget.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/SmallPtrSet.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/CodeGen/CallingConvLower.h"20#include "llvm/CodeGen/MIRYamlMapping.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineFunction.h"23#include "llvm/IR/Function.h"24#include "llvm/MC/MCLinkerOptimizationHint.h"25#include "llvm/MC/MCSymbol.h"26#include <cassert>27#include <optional>2829namespace llvm {3031namespace yaml {32struct AArch64FunctionInfo;33} // end namespace yaml3435class AArch64Subtarget;36class MachineInstr;3738struct TPIDR2Object {39int FrameIndex = std::numeric_limits<int>::max();40unsigned Uses = 0;41};4243/// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and44/// contains private AArch64-specific information for each MachineFunction.45class AArch64FunctionInfo final : public MachineFunctionInfo {46/// Number of bytes of arguments this function has on the stack. If the callee47/// is expected to restore the argument stack this should be a multiple of 16,48/// all usable during a tail call.49///50/// The alternative would forbid tail call optimisation in some cases: if we51/// want to transfer control from a function with 8-bytes of stack-argument52/// space to a function with 16-bytes then misalignment of this value would53/// make a stack adjustment necessary, which could not be undone by the54/// callee.55unsigned BytesInStackArgArea = 0;5657/// The number of bytes to restore to deallocate space for incoming58/// arguments. Canonically 0 in the C calling convention, but non-zero when59/// callee is expected to pop the args.60unsigned ArgumentStackToRestore = 0;6162/// Space just below incoming stack pointer reserved for arguments being63/// passed on the stack during a tail call. This will be the difference64/// between the largest tail call argument space needed in this function and65/// what's already available by reusing space of incoming arguments.66unsigned TailCallReservedStack = 0;6768/// HasStackFrame - True if this function has a stack frame. Set by69/// determineCalleeSaves().70bool HasStackFrame = false;7172/// Amount of stack frame size, not including callee-saved registers.73uint64_t LocalStackSize = 0;7475/// The start and end frame indices for the SVE callee saves.76int MinSVECSFrameIndex = 0;77int MaxSVECSFrameIndex = 0;7879/// Amount of stack frame size used for saving callee-saved registers.80unsigned CalleeSavedStackSize = 0;81unsigned SVECalleeSavedStackSize = 0;82bool HasCalleeSavedStackSize = false;8384/// Number of TLS accesses using the special (combinable)85/// _TLS_MODULE_BASE_ symbol.86unsigned NumLocalDynamicTLSAccesses = 0;8788/// FrameIndex for start of varargs area for arguments passed on the89/// stack.90int VarArgsStackIndex = 0;9192/// Offset of start of varargs area for arguments passed on the stack.93unsigned VarArgsStackOffset = 0;9495/// FrameIndex for start of varargs area for arguments passed in96/// general purpose registers.97int VarArgsGPRIndex = 0;9899/// Size of the varargs area for arguments passed in general purpose100/// registers.101unsigned VarArgsGPRSize = 0;102103/// FrameIndex for start of varargs area for arguments passed in104/// floating-point registers.105int VarArgsFPRIndex = 0;106107/// Size of the varargs area for arguments passed in floating-point108/// registers.109unsigned VarArgsFPRSize = 0;110111/// The stack slots used to add space between FPR and GPR accesses when using112/// hazard padding. StackHazardCSRSlotIndex is added between GPR and FPR CSRs.113/// StackHazardSlotIndex is added between (sorted) stack objects.114int StackHazardSlotIndex = std::numeric_limits<int>::max();115int StackHazardCSRSlotIndex = std::numeric_limits<int>::max();116117/// True if this function has a subset of CSRs that is handled explicitly via118/// copies.119bool IsSplitCSR = false;120121/// True when the stack gets realigned dynamically because the size of stack122/// frame is unknown at compile time. e.g., in case of VLAs.123bool StackRealigned = false;124125/// True when the callee-save stack area has unused gaps that may be used for126/// other stack allocations.127bool CalleeSaveStackHasFreeSpace = false;128129/// SRetReturnReg - sret lowering includes returning the value of the130/// returned struct in a register. This field holds the virtual register into131/// which the sret argument is passed.132Register SRetReturnReg;133134/// SVE stack size (for predicates and data vectors) are maintained here135/// rather than in FrameInfo, as the placement and Stack IDs are target136/// specific.137uint64_t StackSizeSVE = 0;138139/// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid.140bool HasCalculatedStackSizeSVE = false;141142/// Has a value when it is known whether or not the function uses a143/// redzone, and no value otherwise.144/// Initialized during frame lowering, unless the function has the noredzone145/// attribute, in which case it is set to false at construction.146std::optional<bool> HasRedZone;147148/// ForwardedMustTailRegParms - A list of virtual and physical registers149/// that must be forwarded to every musttail call.150SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms;151152/// FrameIndex for the tagged base pointer.153std::optional<int> TaggedBasePointerIndex;154155/// Offset from SP-at-entry to the tagged base pointer.156/// Tagged base pointer is set up to point to the first (lowest address)157/// tagged stack slot.158unsigned TaggedBasePointerOffset;159160/// OutliningStyle denotes, if a function was outined, how it was outlined,161/// e.g. Tail Call, Thunk, or Function if none apply.162std::optional<std::string> OutliningStyle;163164// Offset from SP-after-callee-saved-spills (i.e. SP-at-entry minus165// CalleeSavedStackSize) to the address of the frame record.166int CalleeSaveBaseToFrameRecordOffset = 0;167168/// SignReturnAddress is true if PAC-RET is enabled for the function with169/// defaults being sign non-leaf functions only, with the B key.170bool SignReturnAddress = false;171172/// SignReturnAddressAll modifies the default PAC-RET mode to signing leaf173/// functions as well.174bool SignReturnAddressAll = false;175176/// SignWithBKey modifies the default PAC-RET mode to signing with the B key.177bool SignWithBKey = false;178179/// SigningInstrOffset captures the offset of the PAC-RET signing instruction180/// within the prologue, so it can be re-used for authentication in the181/// epilogue when using PC as a second salt (FEAT_PAuth_LR)182MCSymbol *SignInstrLabel = nullptr;183184/// BranchTargetEnforcement enables placing BTI instructions at potential185/// indirect branch destinations.186bool BranchTargetEnforcement = false;187188/// Indicates that SP signing should be diversified with PC as-per PAuthLR.189/// This is set by -mbranch-protection and will emit NOP instructions unless190/// the subtarget feature +pauthlr is also used (in which case non-NOP191/// instructions are emitted).192bool BranchProtectionPAuthLR = false;193194/// Whether this function has an extended frame record [Ctx, FP, LR]. If so,195/// bit 60 of the in-memory FP will be 1 to enable other tools to detect the196/// extended record.197bool HasSwiftAsyncContext = false;198199/// The stack slot where the Swift asynchronous context is stored.200int SwiftAsyncContextFrameIdx = std::numeric_limits<int>::max();201202bool IsMTETagged = false;203204/// The function has Scalable Vector or Scalable Predicate register argument205/// or return type206bool IsSVECC = false;207208/// The frame-index for the TPIDR2 object used for lazy saves.209TPIDR2Object TPIDR2;210211/// Whether this function changes streaming mode within the function.212bool HasStreamingModeChanges = false;213214/// True if the function need unwind information.215mutable std::optional<bool> NeedsDwarfUnwindInfo;216217/// True if the function need asynchronous unwind information.218mutable std::optional<bool> NeedsAsyncDwarfUnwindInfo;219220int64_t StackProbeSize = 0;221222// Holds a register containing pstate.sm. This is set223// on function entry to record the initial pstate of a function.224Register PStateSMReg = MCRegister::NoRegister;225226// Has the PNReg used to build PTRUE instruction.227// The PTRUE is used for the LD/ST of ZReg pairs in save and restore.228unsigned PredicateRegForFillSpill = 0;229230// The stack slots where VG values are stored to.231int64_t VGIdx = std::numeric_limits<int>::max();232int64_t StreamingVGIdx = std::numeric_limits<int>::max();233234public:235AArch64FunctionInfo(const Function &F, const AArch64Subtarget *STI);236237MachineFunctionInfo *238clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,239const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)240const override;241242void setPredicateRegForFillSpill(unsigned Reg) {243PredicateRegForFillSpill = Reg;244}245unsigned getPredicateRegForFillSpill() const {246return PredicateRegForFillSpill;247}248249Register getPStateSMReg() const { return PStateSMReg; };250void setPStateSMReg(Register Reg) { PStateSMReg = Reg; };251252int64_t getVGIdx() const { return VGIdx; };253void setVGIdx(unsigned Idx) { VGIdx = Idx; };254255int64_t getStreamingVGIdx() const { return StreamingVGIdx; };256void setStreamingVGIdx(unsigned FrameIdx) { StreamingVGIdx = FrameIdx; };257258bool isSVECC() const { return IsSVECC; };259void setIsSVECC(bool s) { IsSVECC = s; };260261TPIDR2Object &getTPIDR2Obj() { return TPIDR2; }262263void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI);264265unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; }266void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; }267268unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; }269void setArgumentStackToRestore(unsigned bytes) {270ArgumentStackToRestore = bytes;271}272273unsigned getTailCallReservedStack() const { return TailCallReservedStack; }274void setTailCallReservedStack(unsigned bytes) {275TailCallReservedStack = bytes;276}277278bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; }279280void setStackSizeSVE(uint64_t S) {281HasCalculatedStackSizeSVE = true;282StackSizeSVE = S;283}284285uint64_t getStackSizeSVE() const { return StackSizeSVE; }286287bool hasStackFrame() const { return HasStackFrame; }288void setHasStackFrame(bool s) { HasStackFrame = s; }289290bool isStackRealigned() const { return StackRealigned; }291void setStackRealigned(bool s) { StackRealigned = s; }292293bool hasCalleeSaveStackFreeSpace() const {294return CalleeSaveStackHasFreeSpace;295}296void setCalleeSaveStackHasFreeSpace(bool s) {297CalleeSaveStackHasFreeSpace = s;298}299bool isSplitCSR() const { return IsSplitCSR; }300void setIsSplitCSR(bool s) { IsSplitCSR = s; }301302void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; }303uint64_t getLocalStackSize() const { return LocalStackSize; }304305void setOutliningStyle(std::string Style) { OutliningStyle = Style; }306std::optional<std::string> getOutliningStyle() const {307return OutliningStyle;308}309310void setCalleeSavedStackSize(unsigned Size) {311CalleeSavedStackSize = Size;312HasCalleeSavedStackSize = true;313}314315// When CalleeSavedStackSize has not been set (for example when316// some MachineIR pass is run in isolation), then recalculate317// the CalleeSavedStackSize directly from the CalleeSavedInfo.318// Note: This information can only be recalculated after PEI319// has assigned offsets to the callee save objects.320unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const {321bool ValidateCalleeSavedStackSize = false;322323#ifndef NDEBUG324// Make sure the calculated size derived from the CalleeSavedInfo325// equals the cached size that was calculated elsewhere (e.g. in326// determineCalleeSaves).327ValidateCalleeSavedStackSize = HasCalleeSavedStackSize;328#endif329330if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) {331assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated");332if (MFI.getCalleeSavedInfo().empty())333return 0;334335int64_t MinOffset = std::numeric_limits<int64_t>::max();336int64_t MaxOffset = std::numeric_limits<int64_t>::min();337for (const auto &Info : MFI.getCalleeSavedInfo()) {338int FrameIdx = Info.getFrameIdx();339if (MFI.getStackID(FrameIdx) != TargetStackID::Default)340continue;341int64_t Offset = MFI.getObjectOffset(FrameIdx);342int64_t ObjSize = MFI.getObjectSize(FrameIdx);343MinOffset = std::min<int64_t>(Offset, MinOffset);344MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset);345}346347if (SwiftAsyncContextFrameIdx != std::numeric_limits<int>::max()) {348int64_t Offset = MFI.getObjectOffset(getSwiftAsyncContextFrameIdx());349int64_t ObjSize = MFI.getObjectSize(getSwiftAsyncContextFrameIdx());350MinOffset = std::min<int64_t>(Offset, MinOffset);351MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset);352}353354if (StackHazardCSRSlotIndex != std::numeric_limits<int>::max()) {355int64_t Offset = MFI.getObjectOffset(StackHazardCSRSlotIndex);356int64_t ObjSize = MFI.getObjectSize(StackHazardCSRSlotIndex);357MinOffset = std::min<int64_t>(Offset, MinOffset);358MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset);359}360361unsigned Size = alignTo(MaxOffset - MinOffset, 16);362assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) &&363"Invalid size calculated for callee saves");364return Size;365}366367return getCalleeSavedStackSize();368}369370unsigned getCalleeSavedStackSize() const {371assert(HasCalleeSavedStackSize &&372"CalleeSavedStackSize has not been calculated");373return CalleeSavedStackSize;374}375376// Saves the CalleeSavedStackSize for SVE vectors in 'scalable bytes'377void setSVECalleeSavedStackSize(unsigned Size) {378SVECalleeSavedStackSize = Size;379}380unsigned getSVECalleeSavedStackSize() const {381return SVECalleeSavedStackSize;382}383384void setMinMaxSVECSFrameIndex(int Min, int Max) {385MinSVECSFrameIndex = Min;386MaxSVECSFrameIndex = Max;387}388389int getMinSVECSFrameIndex() const { return MinSVECSFrameIndex; }390int getMaxSVECSFrameIndex() const { return MaxSVECSFrameIndex; }391392void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; }393unsigned getNumLocalDynamicTLSAccesses() const {394return NumLocalDynamicTLSAccesses;395}396397std::optional<bool> hasRedZone() const { return HasRedZone; }398void setHasRedZone(bool s) { HasRedZone = s; }399400int getVarArgsStackIndex() const { return VarArgsStackIndex; }401void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; }402403unsigned getVarArgsStackOffset() const { return VarArgsStackOffset; }404void setVarArgsStackOffset(unsigned Offset) { VarArgsStackOffset = Offset; }405406int getVarArgsGPRIndex() const { return VarArgsGPRIndex; }407void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; }408409unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; }410void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; }411412int getVarArgsFPRIndex() const { return VarArgsFPRIndex; }413void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; }414415unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; }416void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; }417418bool hasStackHazardSlotIndex() const {419return StackHazardSlotIndex != std::numeric_limits<int>::max();420}421int getStackHazardSlotIndex() const { return StackHazardSlotIndex; }422void setStackHazardSlotIndex(int Index) {423assert(StackHazardSlotIndex == std::numeric_limits<int>::max());424StackHazardSlotIndex = Index;425}426int getStackHazardCSRSlotIndex() const { return StackHazardCSRSlotIndex; }427void setStackHazardCSRSlotIndex(int Index) {428assert(StackHazardCSRSlotIndex == std::numeric_limits<int>::max());429StackHazardCSRSlotIndex = Index;430}431432unsigned getSRetReturnReg() const { return SRetReturnReg; }433void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }434435unsigned getJumpTableEntrySize(int Idx) const {436return JumpTableEntryInfo[Idx].first;437}438MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const {439return JumpTableEntryInfo[Idx].second;440}441void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) {442if ((unsigned)Idx >= JumpTableEntryInfo.size())443JumpTableEntryInfo.resize(Idx+1);444JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym);445}446447using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>;448449const SetOfInstructions &getLOHRelated() const { return LOHRelated; }450451// Shortcuts for LOH related types.452class MILOHDirective {453MCLOHType Kind;454455/// Arguments of this directive. Order matters.456SmallVector<const MachineInstr *, 3> Args;457458public:459using LOHArgs = ArrayRef<const MachineInstr *>;460461MILOHDirective(MCLOHType Kind, LOHArgs Args)462: Kind(Kind), Args(Args.begin(), Args.end()) {463assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");464}465466MCLOHType getKind() const { return Kind; }467LOHArgs getArgs() const { return Args; }468};469470using MILOHArgs = MILOHDirective::LOHArgs;471using MILOHContainer = SmallVector<MILOHDirective, 32>;472473const MILOHContainer &getLOHContainer() const { return LOHContainerSet; }474475/// Add a LOH directive of this @p Kind and this @p Args.476void addLOHDirective(MCLOHType Kind, MILOHArgs Args) {477LOHContainerSet.push_back(MILOHDirective(Kind, Args));478LOHRelated.insert(Args.begin(), Args.end());479}480481SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() {482return ForwardedMustTailRegParms;483}484485std::optional<int> getTaggedBasePointerIndex() const {486return TaggedBasePointerIndex;487}488void setTaggedBasePointerIndex(int Index) { TaggedBasePointerIndex = Index; }489490unsigned getTaggedBasePointerOffset() const {491return TaggedBasePointerOffset;492}493void setTaggedBasePointerOffset(unsigned Offset) {494TaggedBasePointerOffset = Offset;495}496497int getCalleeSaveBaseToFrameRecordOffset() const {498return CalleeSaveBaseToFrameRecordOffset;499}500void setCalleeSaveBaseToFrameRecordOffset(int Offset) {501CalleeSaveBaseToFrameRecordOffset = Offset;502}503504bool shouldSignReturnAddress(const MachineFunction &MF) const;505bool shouldSignReturnAddress(bool SpillsLR) const;506507bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const;508509bool shouldSignWithBKey() const { return SignWithBKey; }510511MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; }512void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; }513514bool isMTETagged() const { return IsMTETagged; }515516bool branchTargetEnforcement() const { return BranchTargetEnforcement; }517518bool branchProtectionPAuthLR() const { return BranchProtectionPAuthLR; }519520void setHasSwiftAsyncContext(bool HasContext) {521HasSwiftAsyncContext = HasContext;522}523bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; }524525void setSwiftAsyncContextFrameIdx(int FI) {526SwiftAsyncContextFrameIdx = FI;527}528int getSwiftAsyncContextFrameIdx() const { return SwiftAsyncContextFrameIdx; }529530bool needsDwarfUnwindInfo(const MachineFunction &MF) const;531bool needsAsyncDwarfUnwindInfo(const MachineFunction &MF) const;532533bool hasStreamingModeChanges() const { return HasStreamingModeChanges; }534void setHasStreamingModeChanges(bool HasChanges) {535HasStreamingModeChanges = HasChanges;536}537538bool hasStackProbing() const { return StackProbeSize != 0; }539540int64_t getStackProbeSize() const { return StackProbeSize; }541542private:543// Hold the lists of LOHs.544MILOHContainer LOHContainerSet;545SetOfInstructions LOHRelated;546547SmallVector<std::pair<unsigned, MCSymbol *>, 2> JumpTableEntryInfo;548};549550namespace yaml {551struct AArch64FunctionInfo final : public yaml::MachineFunctionInfo {552std::optional<bool> HasRedZone;553554AArch64FunctionInfo() = default;555AArch64FunctionInfo(const llvm::AArch64FunctionInfo &MFI);556557void mappingImpl(yaml::IO &YamlIO) override;558~AArch64FunctionInfo() = default;559};560561template <> struct MappingTraits<AArch64FunctionInfo> {562static void mapping(IO &YamlIO, AArch64FunctionInfo &MFI) {563YamlIO.mapOptional("hasRedZone", MFI.HasRedZone);564}565};566567} // end namespace yaml568569} // end namespace llvm570571#endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H572573574