diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp index a37e38072554..41343ba9700c 100644 --- a/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp +++ b/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -14,6 +14,9 @@ //===----------------------------------------------------------------------===// #include "AArch64MachineFunctionInfo.h" +#include "AArch64InstrInfo.h" +#include <llvm/IR/Metadata.h> +#include <llvm/IR/Module.h> using namespace llvm; @@ -30,3 +33,82 @@ void AArch64FunctionInfo::initializeBaseYamlFields( if (YamlMFI.HasRedZone.hasValue()) HasRedZone = YamlMFI.HasRedZone; } + +static std::pair<bool, bool> GetSignReturnAddress(const Function &F) { + // The function should be signed in the following situations: + // - sign-return-address=all + // - sign-return-address=non-leaf and the functions spills the LR + if (!F.hasFnAttribute("sign-return-address")) { + const Module &M = *F.getParent(); + if (const auto *Sign = mdconst::extract_or_null<ConstantInt>( + M.getModuleFlag("sign-return-address"))) { + if (Sign->getZExtValue()) { + if (const auto *All = mdconst::extract_or_null<ConstantInt>( + M.getModuleFlag("sign-return-address-all"))) + return {true, All->getZExtValue()}; + return {true, false}; + } + } + return {false, false}; + } + + StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString(); + if (Scope.equals("none")) + return {false, false}; + + if (Scope.equals("all")) + return {true, true}; + + assert(Scope.equals("non-leaf")); + return {true, false}; +} + +static bool ShouldSignWithBKey(const Function &F) { + if (!F.hasFnAttribute("sign-return-address-key")) { + if (const auto *BKey = mdconst::extract_or_null<ConstantInt>( + F.getParent()->getModuleFlag("sign-return-address-with-bkey"))) + return BKey->getZExtValue(); + return false; + } + + const StringRef Key = + F.getFnAttribute("sign-return-address-key").getValueAsString(); + assert(Key.equals_lower("a_key") || Key.equals_lower("b_key")); + return Key.equals_lower("b_key"); +} + +AArch64FunctionInfo::AArch64FunctionInfo(MachineFunction &MF) : MF(MF) { + // If we already know that the function doesn't have a redzone, set + // HasRedZone here. + if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) + HasRedZone = false; + + const Function &F = MF.getFunction(); + std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F); + SignWithBKey = ShouldSignWithBKey(F); + + if (!F.hasFnAttribute("branch-target-enforcement")) { + if (const auto *BTE = mdconst::extract_or_null<ConstantInt>( + F.getParent()->getModuleFlag("branch-target-enforcement"))) + BranchTargetEnforcement = BTE->getZExtValue(); + return; + } + + const StringRef BTIEnable = F.getFnAttribute("branch-target-enforcement").getValueAsString(); + assert(BTIEnable.equals_lower("true") || BTIEnable.equals_lower("false")); + BranchTargetEnforcement = BTIEnable.equals_lower("true"); +} + +bool AArch64FunctionInfo::shouldSignReturnAddress(bool SpillsLR) const { + if (!SignReturnAddress) + return false; + if (SignReturnAddressAll) + return true; + return SpillsLR; +} + +bool AArch64FunctionInfo::shouldSignReturnAddress() const { + return shouldSignReturnAddress(llvm::any_of( + MF.getFrameInfo().getCalleeSavedInfo(), + [](const auto &Info) { return Info.getReg() == AArch64::LR; })); +} |