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