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" 1881ad6265SDimitry Andric #include "AArch64Subtarget.h" 1981ad6265SDimitry Andric #include "llvm/IR/Constants.h" 2081ad6265SDimitry Andric #include "llvm/IR/Metadata.h" 2181ad6265SDimitry Andric #include "llvm/IR/Module.h" 2281ad6265SDimitry 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) { 3681ad6265SDimitry 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 69*bdd1243dSDimitry Andric static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) { 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(); 74*bdd1243dSDimitry Andric if (STI.getTargetTriple().isOSWindows()) 75*bdd1243dSDimitry Andric return true; 76e8d8bef9SDimitry Andric return false; 77e8d8bef9SDimitry Andric } 78e8d8bef9SDimitry Andric 79e8d8bef9SDimitry Andric const StringRef Key = 80e8d8bef9SDimitry Andric F.getFnAttribute("sign-return-address-key").getValueAsString(); 81fe6060f1SDimitry Andric assert(Key.equals_insensitive("a_key") || Key.equals_insensitive("b_key")); 82fe6060f1SDimitry Andric return Key.equals_insensitive("b_key"); 83e8d8bef9SDimitry Andric } 84e8d8bef9SDimitry Andric 85*bdd1243dSDimitry Andric AArch64FunctionInfo::AArch64FunctionInfo(const Function &F, 86*bdd1243dSDimitry Andric const AArch64Subtarget *STI) { 87e8d8bef9SDimitry Andric // If we already know that the function doesn't have a redzone, set 88e8d8bef9SDimitry Andric // HasRedZone here. 89*bdd1243dSDimitry Andric if (F.hasFnAttribute(Attribute::NoRedZone)) 90e8d8bef9SDimitry Andric HasRedZone = false; 91e8d8bef9SDimitry Andric std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F); 92*bdd1243dSDimitry Andric SignWithBKey = ShouldSignWithBKey(F, *STI); 9381ad6265SDimitry Andric // TODO: skip functions that have no instrumented allocas for optimization 9481ad6265SDimitry Andric IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag); 95e8d8bef9SDimitry Andric 96e8d8bef9SDimitry Andric if (!F.hasFnAttribute("branch-target-enforcement")) { 97e8d8bef9SDimitry Andric if (const auto *BTE = mdconst::extract_or_null<ConstantInt>( 98e8d8bef9SDimitry Andric F.getParent()->getModuleFlag("branch-target-enforcement"))) 99e8d8bef9SDimitry Andric BranchTargetEnforcement = BTE->getZExtValue(); 100e8d8bef9SDimitry Andric return; 101e8d8bef9SDimitry Andric } 102e8d8bef9SDimitry Andric 103fe6060f1SDimitry Andric const StringRef BTIEnable = 104fe6060f1SDimitry Andric F.getFnAttribute("branch-target-enforcement").getValueAsString(); 105fe6060f1SDimitry Andric assert(BTIEnable.equals_insensitive("true") || 106fe6060f1SDimitry Andric BTIEnable.equals_insensitive("false")); 107fe6060f1SDimitry Andric BranchTargetEnforcement = BTIEnable.equals_insensitive("true"); 108e8d8bef9SDimitry Andric } 109e8d8bef9SDimitry Andric 11081ad6265SDimitry Andric MachineFunctionInfo *AArch64FunctionInfo::clone( 11181ad6265SDimitry Andric BumpPtrAllocator &Allocator, MachineFunction &DestMF, 11281ad6265SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 11381ad6265SDimitry Andric const { 114*bdd1243dSDimitry Andric return DestMF.cloneInfo<AArch64FunctionInfo>(*this); 11581ad6265SDimitry Andric } 11681ad6265SDimitry Andric 117e8d8bef9SDimitry Andric bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const { 118e8d8bef9SDimitry Andric if (!SignReturnAddress) 119e8d8bef9SDimitry Andric return false; 120e8d8bef9SDimitry Andric if (SignReturnAddressAll) 121e8d8bef9SDimitry Andric return true; 122e8d8bef9SDimitry Andric return SpillsLR; 123e8d8bef9SDimitry Andric } 124e8d8bef9SDimitry Andric 125*bdd1243dSDimitry Andric bool AArch64FunctionInfo::shouldSignReturnAddress( 126*bdd1243dSDimitry Andric const MachineFunction &MF) const { 127e8d8bef9SDimitry Andric return shouldSignReturnAddress(llvm::any_of( 128*bdd1243dSDimitry Andric MF.getFrameInfo().getCalleeSavedInfo(), 129e8d8bef9SDimitry Andric [](const auto &Info) { return Info.getReg() == AArch64::LR; })); 130e8d8bef9SDimitry Andric } 13181ad6265SDimitry Andric 132*bdd1243dSDimitry Andric bool AArch64FunctionInfo::needsDwarfUnwindInfo( 133*bdd1243dSDimitry Andric const MachineFunction &MF) const { 13481ad6265SDimitry Andric if (!NeedsDwarfUnwindInfo) 135*bdd1243dSDimitry Andric NeedsDwarfUnwindInfo = MF.needsFrameMoves() && 136*bdd1243dSDimitry Andric !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); 13781ad6265SDimitry Andric 13881ad6265SDimitry Andric return *NeedsDwarfUnwindInfo; 13981ad6265SDimitry Andric } 14081ad6265SDimitry Andric 141*bdd1243dSDimitry Andric bool AArch64FunctionInfo::needsAsyncDwarfUnwindInfo( 142*bdd1243dSDimitry Andric const MachineFunction &MF) const { 14381ad6265SDimitry Andric if (!NeedsAsyncDwarfUnwindInfo) { 144*bdd1243dSDimitry Andric const Function &F = MF.getFunction(); 14581ad6265SDimitry Andric // The check got "minsize" is because epilogue unwind info is not emitted 14681ad6265SDimitry Andric // (yet) for homogeneous epilogues, outlined functions, and functions 14781ad6265SDimitry Andric // outlined from. 148*bdd1243dSDimitry Andric NeedsAsyncDwarfUnwindInfo = needsDwarfUnwindInfo(MF) && 14981ad6265SDimitry Andric F.getUWTableKind() == UWTableKind::Async && 15081ad6265SDimitry Andric !F.hasMinSize(); 15181ad6265SDimitry Andric } 15281ad6265SDimitry Andric return *NeedsAsyncDwarfUnwindInfo; 15381ad6265SDimitry Andric } 154