Path: blob/main/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
35294 views
//=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=//12//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 implements AArch64-specific per-machine-function11/// information.12///13//===----------------------------------------------------------------------===//1415#include "AArch64MachineFunctionInfo.h"16#include "AArch64InstrInfo.h"17#include "AArch64Subtarget.h"18#include "llvm/IR/Constants.h"19#include "llvm/IR/Metadata.h"20#include "llvm/IR/Module.h"21#include "llvm/MC/MCAsmInfo.h"2223using namespace llvm;2425yaml::AArch64FunctionInfo::AArch64FunctionInfo(26const llvm::AArch64FunctionInfo &MFI)27: HasRedZone(MFI.hasRedZone()) {}2829void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) {30MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this);31}3233void AArch64FunctionInfo::initializeBaseYamlFields(34const yaml::AArch64FunctionInfo &YamlMFI) {35if (YamlMFI.HasRedZone)36HasRedZone = YamlMFI.HasRedZone;37}3839static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {40if (F.hasFnAttribute("ptrauth-returns"))41return {true, false}; // non-leaf42// The function should be signed in the following situations:43// - sign-return-address=all44// - sign-return-address=non-leaf and the functions spills the LR45if (!F.hasFnAttribute("sign-return-address"))46return {false, false};4748StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();49if (Scope == "none")50return {false, false};5152if (Scope == "all")53return {true, true};5455assert(Scope == "non-leaf");56return {true, false};57}5859static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {60if (F.hasFnAttribute("ptrauth-returns"))61return true;62if (!F.hasFnAttribute("sign-return-address-key")) {63if (STI.getTargetTriple().isOSWindows())64return true;65return false;66}6768const StringRef Key =69F.getFnAttribute("sign-return-address-key").getValueAsString();70assert(Key == "a_key" || Key == "b_key");71return Key == "b_key";72}7374AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,75const AArch64Subtarget *STI) {76// If we already know that the function doesn't have a redzone, set77// HasRedZone here.78if (F.hasFnAttribute(Attribute::NoRedZone))79HasRedZone = false;80std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);81SignWithBKey = ShouldSignWithBKey(F, *STI);82// TODO: skip functions that have no instrumented allocas for optimization83IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);8485// BTI/PAuthLR are set on the function attribute.86BranchTargetEnforcement = F.hasFnAttribute("branch-target-enforcement");87BranchProtectionPAuthLR = F.hasFnAttribute("branch-protection-pauth-lr");8889// The default stack probe size is 4096 if the function has no90// stack-probe-size attribute. This is a safe default because it is the91// smallest possible guard page size.92uint64_t ProbeSize = 4096;93if (F.hasFnAttribute("stack-probe-size"))94ProbeSize = F.getFnAttributeAsParsedInteger("stack-probe-size");95else if (const auto *PS = mdconst::extract_or_null<ConstantInt>(96F.getParent()->getModuleFlag("stack-probe-size")))97ProbeSize = PS->getZExtValue();98assert(int64_t(ProbeSize) > 0 && "Invalid stack probe size");99100if (STI->isTargetWindows()) {101if (!F.hasFnAttribute("no-stack-arg-probe"))102StackProbeSize = ProbeSize;103} else {104// Round down to the stack alignment.105uint64_t StackAlign =106STI->getFrameLowering()->getTransientStackAlign().value();107ProbeSize = std::max(StackAlign, ProbeSize & ~(StackAlign - 1U));108StringRef ProbeKind;109if (F.hasFnAttribute("probe-stack"))110ProbeKind = F.getFnAttribute("probe-stack").getValueAsString();111else if (const auto *PS = dyn_cast_or_null<MDString>(112F.getParent()->getModuleFlag("probe-stack")))113ProbeKind = PS->getString();114if (ProbeKind.size()) {115if (ProbeKind != "inline-asm")116report_fatal_error("Unsupported stack probing method");117StackProbeSize = ProbeSize;118}119}120}121122MachineFunctionInfo *AArch64FunctionInfo::clone(123BumpPtrAllocator &Allocator, MachineFunction &DestMF,124const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)125const {126return DestMF.cloneInfo<AArch64FunctionInfo>(*this);127}128129bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {130if (!SignReturnAddress)131return false;132if (SignReturnAddressAll)133return true;134return SpillsLR;135}136137static bool isLRSpilled(const MachineFunction &MF) {138return llvm::any_of(139MF.getFrameInfo().getCalleeSavedInfo(),140[](const auto &Info) { return Info.getReg() == AArch64::LR; });141}142143bool AArch64FunctionInfo::shouldSignReturnAddress(144const MachineFunction &MF) const {145return shouldSignReturnAddress(isLRSpilled(MF));146}147148bool AArch64FunctionInfo::needsShadowCallStackPrologueEpilogue(149MachineFunction &MF) const {150if (!(isLRSpilled(MF) &&151MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)))152return false;153154if (!MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(18))155report_fatal_error("Must reserve x18 to use shadow call stack");156157return true;158}159160bool AArch64FunctionInfo::needsDwarfUnwindInfo(161const MachineFunction &MF) const {162if (!NeedsDwarfUnwindInfo)163NeedsDwarfUnwindInfo = MF.needsFrameMoves() &&164!MF.getTarget().getMCAsmInfo()->usesWindowsCFI();165166return *NeedsDwarfUnwindInfo;167}168169bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo(170const MachineFunction &MF) const {171if (!NeedsAsyncDwarfUnwindInfo) {172const Function &F = MF.getFunction();173const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();174// The check got "minsize" is because epilogue unwind info is not emitted175// (yet) for homogeneous epilogues, outlined functions, and functions176// outlined from.177NeedsAsyncDwarfUnwindInfo =178needsDwarfUnwindInfo(MF) &&179((F.getUWTableKind() == UWTableKind::Async && !F.hasMinSize()) ||180AFI->hasStreamingModeChanges());181}182return *NeedsAsyncDwarfUnwindInfo;183}184185186