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