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 "llvm/MC/MCAsmInfo.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Metadata.h"
21 #include "llvm/IR/Module.h"
22 
23 using namespace llvm;
24 
25 yaml::AArch64FunctionInfo::AArch64FunctionInfo(
26     const llvm::AArch64FunctionInfo &MFI)
27     : HasRedZone(MFI.hasRedZone()) {}
28 
29 void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) {
30   MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this);
31 }
32 
33 void AArch64FunctionInfo::initializeBaseYamlFields(
34     const yaml::AArch64FunctionInfo &YamlMFI) {
35   if (YamlMFI.HasRedZone.hasValue())
36     HasRedZone = YamlMFI.HasRedZone;
37 }
38 
39 static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
40   // The function should be signed in the following situations:
41   // - sign-return-address=all
42   // - sign-return-address=non-leaf and the functions spills the LR
43   if (!F.hasFnAttribute("sign-return-address")) {
44     const Module &M = *F.getParent();
45     if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
46             M.getModuleFlag("sign-return-address"))) {
47       if (Sign->getZExtValue()) {
48         if (const auto *All = mdconst::extract_or_null<ConstantInt>(
49                 M.getModuleFlag("sign-return-address-all")))
50           return {true, All->getZExtValue()};
51         return {true, false};
52       }
53     }
54     return {false, false};
55   }
56 
57   StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
58   if (Scope.equals("none"))
59     return {false, false};
60 
61   if (Scope.equals("all"))
62     return {true, true};
63 
64   assert(Scope.equals("non-leaf"));
65   return {true, false};
66 }
67 
68 static bool ShouldSignWithBKey(const Function &F) {
69   if (!F.hasFnAttribute("sign-return-address-key")) {
70     if (const auto *BKey = mdconst::extract_or_null<ConstantInt>(
71             F.getParent()->getModuleFlag("sign-return-address-with-bkey")))
72       return BKey->getZExtValue();
73     return false;
74   }
75 
76   const StringRef Key =
77       F.getFnAttribute("sign-return-address-key").getValueAsString();
78   assert(Key.equals_insensitive("a_key") || Key.equals_insensitive("b_key"));
79   return Key.equals_insensitive("b_key");
80 }
81 
82 AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF) : MF(MF) {
83   // If we already know that the function doesn't have a redzone, set
84   // HasRedZone here.
85   if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone))
86     HasRedZone = false;
87 
88   const Function &F = MF.getFunction();
89   std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
90   SignWithBKey = ShouldSignWithBKey(F);
91 
92   if (!F.hasFnAttribute("branch-target-enforcement")) {
93     if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
94             F.getParent()->getModuleFlag("branch-target-enforcement")))
95       BranchTargetEnforcement = BTE->getZExtValue();
96     return;
97   }
98 
99   const StringRef BTIEnable =
100       F.getFnAttribute("branch-target-enforcement").getValueAsString();
101   assert(BTIEnable.equals_insensitive("true") ||
102          BTIEnable.equals_insensitive("false"));
103   BranchTargetEnforcement = BTIEnable.equals_insensitive("true");
104 }
105 
106 bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {
107   if (!SignReturnAddress)
108     return false;
109   if (SignReturnAddressAll)
110     return true;
111   return SpillsLR;
112 }
113 
114 bool AArch64FunctionInfo::shouldSignReturnAddress() const {
115   return shouldSignReturnAddress(llvm::any_of(
116       MF.getFrameInfo().getCalleeSavedInfo(),
117       [](const auto &Info) { return Info.getReg() == AArch64::LR; }));
118 }
119 
120 bool AArch64FunctionInfo::needsDwarfUnwindInfo() const {
121   if (!NeedsDwarfUnwindInfo.hasValue())
122     NeedsDwarfUnwindInfo = MF.needsFrameMoves() &&
123                            !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
124 
125   return NeedsDwarfUnwindInfo.getValue();
126 }
127 
128 bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo() const {
129   if (!NeedsDwarfAsyncUnwindInfo.hasValue())
130     NeedsDwarfAsyncUnwindInfo =
131         needsDwarfUnwindInfo() &&
132         MF.getFunction().getUWTableKind() == UWTableKind::Async;
133   return NeedsDwarfAsyncUnwindInfo.getValue();
134 }
135