xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=//
25ffd83dbSDimitry Andric 
35ffd83dbSDimitry Andric //
45ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
55ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
65ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
75ffd83dbSDimitry Andric //
85ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
95ffd83dbSDimitry Andric ///
105ffd83dbSDimitry Andric /// \file
115ffd83dbSDimitry Andric /// This file implements AArch64-specific per-machine-function
125ffd83dbSDimitry Andric /// information.
135ffd83dbSDimitry Andric ///
145ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
155ffd83dbSDimitry Andric 
165ffd83dbSDimitry Andric #include "AArch64MachineFunctionInfo.h"
17*e8d8bef9SDimitry Andric #include "AArch64InstrInfo.h"
18*e8d8bef9SDimitry Andric #include <llvm/IR/Metadata.h>
19*e8d8bef9SDimitry Andric #include <llvm/IR/Module.h>
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric using namespace llvm;
225ffd83dbSDimitry Andric 
235ffd83dbSDimitry Andric yaml::AArch64FunctionInfo::AArch64FunctionInfo(
245ffd83dbSDimitry Andric     const llvm::AArch64FunctionInfo &MFI)
255ffd83dbSDimitry Andric     : HasRedZone(MFI.hasRedZone()) {}
265ffd83dbSDimitry Andric 
275ffd83dbSDimitry Andric void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) {
285ffd83dbSDimitry Andric   MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this);
295ffd83dbSDimitry Andric }
305ffd83dbSDimitry Andric 
315ffd83dbSDimitry Andric void AArch64FunctionInfo::initializeBaseYamlFields(
325ffd83dbSDimitry Andric     const yaml::AArch64FunctionInfo &YamlMFI) {
335ffd83dbSDimitry Andric   if (YamlMFI.HasRedZone.hasValue())
345ffd83dbSDimitry Andric     HasRedZone = YamlMFI.HasRedZone;
355ffd83dbSDimitry Andric }
36*e8d8bef9SDimitry Andric 
37*e8d8bef9SDimitry Andric static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
38*e8d8bef9SDimitry Andric   // The function should be signed in the following situations:
39*e8d8bef9SDimitry Andric   // - sign-return-address=all
40*e8d8bef9SDimitry Andric   // - sign-return-address=non-leaf and the functions spills the LR
41*e8d8bef9SDimitry Andric   if (!F.hasFnAttribute("sign-return-address")) {
42*e8d8bef9SDimitry Andric     const Module &M = *F.getParent();
43*e8d8bef9SDimitry Andric     if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
44*e8d8bef9SDimitry Andric             M.getModuleFlag("sign-return-address"))) {
45*e8d8bef9SDimitry Andric       if (Sign->getZExtValue()) {
46*e8d8bef9SDimitry Andric         if (const auto *All = mdconst::extract_or_null<ConstantInt>(
47*e8d8bef9SDimitry Andric                 M.getModuleFlag("sign-return-address-all")))
48*e8d8bef9SDimitry Andric           return {true, All->getZExtValue()};
49*e8d8bef9SDimitry Andric         return {true, false};
50*e8d8bef9SDimitry Andric       }
51*e8d8bef9SDimitry Andric     }
52*e8d8bef9SDimitry Andric     return {false, false};
53*e8d8bef9SDimitry Andric   }
54*e8d8bef9SDimitry Andric 
55*e8d8bef9SDimitry Andric   StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
56*e8d8bef9SDimitry Andric   if (Scope.equals("none"))
57*e8d8bef9SDimitry Andric     return {false, false};
58*e8d8bef9SDimitry Andric 
59*e8d8bef9SDimitry Andric   if (Scope.equals("all"))
60*e8d8bef9SDimitry Andric     return {true, true};
61*e8d8bef9SDimitry Andric 
62*e8d8bef9SDimitry Andric   assert(Scope.equals("non-leaf"));
63*e8d8bef9SDimitry Andric   return {true, false};
64*e8d8bef9SDimitry Andric }
65*e8d8bef9SDimitry Andric 
66*e8d8bef9SDimitry Andric static bool ShouldSignWithBKey(const Function &F) {
67*e8d8bef9SDimitry Andric   if (!F.hasFnAttribute("sign-return-address-key")) {
68*e8d8bef9SDimitry Andric     if (const auto *BKey = mdconst::extract_or_null<ConstantInt>(
69*e8d8bef9SDimitry Andric             F.getParent()->getModuleFlag("sign-return-address-with-bkey")))
70*e8d8bef9SDimitry Andric       return BKey->getZExtValue();
71*e8d8bef9SDimitry Andric     return false;
72*e8d8bef9SDimitry Andric   }
73*e8d8bef9SDimitry Andric 
74*e8d8bef9SDimitry Andric   const StringRef Key =
75*e8d8bef9SDimitry Andric       F.getFnAttribute("sign-return-address-key").getValueAsString();
76*e8d8bef9SDimitry Andric   assert(Key.equals_lower("a_key") || Key.equals_lower("b_key"));
77*e8d8bef9SDimitry Andric   return Key.equals_lower("b_key");
78*e8d8bef9SDimitry Andric }
79*e8d8bef9SDimitry Andric 
80*e8d8bef9SDimitry Andric AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF) : MF(MF) {
81*e8d8bef9SDimitry Andric   // If we already know that the function doesn't have a redzone, set
82*e8d8bef9SDimitry Andric   // HasRedZone here.
83*e8d8bef9SDimitry Andric   if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone))
84*e8d8bef9SDimitry Andric     HasRedZone = false;
85*e8d8bef9SDimitry Andric 
86*e8d8bef9SDimitry Andric   const Function &F = MF.getFunction();
87*e8d8bef9SDimitry Andric   std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
88*e8d8bef9SDimitry Andric   SignWithBKey = ShouldSignWithBKey(F);
89*e8d8bef9SDimitry Andric 
90*e8d8bef9SDimitry Andric   if (!F.hasFnAttribute("branch-target-enforcement")) {
91*e8d8bef9SDimitry Andric     if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
92*e8d8bef9SDimitry Andric             F.getParent()->getModuleFlag("branch-target-enforcement")))
93*e8d8bef9SDimitry Andric       BranchTargetEnforcement = BTE->getZExtValue();
94*e8d8bef9SDimitry Andric     return;
95*e8d8bef9SDimitry Andric   }
96*e8d8bef9SDimitry Andric 
97*e8d8bef9SDimitry Andric   const StringRef BTIEnable = F.getFnAttribute("branch-target-enforcement").getValueAsString();
98*e8d8bef9SDimitry Andric   assert(BTIEnable.equals_lower("true") || BTIEnable.equals_lower("false"));
99*e8d8bef9SDimitry Andric   BranchTargetEnforcement = BTIEnable.equals_lower("true");
100*e8d8bef9SDimitry Andric }
101*e8d8bef9SDimitry Andric 
102*e8d8bef9SDimitry Andric bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const {
103*e8d8bef9SDimitry Andric   if (!SignReturnAddress)
104*e8d8bef9SDimitry Andric     return false;
105*e8d8bef9SDimitry Andric   if (SignReturnAddressAll)
106*e8d8bef9SDimitry Andric     return true;
107*e8d8bef9SDimitry Andric   return SpillsLR;
108*e8d8bef9SDimitry Andric }
109*e8d8bef9SDimitry Andric 
110*e8d8bef9SDimitry Andric bool AArch64FunctionInfo::shouldSignReturnAddress() const {
111*e8d8bef9SDimitry Andric   return shouldSignReturnAddress(llvm::any_of(
112*e8d8bef9SDimitry Andric       MF.getFrameInfo().getCalleeSavedInfo(),
113*e8d8bef9SDimitry Andric       [](const auto &Info) { return Info.getReg() == AArch64::LR; }));
114*e8d8bef9SDimitry Andric }
115