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 26 yaml::AArch64FunctionInfo::AArch64FunctionInfo( 27 const llvm::AArch64FunctionInfo &MFI) 28 : HasRedZone(MFI.hasRedZone()) {} 29 30 void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) { 31 MappingTraits<AArch64FunctionInfo>::mapping(YamlIO, *this); 32 } 33 34 void AArch64FunctionInfo::initializeBaseYamlFields( 35 const yaml::AArch64FunctionInfo &YamlMFI) { 36 if (YamlMFI.HasRedZone) 37 HasRedZone = YamlMFI.HasRedZone; 38 } 39 40 static std::pair<bool, bool> GetSignReturnAddress(const Function &F) { 41 // The function should be signed in the following situations: 42 // - sign-return-address=all 43 // - sign-return-address=non-leaf and the functions spills the LR 44 if (!F.hasFnAttribute("sign-return-address")) { 45 const Module &M = *F.getParent(); 46 if (const auto *Sign = mdconst::extract_or_null<ConstantInt>( 47 M.getModuleFlag("sign-return-address"))) { 48 if (Sign->getZExtValue()) { 49 if (const auto *All = mdconst::extract_or_null<ConstantInt>( 50 M.getModuleFlag("sign-return-address-all"))) 51 return {true, All->getZExtValue()}; 52 return {true, false}; 53 } 54 } 55 return {false, false}; 56 } 57 58 StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString(); 59 if (Scope.equals("none")) 60 return {false, false}; 61 62 if (Scope.equals("all")) 63 return {true, true}; 64 65 assert(Scope.equals("non-leaf")); 66 return {true, false}; 67 } 68 69 static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) { 70 if (!F.hasFnAttribute("sign-return-address-key")) { 71 if (const auto *BKey = mdconst::extract_or_null<ConstantInt>( 72 F.getParent()->getModuleFlag("sign-return-address-with-bkey"))) 73 return BKey->getZExtValue(); 74 if (STI.getTargetTriple().isOSWindows()) 75 return true; 76 return false; 77 } 78 79 const StringRef Key = 80 F.getFnAttribute("sign-return-address-key").getValueAsString(); 81 assert(Key.equals_insensitive("a_key") || Key.equals_insensitive("b_key")); 82 return Key.equals_insensitive("b_key"); 83 } 84 85 AArch64FunctionInfo::AArch64FunctionInfo(const Function &F, 86 const AArch64Subtarget *STI) { 87 // If we already know that the function doesn't have a redzone, set 88 // HasRedZone here. 89 if (F.hasFnAttribute(Attribute::NoRedZone)) 90 HasRedZone = false; 91 std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F); 92 SignWithBKey = ShouldSignWithBKey(F, *STI); 93 // TODO: skip functions that have no instrumented allocas for optimization 94 IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag); 95 96 if (!F.hasFnAttribute("branch-target-enforcement")) { 97 if (const auto *BTE = mdconst::extract_or_null<ConstantInt>( 98 F.getParent()->getModuleFlag("branch-target-enforcement"))) 99 BranchTargetEnforcement = BTE->getZExtValue(); 100 return; 101 } 102 103 const StringRef BTIEnable = 104 F.getFnAttribute("branch-target-enforcement").getValueAsString(); 105 assert(BTIEnable.equals_insensitive("true") || 106 BTIEnable.equals_insensitive("false")); 107 BranchTargetEnforcement = BTIEnable.equals_insensitive("true"); 108 } 109 110 MachineFunctionInfo *AArch64FunctionInfo::clone( 111 BumpPtrAllocator &Allocator, MachineFunction &DestMF, 112 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 113 const { 114 return DestMF.cloneInfo<AArch64FunctionInfo>(*this); 115 } 116 117 bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const { 118 if (!SignReturnAddress) 119 return false; 120 if (SignReturnAddressAll) 121 return true; 122 return SpillsLR; 123 } 124 125 bool AArch64FunctionInfo::shouldSignReturnAddress( 126 const MachineFunction &MF) const { 127 return shouldSignReturnAddress(llvm::any_of( 128 MF.getFrameInfo().getCalleeSavedInfo(), 129 [](const auto &Info) { return Info.getReg() == AArch64::LR; })); 130 } 131 132 bool AArch64FunctionInfo::needsDwarfUnwindInfo( 133 const MachineFunction &MF) const { 134 if (!NeedsDwarfUnwindInfo) 135 NeedsDwarfUnwindInfo = MF.needsFrameMoves() && 136 !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); 137 138 return *NeedsDwarfUnwindInfo; 139 } 140 141 bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo( 142 const MachineFunction &MF) const { 143 if (!NeedsAsyncDwarfUnwindInfo) { 144 const Function &F = MF.getFunction(); 145 // The check got "minsize" is because epilogue unwind info is not emitted 146 // (yet) for homogeneous epilogues, outlined functions, and functions 147 // outlined from. 148 NeedsAsyncDwarfUnwindInfo = needsDwarfUnwindInfo(MF) && 149 F.getUWTableKind() == UWTableKind::Async && 150 !F.hasMinSize(); 151 } 152 return *NeedsAsyncDwarfUnwindInfo; 153 } 154