forked from OSchip/llvm-project
[ARM] add common parts for PACBTI-M support in the backend
This patch encapsulates decision logic about when and how to generate PAC/BTI related code. It's a part shared by PAC-RET, BTI placement, build attribute emission, etc, so it make sense committing it separately in order to unblock the aforementioned parts, which can proceed concurrently. This patch adds a few member functions to `ARMFunctionInfo`, which are currently unused, therefore there is no testing for them at the moment. This code is tested in follow-up PAC/BTI code gen patches. This patch is part of a series that adds support for the PACBTI-M extension of the Armv8.1-M architecture, as detailed here: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension The PACBTI-M specification can be found in the Armv8-M Architecture Reference Manual: https://developer.arm.com/documentation/ddi0553/latest The following people contributed to this patch: - Momchil Velikov - Ties Stuij Reviewed By: danielkiss Differential Revision: https://reviews.llvm.org/D112423
This commit is contained in:
parent
ab2611d099
commit
c12c7a84b0
|
@ -13,8 +13,63 @@ using namespace llvm;
|
|||
|
||||
void ARMFunctionInfo::anchor() {}
|
||||
|
||||
static bool GetBranchTargetEnforcement(MachineFunction &MF) {
|
||||
const auto &Subtarget = MF.getSubtarget<ARMSubtarget>();
|
||||
if (!Subtarget.isMClass() || !Subtarget.hasV7Ops())
|
||||
return false;
|
||||
|
||||
const Function &F = MF.getFunction();
|
||||
if (!F.hasFnAttribute("branch-target-enforcement")) {
|
||||
if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
|
||||
F.getParent()->getModuleFlag("branch-target-enforcement")))
|
||||
return BTE->getZExtValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
const StringRef BTIEnable =
|
||||
F.getFnAttribute("branch-target-enforcement").getValueAsString();
|
||||
assert(BTIEnable.equals_insensitive("true") ||
|
||||
BTIEnable.equals_insensitive("false"));
|
||||
return BTIEnable.equals_insensitive("true");
|
||||
}
|
||||
|
||||
// The pair returns values for the ARMFunctionInfo members
|
||||
// SignReturnAddress and SignReturnAddressAll respectively.
|
||||
static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
|
||||
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};
|
||||
}
|
||||
|
||||
ARMFunctionInfo::ARMFunctionInfo(MachineFunction &MF)
|
||||
: isThumb(MF.getSubtarget<ARMSubtarget>().isThumb()),
|
||||
hasThumb2(MF.getSubtarget<ARMSubtarget>().hasThumb2()),
|
||||
IsCmseNSEntry(MF.getFunction().hasFnAttribute("cmse_nonsecure_entry")),
|
||||
IsCmseNSCall(MF.getFunction().hasFnAttribute("cmse_nonsecure_call")) {}
|
||||
IsCmseNSCall(MF.getFunction().hasFnAttribute("cmse_nonsecure_call")),
|
||||
BranchTargetEnforcement(GetBranchTargetEnforcement(MF)) {
|
||||
|
||||
const auto &Subtarget = MF.getSubtarget<ARMSubtarget>();
|
||||
if (Subtarget.isMClass() && Subtarget.hasV7Ops())
|
||||
std::tie(SignReturnAddress, SignReturnAddressAll) =
|
||||
GetSignReturnAddress(MF.getFunction());
|
||||
}
|
||||
|
|
|
@ -142,6 +142,17 @@ class ARMFunctionInfo : public MachineFunctionInfo {
|
|||
/// con/destructors).
|
||||
bool PreservesR0 = false;
|
||||
|
||||
/// True if the function should sign its return address.
|
||||
bool SignReturnAddress = false;
|
||||
|
||||
/// True if the fucntion should sign its return address, even if LR is not
|
||||
/// saved.
|
||||
bool SignReturnAddressAll = false;
|
||||
|
||||
/// True if BTI instructions should be placed at potential indirect jump
|
||||
/// destinations.
|
||||
bool BranchTargetEnforcement = false;
|
||||
|
||||
public:
|
||||
ARMFunctionInfo() = default;
|
||||
|
||||
|
@ -268,6 +279,20 @@ public:
|
|||
|
||||
void setPreservesR0() { PreservesR0 = true; }
|
||||
bool getPreservesR0() const { return PreservesR0; }
|
||||
|
||||
bool shouldSignReturnAddress() const {
|
||||
return shouldSignReturnAddress(LRSpilled);
|
||||
}
|
||||
|
||||
bool shouldSignReturnAddress(bool SpillsLR) const {
|
||||
if (!SignReturnAddress)
|
||||
return false;
|
||||
if (SignReturnAddressAll)
|
||||
return true;
|
||||
return LRSpilled;
|
||||
}
|
||||
|
||||
bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
Loading…
Reference in New Issue