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