xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
1  //=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=//
2  
3  //
4  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5  // See https://llvm.org/LICENSE.txt for license information.
6  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7  //
8  //===----------------------------------------------------------------------===//
9  ///
10  /// \file
11  /// This file implements AArch64-specific per-machine-function
12  /// information.
13  ///
14  //===----------------------------------------------------------------------===//
15  
16  #include "AArch64MachineFunctionInfo.h"
17  #include "AArch64InstrInfo.h"
18  #include "AArch64Subtarget.h"
19  #include "llvm/IR/Constants.h"
20  #include "llvm/IR/Metadata.h"
21  #include "llvm/IR/Module.h"
22  #include "llvm/MC/MCAsmInfo.h"
23  
24  using namespace llvm;
25  
AArch64FunctionInfo(const llvm::AArch64FunctionInfo & MFI)26  yaml::AArch64FunctionInfo::AArch64FunctionInfo(
27      const llvm::AArch64FunctionInfo &MFI)
28      : HasRedZone(MFI.hasRedZone()) {}
29  
mappingImpl(yaml::IO & YamlIO)30  void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) {
31    MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this);
32  }
33  
initializeBaseYamlFields(const yaml::AArch64FunctionInfo & YamlMFI)34  void AArch64FunctionInfo::initializeBaseYamlFields(
35      const yaml::AArch64FunctionInfo &YamlMFI) {
36    if (YamlMFI.HasRedZone)
37      HasRedZone = YamlMFI.HasRedZone;
38  }
39  
GetSignReturnAddress(const Function & F)40  static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
41    if (F.hasFnAttribute("ptrauth-returns"))
42      return {true, false}; // non-leaf
43    // The function should be signed in the following situations:
44    // - sign-return-address=all
45    // - sign-return-address=non-leaf and the functions spills the LR
46    if (!F.hasFnAttribute("sign-return-address"))
47      return {false, false};
48  
49    StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
50    if (Scope == "none")
51      return {false, false};
52  
53    if (Scope == "all")
54      return {true, true};
55  
56    assert(Scope == "non-leaf");
57    return {true, false};
58  }
59  
ShouldSignWithBKey(const Function & F,const AArch64Subtarget & STI)60  static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
61    if (F.hasFnAttribute("ptrauth-returns"))
62      return true;
63    if (!F.hasFnAttribute("sign-return-address-key")) {
64      if (STI.getTargetTriple().isOSWindows())
65        return true;
66      return false;
67    }
68  
69    const StringRef Key =
70        F.getFnAttribute("sign-return-address-key").getValueAsString();
71    assert(Key == "a_key" || Key == "b_key");
72    return Key == "b_key";
73  }
74  
AArch64FunctionInfo(const Function & F,const AArch64Subtarget * STI)75  AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
76                                           const AArch64Subtarget *STI) {
77    // If we already know that the function doesn't have a redzone, set
78    // HasRedZone here.
79    if (F.hasFnAttribute(Attribute::NoRedZone))
80      HasRedZone = false;
81    std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
82    SignWithBKey = ShouldSignWithBKey(F, *STI);
83    // TODO: skip functions that have no instrumented allocas for optimization
84    IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);
85  
86    // BTI/PAuthLR are set on the function attribute.
87    BranchTargetEnforcement = F.hasFnAttribute("branch-target-enforcement");
88    BranchProtectionPAuthLR = F.hasFnAttribute("branch-protection-pauth-lr");
89  
90    // The default stack probe size is 4096 if the function has no
91    // stack-probe-size attribute. This is a safe default because it is the
92    // smallest possible guard page size.
93    uint64_t ProbeSize = 4096;
94    if (F.hasFnAttribute("stack-probe-size"))
95      ProbeSize = F.getFnAttributeAsParsedInteger("stack-probe-size");
96    else if (const auto *PS = mdconst::extract_or_null<ConstantInt>(
97                 F.getParent()->getModuleFlag("stack-probe-size")))
98      ProbeSize = PS->getZExtValue();
99    assert(int64_t(ProbeSize) > 0 && "Invalid stack probe size");
100  
101    if (STI->isTargetWindows()) {
102      if (!F.hasFnAttribute("no-stack-arg-probe"))
103        StackProbeSize = ProbeSize;
104    } else {
105      // Round down to the stack alignment.
106      uint64_t StackAlign =
107          STI->getFrameLowering()->getTransientStackAlign().value();
108      ProbeSize = std::max(StackAlign, ProbeSize & ~(StackAlign - 1U));
109      StringRef ProbeKind;
110      if (F.hasFnAttribute("probe-stack"))
111        ProbeKind = F.getFnAttribute("probe-stack").getValueAsString();
112      else if (const auto *PS = dyn_cast_or_null<MDString>(
113                   F.getParent()->getModuleFlag("probe-stack")))
114        ProbeKind = PS->getString();
115      if (ProbeKind.size()) {
116        if (ProbeKind != "inline-asm")
117          report_fatal_error("Unsupported stack probing method");
118        StackProbeSize = ProbeSize;
119      }
120    }
121  }
122  
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const123  MachineFunctionInfo *AArch64FunctionInfo::clone(
124      BumpPtrAllocator &Allocator, MachineFunction &DestMF,
125      const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
126      const {
127    return DestMF.cloneInfo<AArch64FunctionInfo>(*this);
128  }
129  
shouldSignReturnAddress(bool SpillsLR) const130  bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {
131    if (!SignReturnAddress)
132      return false;
133    if (SignReturnAddressAll)
134      return true;
135    return SpillsLR;
136  }
137  
isLRSpilled(const MachineFunction & MF)138  static bool isLRSpilled(const MachineFunction &MF) {
139    return llvm::any_of(
140        MF.getFrameInfo().getCalleeSavedInfo(),
141        [](const auto &Info) { return Info.getReg() == AArch64::LR; });
142  }
143  
shouldSignReturnAddress(const MachineFunction & MF) const144  bool AArch64FunctionInfo::shouldSignReturnAddress(
145      const MachineFunction &MF) const {
146    return shouldSignReturnAddress(isLRSpilled(MF));
147  }
148  
needsShadowCallStackPrologueEpilogue(MachineFunction & MF) const149  bool AArch64FunctionInfo::needsShadowCallStackPrologueEpilogue(
150      MachineFunction &MF) const {
151    if (!(isLRSpilled(MF) &&
152          MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)))
153      return false;
154  
155    if (!MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(18))
156      report_fatal_error("Must reserve x18 to use shadow call stack");
157  
158    return true;
159  }
160  
needsDwarfUnwindInfo(const MachineFunction & MF) const161  bool AArch64FunctionInfo::needsDwarfUnwindInfo(
162      const MachineFunction &MF) const {
163    if (!NeedsDwarfUnwindInfo)
164      NeedsDwarfUnwindInfo = MF.needsFrameMoves() &&
165                             !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
166  
167    return *NeedsDwarfUnwindInfo;
168  }
169  
needsAsyncDwarfUnwindInfo(const MachineFunction & MF) const170  bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo(
171      const MachineFunction &MF) const {
172    if (!NeedsAsyncDwarfUnwindInfo) {
173      const Function &F = MF.getFunction();
174      const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
175      //  The check got "minsize" is because epilogue unwind info is not emitted
176      //  (yet) for homogeneous epilogues, outlined functions, and functions
177      //  outlined from.
178      NeedsAsyncDwarfUnwindInfo =
179          needsDwarfUnwindInfo(MF) &&
180          ((F.getUWTableKind() == UWTableKind::Async && !F.hasMinSize()) ||
181           AFI->hasStreamingModeChanges());
182    }
183    return *NeedsAsyncDwarfUnwindInfo;
184  }
185