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