[clang] a88c722 - [AArch64] PAC/BTI code generation for LLVM generated functions
Momchil Velikov via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 04:01:06 PDT 2020
Author: Momchil Velikov
Date: 2020-09-25T11:47:14+01:00
New Revision: a88c722e687e6780dcd6a58718350dc76fcc4cc9
URL: https://github.com/llvm/llvm-project/commit/a88c722e687e6780dcd6a58718350dc76fcc4cc9
DIFF: https://github.com/llvm/llvm-project/commit/a88c722e687e6780dcd6a58718350dc76fcc4cc9.diff
LOG: [AArch64] PAC/BTI code generation for LLVM generated functions
PAC/BTI-related codegen in the AArch64 backend is controlled by a set
of LLVM IR function attributes, added to the function by Clang, based
on command-line options and GCC-style function attributes. However,
functions, generated in the LLVM middle end (for example,
asan.module.ctor or __llvm_gcov_write_out) do not get any attributes
and the backend incorrectly does not do any PAC/BTI code generation.
This patch record the default state of PAC/BTI codegen in a set of
LLVM IR module-level attributes, based on command-line options:
* "sign-return-address", with non-zero value means generate code to
sign return addresses (PAC-RET), zero value means disable PAC-RET.
* "sign-return-address-all", with non-zero value means enable PAC-RET
for all functions, zero value means enable PAC-RET only for
functions, which spill LR.
* "sign-return-address-with-bkey", with non-zero value means use B-key
for signing, zero value mean use A-key.
This set of attributes are always added for AArch64 targets (as
opposed, for example, to interpreting a missing attribute as having a
value 0) in order to be able to check for conflicts when combining
module attributed during LTO.
Module-level attributes are overridden by function level attributes.
All the decision making about whether to not to generate PAC and/or
BTI code is factored out into AArch64FunctionInfo, there shouldn't be
any places left, other than AArch64FunctionInfo, which directly
examine PAC/BTI attributes, except AArch64AsmPrinter.cpp, which
is/will-be handled by a separate patch.
Differential Revision: https://reviews.llvm.org/D85649
Added:
llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-1.ll
llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll
llvm/test/CodeGen/AArch64/pacbti-module-attrs.ll
Modified:
clang/lib/CodeGen/CGDeclCXX.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/aarch64-branch-protection-attr.c
clang/test/CodeGen/aarch64-sign-return-address.c
llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll
llvm/test/CodeGen/AArch64/branch-target-enforcement.mir
llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll
llvm/test/CodeGen/AArch64/machine-outliner-2fixup-blr-terminator.mir
llvm/test/CodeGen/AArch64/machine-outliner-bti.mir
llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
Removed:
clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp
################################################################################
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index bfefd7956157..3f6d0e23c685 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -421,22 +421,6 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
!isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
- auto RASignKind = getLangOpts().getSignReturnAddressScope();
- if (RASignKind != LangOptions::SignReturnAddressScopeKind::None) {
- Fn->addFnAttr("sign-return-address",
- RASignKind == LangOptions::SignReturnAddressScopeKind::All
- ? "all"
- : "non-leaf");
- auto RASignKey = getLangOpts().getSignReturnAddressKey();
- Fn->addFnAttr("sign-return-address-key",
- RASignKey == LangOptions::SignReturnAddressKeyKind::AKey
- ? "a_key"
- : "b_key");
- }
-
- if (getLangOpts().BranchTargetEnforcement)
- Fn->addFnAttr("branch-target-enforcement");
-
return Fn;
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6a77f6b040a1..c3457865c0b0 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -590,6 +590,23 @@ void CodeGenModule::Release() {
1);
}
+ if (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
+ Arch == llvm::Triple::aarch64_be) {
+ getModule().addModuleFlag(llvm::Module::Error,
+ "branch-target-enforcement",
+ LangOpts.BranchTargetEnforcement);
+
+ getModule().addModuleFlag(llvm::Module::Error, "sign-return-address",
+ LangOpts.hasSignReturnAddress());
+
+ getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
+ LangOpts.isSignReturnAddressScopeAll());
+
+ getModule().addModuleFlag(llvm::Module::Error,
+ "sign-return-address-with-bkey",
+ !LangOpts.isSignReturnAddressWithAKey());
+ }
+
if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) {
// Indicate whether __nvvm_reflect should be configured to flush denormal
// floating point values to 0. (This corresponds to its "__CUDA_FTZ"
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 5ebf432a4cd3..2f3f4c281079 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -5521,40 +5521,33 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
if (!FD)
return;
- LangOptions::SignReturnAddressScopeKind Scope =
- CGM.getLangOpts().getSignReturnAddressScope();
- LangOptions::SignReturnAddressKeyKind Key =
- CGM.getLangOpts().getSignReturnAddressKey();
- bool BranchTargetEnforcement = CGM.getLangOpts().BranchTargetEnforcement;
- if (const auto *TA = FD->getAttr<TargetAttr>()) {
- ParsedTargetAttr Attr = TA->parse();
- if (!Attr.BranchProtection.empty()) {
- TargetInfo::BranchProtectionInfo BPI;
- StringRef Error;
- (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
- BPI, Error);
- assert(Error.empty());
- Scope = BPI.SignReturnAddr;
- Key = BPI.SignKey;
- BranchTargetEnforcement = BPI.BranchTargetEnforcement;
- }
- }
+ const auto *TA = FD->getAttr<TargetAttr>();
+ if (TA == nullptr)
+ return;
+
+ ParsedTargetAttr Attr = TA->parse();
+ if (Attr.BranchProtection.empty())
+ return;
+
+ TargetInfo::BranchProtectionInfo BPI;
+ StringRef Error;
+ (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
+ BPI, Error);
+ assert(Error.empty());
auto *Fn = cast<llvm::Function>(GV);
- if (Scope != LangOptions::SignReturnAddressScopeKind::None) {
- Fn->addFnAttr("sign-return-address",
- Scope == LangOptions::SignReturnAddressScopeKind::All
- ? "all"
- : "non-leaf");
+ static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
+ Fn->addFnAttr("sign-return-address", SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
+ if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
Fn->addFnAttr("sign-return-address-key",
- Key == LangOptions::SignReturnAddressKeyKind::AKey
+ BPI.SignKey == LangOptions::SignReturnAddressKeyKind::AKey
? "a_key"
: "b_key");
}
- if (BranchTargetEnforcement)
- Fn->addFnAttr("branch-target-enforcement");
+ Fn->addFnAttr("branch-target-enforcement",
+ BPI.BranchTargetEnforcement ? "true" : "false");
}
};
diff --git a/clang/test/CodeGen/aarch64-branch-protection-attr.c b/clang/test/CodeGen/aarch64-branch-protection-attr.c
index ee761d6e8977..d694b619802d 100644
--- a/clang/test/CodeGen/aarch64-branch-protection-attr.c
+++ b/clang/test/CodeGen/aarch64-branch-protection-attr.c
@@ -1,81 +1,63 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple aarch64-unknown-unknown-eabi -emit-llvm -target-cpu generic -target-feature +v8.5a %s -o - \
-// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=NO-OVERRIDE
-// RUN: %clang_cc1 -triple aarch64-unknown-unknown-eabi -emit-llvm -target-cpu generic -target-feature +v8.5a %s -o - \
-// RUN: -msign-return-address=non-leaf -msign-return-address-key=a_key -mbranch-target-enforce \
-// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=OVERRIDE
-
-void missing() {}
-// NO-OVERRIDE: define void @missing() #[[#NONE:]]
-// OVERRIDE: define void @missing() #[[#STD:]]
+// RUN: | FileCheck %s --check-prefix=CHECK
__attribute__ ((target("branch-protection=none")))
void none() {}
-// NO-OVERRIDE: define void @none() #[[#NONE]]
-// OVERRIDE: define void @none() #[[#NONE:]]
+// CHECK: define void @none() #[[#NONE:]]
__attribute__ ((target("branch-protection=standard")))
void std() {}
-// NO-OVERRIDE: define void @std() #[[#STD:]]
-// OVERRIDE: define void @std() #[[#STD]]
+// CHECK: define void @std() #[[#STD:]]
__attribute__ ((target("branch-protection=bti")))
void btionly() {}
-// NO-OVERRIDE: define void @btionly() #[[#BTI:]]
-// OVERRIDE: define void @btionly() #[[#BTI:]]
+// CHECK: define void @btionly() #[[#BTI:]]
__attribute__ ((target("branch-protection=pac-ret")))
void paconly() {}
-// NO-OVERRIDE: define void @paconly() #[[#PAC:]]
-// OVERRIDE: define void @paconly() #[[#PAC:]]
+// CHECK: define void @paconly() #[[#PAC:]]
__attribute__ ((target("branch-protection=pac-ret+bti")))
void pacbti0() {}
-// NO-OVERRIDE: define void @pacbti0() #[[#PACBTI:]]
-// OVERRIDE: define void @pacbti0() #[[#PACBTI:]]
+// CHECK: define void @pacbti0() #[[#PACBTI:]]
__attribute__ ((target("branch-protection=bti+pac-ret")))
void pacbti1() {}
-// NO-OVERRIDE: define void @pacbti1() #[[#PACBTI]]
-// OVERRIDE: define void @pacbti1() #[[#PACBTI]]
+// CHECK: define void @pacbti1() #[[#PACBTI]]
__attribute__ ((target("branch-protection=pac-ret+leaf")))
void leaf() {}
-// NO-OVERRIDE: define void @leaf() #[[#PACLEAF:]]
-// OVERRIDE: define void @leaf() #[[#PACLEAF:]]
+// CHECK: define void @leaf() #[[#PACLEAF:]]
__attribute__ ((target("branch-protection=pac-ret+b-key")))
void bkey() {}
-// NO-OVERRIDE: define void @bkey() #[[#PACBKEY:]]
-// OVERRIDE: define void @bkey() #[[#PACBKEY:]]
+// CHECK: define void @bkey() #[[#PACBKEY:]]
__attribute__ ((target("branch-protection=pac-ret+b-key+leaf")))
void bkeyleaf0() {}
-// NO-OVERRIDE: define void @bkeyleaf0() #[[#PACBKEYLEAF:]]
-// OVERRIDE: define void @bkeyleaf0() #[[#PACBKEYLEAF:]]
+// CHECK: define void @bkeyleaf0() #[[#PACBKEYLEAF:]]
__attribute__ ((target("branch-protection=pac-ret+leaf+b-key")))
void bkeyleaf1() {}
-// NO-OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF]]
-// OVERRIDE: define void @bkeyleaf1() #[[#PACBKEYLEAF]]
+// CHECK: define void @bkeyleaf1() #[[#PACBKEYLEAF]]
__attribute__ ((target("branch-protection=pac-ret+leaf+bti")))
void btileaf() {}
-// NO-OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]]
-// OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]]
+// CHECK: define void @btileaf() #[[#BTIPACLEAF:]]
-// CHECK-DAG: attributes #[[#NONE]]
+// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="none"
-// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
+// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#BTI]] = { {{.*}}"branch-target-enforcement"
+// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="none"
-// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
+// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
+// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
-// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
+// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}}"branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
-// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"
+// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key"
-// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
+// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
diff --git a/clang/test/CodeGen/aarch64-sign-return-address.c b/clang/test/CodeGen/aarch64-sign-return-address.c
index d062685e40c9..7dd7231e824a 100644
--- a/clang/test/CodeGen/aarch64-sign-return-address.c
+++ b/clang/test/CodeGen/aarch64-sign-return-address.c
@@ -1,27 +1,46 @@
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.2-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=PARTIAL --check-prefix=A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.4-a -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PARTIAL --check-prefix=B-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL --check-prefix=B-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.3-a -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
+
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=none %s | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=B-KEY
+// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
// REQUIRES: aarch64-registered-target
-// CHECK: @foo() #[[ATTR:[0-9]*]]
-//
-// NONE-NOT: "sign-return-address"={{.*}}
+// Check there are no branch protection function attributes
+
+// CHECK-LABEL: @foo() #[[#ATTR:]]
+
+// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
+// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
+// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
-// PARTIAL: "sign-return-address"="non-leaf"
+// Check module attributes
-// ALL: "sign-return-address"="all"
+// NONE: !{i32 1, !"branch-target-enforcement", i32 0}
+// ALL: !{i32 1, !"branch-target-enforcement", i32 0}
+// PART: !{i32 1, !"branch-target-enforcement", i32 0}
+// BTE: !{i32 1, !"branch-target-enforcement", i32 1}
+// B-KEY: !{i32 1, !"branch-target-enforcement", i32 0}
-// BTE: "branch-target-enforcement"
+// NONE: !{i32 1, !"sign-return-address", i32 0}
+// ALL: !{i32 1, !"sign-return-address", i32 1}
+// PART: !{i32 1, !"sign-return-address", i32 1}
+// BTE: !{i32 1, !"sign-return-address", i32 0}
+// B-KEY: !{i32 1, !"sign-return-address", i32 1}
-// A-KEY: "sign-return-address-key"="a_key"
+// NONE: !{i32 1, !"sign-return-address-all", i32 0}
+// ALL: !{i32 1, !"sign-return-address-all", i32 1}
+// PART: !{i32 1, !"sign-return-address-all", i32 0}
+// BTE: !{i32 1, !"sign-return-address-all", i32 0}
+// B-KEY: !{i32 1, !"sign-return-address-all", i32 0}
-// B-KEY: "sign-return-address-key"="b_key"
+// NONE: !{i32 1, !"sign-return-address-with-bkey", i32 0}
+// ALL: !{i32 1, !"sign-return-address-with-bkey", i32 0}
+// PART: !{i32 1, !"sign-return-address-with-bkey", i32 0}
+// BTE: !{i32 1, !"sign-return-address-with-bkey", i32 0}
+// B-KEY: !{i32 1, !"sign-return-address-with-bkey", i32 1}
void foo() {}
diff --git a/clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp b/clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp
deleted file mode 100644
index 3971c22287f9..000000000000
--- a/clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY
-
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=none %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=standard %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY --check-prefix=CHECK-BTE
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-A-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL --check-prefix=CHECK-B-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=bti %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTE
-// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf+bti %s | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL --check-prefix=CHECK-B-KEY --check-prefix=BTE
-
-struct Foo {
- Foo() {}
- ~Foo() {}
-};
-
-Foo f;
-
-// CHECK: @llvm.global_ctors {{.*}}i32 65535, void ()* @[[CTOR_FN:.*]], i8* null
-
-// CHECK: @[[CTOR_FN]]() #[[ATTR:[0-9]*]]
-
-// CHECK-NONE-NOT: "sign-return-address"={{.*}}
-// CHECK-PARTIAL: "sign-return-address"="non-leaf"
-// CHECK-ALL: "sign-return-address"="all"
-// CHECK-A-KEY: "sign-return-address-key"="a_key"
-// CHECK-B-KEY: "sign-return-address-key"="b_key"
-// CHECK-BTE: "branch-target-enforcement"
diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
index 1956014b738d..d3b5166585c3 100644
--- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -16,6 +16,7 @@
//
//===----------------------------------------------------------------------===//
+#include "AArch64MachineFunctionInfo.h"
#include "AArch64Subtarget.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -57,13 +58,13 @@ FunctionPass *llvm::createAArch64BranchTargetsPass() {
}
bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) {
- const Function &F = MF.getFunction();
- if (!F.hasFnAttribute("branch-target-enforcement"))
+ if (!MF.getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
return false;
LLVM_DEBUG(
dbgs() << "********** AArch64 Branch Targets **********\n"
<< "********** Function: " << MF.getName() << '\n');
+ const Function &F = MF.getFunction();
// LLVM does not consider basic blocks which are the targets of jump tables
// to be address-taken (the address can't escape anywhere else), but they are
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 625415e93d9c..7f4498da317c 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -375,31 +375,6 @@ MachineBasicBlock::iterator AArch64FrameLowering::eliminateCallFramePseudoInstr(
return MBB.erase(I);
}
-static bool ShouldSignReturnAddress(MachineFunction &MF) {
- // The function should be signed in the following situations:
- // - sign-return-address=all
- // - sign-return-address=non-leaf and the functions spills the LR
-
- const Function &F = MF.getFunction();
- if (!F.hasFnAttribute("sign-return-address"))
- return false;
-
- StringRef Scope = F.getFnAttribute("sign-return-address").getValueAsString();
- if (Scope.equals("none"))
- return false;
-
- if (Scope.equals("all"))
- return true;
-
- assert(Scope.equals("non-leaf") && "Expected all, none or non-leaf");
-
- for (const auto &Info : MF.getFrameInfo().getCalleeSavedInfo())
- if (Info.getReg() == AArch64::LR)
- return true;
-
- return false;
-}
-
// Convenience function to create a DWARF expression for
// Expr + NumBytes + NumVGScaledBytes * AArch64::VG
static void appendVGScaledOffsetExpr(SmallVectorImpl<char> &Expr,
@@ -1007,17 +982,6 @@ static void adaptForLdStOpt(MachineBasicBlock &MBB,
//
}
-static bool ShouldSignWithAKey(MachineFunction &MF) {
- const Function &F = MF.getFunction();
- if (!F.hasFnAttribute("sign-return-address-key"))
- return true;
-
- 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("a_key");
-}
-
static bool needsWinCFI(const MachineFunction &MF) {
const Function &F = MF.getFunction();
return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
@@ -1070,15 +1034,16 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
// to determine the end of the prologue.
DebugLoc DL;
- if (ShouldSignReturnAddress(MF)) {
- if (ShouldSignWithAKey(MF))
- BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIASP))
- .setMIFlag(MachineInstr::FrameSetup);
- else {
+ const auto &MFnI = *MF.getInfo<AArch64FunctionInfo>();
+ if (MFnI.shouldSignReturnAddress()) {
+ if (MFnI.shouldSignWithBKey()) {
BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY))
.setMIFlag(MachineInstr::FrameSetup);
BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIBSP))
.setMIFlag(MachineInstr::FrameSetup);
+ } else {
+ BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIASP))
+ .setMIFlag(MachineInstr::FrameSetup);
}
unsigned CFIIndex =
@@ -1510,7 +1475,8 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
static void InsertReturnAddressAuth(MachineFunction &MF,
MachineBasicBlock &MBB) {
- if (!ShouldSignReturnAddress(MF))
+ const auto &MFI = *MF.getInfo<AArch64FunctionInfo>();
+ if (!MFI.shouldSignReturnAddress())
return;
const AArch64Subtarget &Subtarget = MF.getSubtarget<AArch64Subtarget>();
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
@@ -1527,13 +1493,13 @@ static void InsertReturnAddressAuth(MachineFunction &MF,
if (Subtarget.hasV8_3aOps() && MBBI != MBB.end() &&
MBBI->getOpcode() == AArch64::RET_ReallyLR) {
BuildMI(MBB, MBBI, DL,
- TII->get(ShouldSignWithAKey(MF) ? AArch64::RETAA : AArch64::RETAB))
+ TII->get(MFI.shouldSignWithBKey() ? AArch64::RETAB : AArch64::RETAA))
.copyImplicitOps(*MBBI);
MBB.erase(MBBI);
} else {
BuildMI(
MBB, MBBI, DL,
- TII->get(ShouldSignWithAKey(MF) ? AArch64::AUTIASP : AArch64::AUTIBSP))
+ TII->get(MFI.shouldSignWithBKey() ? AArch64::AUTIBSP : AArch64::AUTIASP))
.setMIFlag(MachineInstr::FrameDestroy);
}
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index fda514b2006c..16820fea0a7d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "AArch64MachineFunctionInfo.h"
#include "AArch64TargetMachine.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/ADT/APSInt.h"
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index cb9500c16f38..53ae3370c217 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -5842,84 +5842,20 @@ AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const {
static bool
outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a,
const outliner::Candidate &b) {
- const Function &Fa = a.getMF()->getFunction();
- const Function &Fb = b.getMF()->getFunction();
+ const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
+ const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
- // If none of the functions have the "sign-return-address" attribute their
- // signing behaviour is equal
- if (!Fa.hasFnAttribute("sign-return-address") &&
- !Fb.hasFnAttribute("sign-return-address")) {
- return true;
- }
-
- // If both functions have the "sign-return-address" attribute their signing
- // behaviour is equal, if the values of the attributes are equal
- if (Fa.hasFnAttribute("sign-return-address") &&
- Fb.hasFnAttribute("sign-return-address")) {
- StringRef ScopeA =
- Fa.getFnAttribute("sign-return-address").getValueAsString();
- StringRef ScopeB =
- Fb.getFnAttribute("sign-return-address").getValueAsString();
- return ScopeA.equals(ScopeB);
- }
-
- // If function B doesn't have the "sign-return-address" attribute but A does,
- // the functions' signing behaviour is equal if A's value for
- // "sign-return-address" is "none" and vice versa.
- if (Fa.hasFnAttribute("sign-return-address")) {
- StringRef ScopeA =
- Fa.getFnAttribute("sign-return-address").getValueAsString();
- return ScopeA.equals("none");
- }
-
- if (Fb.hasFnAttribute("sign-return-address")) {
- StringRef ScopeB =
- Fb.getFnAttribute("sign-return-address").getValueAsString();
- return ScopeB.equals("none");
- }
-
- llvm_unreachable("Unkown combination of sign-return-address attributes");
+ return MFIa->shouldSignReturnAddress(false) == MFIb->shouldSignReturnAddress(false) &&
+ MFIa->shouldSignReturnAddress(true) == MFIb->shouldSignReturnAddress(true);
}
static bool
outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a,
const outliner::Candidate &b) {
- const Function &Fa = a.getMF()->getFunction();
- const Function &Fb = b.getMF()->getFunction();
-
- // If none of the functions have the "sign-return-address-key" attribute
- // their keys are equal
- if (!Fa.hasFnAttribute("sign-return-address-key") &&
- !Fb.hasFnAttribute("sign-return-address-key")) {
- return true;
- }
-
- // If both functions have the "sign-return-address-key" attribute their
- // keys are equal if the values of "sign-return-address-key" are equal
- if (Fa.hasFnAttribute("sign-return-address-key") &&
- Fb.hasFnAttribute("sign-return-address-key")) {
- StringRef KeyA =
- Fa.getFnAttribute("sign-return-address-key").getValueAsString();
- StringRef KeyB =
- Fb.getFnAttribute("sign-return-address-key").getValueAsString();
- return KeyA.equals(KeyB);
- }
-
- // If B doesn't have the "sign-return-address-key" attribute, both keys are
- // equal, if function a has the default key (a_key)
- if (Fa.hasFnAttribute("sign-return-address-key")) {
- StringRef KeyA =
- Fa.getFnAttribute("sign-return-address-key").getValueAsString();
- return KeyA.equals_lower("a_key");
- }
-
- if (Fb.hasFnAttribute("sign-return-address-key")) {
- StringRef KeyB =
- Fb.getFnAttribute("sign-return-address-key").getValueAsString();
- return KeyB.equals_lower("a_key");
- }
+ const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
+ const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
- llvm_unreachable("Unkown combination of sign-return-address-key attributes");
+ return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
}
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a,
@@ -5975,9 +5911,10 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo(
// v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
// necessary. However, at this point we don't know if the outlined function
// will have a RET instruction so we assume the worst.
- const Function &FCF = FirstCand.getMF()->getFunction();
const TargetRegisterInfo &TRI = getRegisterInfo();
- if (FCF.hasFnAttribute("sign-return-address")) {
+ if (FirstCand.getMF()
+ ->getInfo<AArch64FunctionInfo>()
+ ->shouldSignReturnAddress(true)) {
// One PAC and one AUT instructions
NumBytesToCreateFrame += 8;
@@ -6106,7 +6043,7 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo(
NumBytesToCreateFrame += 4;
bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
- return C.getMF()->getFunction().hasFnAttribute("branch-target-enforcement");
+ return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
});
// We check to see if CFI Instructions are present, and if they are
@@ -6811,27 +6748,11 @@ void AArch64InstrInfo::buildOutlinedFrame(
// If a bunch of candidates reach this point they must agree on their return
// address signing. It is therefore enough to just consider the signing
// behaviour of one of them
- const Function &CF = OF.Candidates.front().getMF()->getFunction();
- bool ShouldSignReturnAddr = false;
- if (CF.hasFnAttribute("sign-return-address")) {
- StringRef Scope =
- CF.getFnAttribute("sign-return-address").getValueAsString();
- if (Scope.equals("all"))
- ShouldSignReturnAddr = true;
- else if (Scope.equals("non-leaf") && !IsLeafFunction)
- ShouldSignReturnAddr = true;
- }
+ const auto &MFI = *OF.Candidates.front().getMF()->getInfo<AArch64FunctionInfo>();
+ bool ShouldSignReturnAddr = MFI.shouldSignReturnAddress(!IsLeafFunction);
// a_key is the default
- bool ShouldSignReturnAddrWithAKey = true;
- if (CF.hasFnAttribute("sign-return-address-key")) {
- const StringRef Key =
- CF.getFnAttribute("sign-return-address-key").getValueAsString();
- // Key can either be a_key or b_key
- assert((Key.equals_lower("a_key") || Key.equals_lower("b_key")) &&
- "Return address signing key must be either a_key or b_key");
- ShouldSignReturnAddrWithAKey = Key.equals_lower("a_key");
- }
+ bool ShouldSignReturnAddrWithAKey = !MFI.shouldSignWithBKey();
// If this is a tail call outlined function, then there's already a return.
if (OF.FrameConstructionID == MachineOutlinerTailCall ||
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index ee12563cb093..3235e1971578 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -593,8 +593,8 @@ let RecomputePerFunction = 1 in {
// Avoid generating STRQro if it is slow, unless we're optimizing for code size.
def UseSTRQro : Predicate<"!Subtarget->isSTRQroSlow() || shouldOptForSize(MF)">;
- def UseBTI : Predicate<[{ MF->getFunction().hasFnAttribute("branch-target-enforcement") }]>;
- def NotUseBTI : Predicate<[{ !MF->getFunction().hasFnAttribute("branch-target-enforcement") }]>;
+ def UseBTI : Predicate<[{ MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement() }]>;
+ def NotUseBTI : Predicate<[{ !MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement() }]>;
def SLSBLRMitigation : Predicate<[{ MF->getSubtarget<AArch64Subtarget>().hardenSlsBlr() }]>;
def NoSLSBLRMitigation : Predicate<[{ !MF->getSubtarget<AArch64Subtarget>().hardenSlsBlr() }]>;
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
index a37e38072554..41343ba9700c 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
+++ b/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; }));
+}
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 7e995b8938c2..cc07b9ae465a 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -35,6 +35,9 @@ class MachineInstr;
/// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and
/// contains private AArch64-specific information for each MachineFunction.
class AArch64FunctionInfo final : public MachineFunctionInfo {
+ /// Backreference to the machine function.
+ MachineFunction &MF;
+
/// Number of bytes of arguments this function has on the stack. If the callee
/// is expected to restore the argument stack this should be a multiple of 16,
/// all usable during a tail call.
@@ -138,17 +141,24 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
// CalleeSavedStackSize) to the address of the frame record.
int CalleeSaveBaseToFrameRecordOffset = 0;
-public:
- AArch64FunctionInfo() = default;
+ /// SignReturnAddress is true if PAC-RET is enabled for the function with
+ /// defaults being sign non-leaf functions only, with the B key.
+ bool SignReturnAddress = false;
- explicit AArch64FunctionInfo(MachineFunction &MF) {
- (void)MF;
+ /// SignReturnAddressAll modifies the default PAC-RET mode to signing leaf
+ /// functions as well.
+ bool SignReturnAddressAll = false;
+
+ /// SignWithBKey modifies the default PAC-RET mode to signing with the B key.
+ bool SignWithBKey = false;
+
+ /// BranchTargetEnforcement enables placing BTI instructions at potential
+ /// indirect branch destinations.
+ bool BranchTargetEnforcement = false;
+
+public:
+ explicit AArch64FunctionInfo(MachineFunction &MF);
- // If we already know that the function doesn't have a redzone, set
- // HasRedZone here.
- if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone))
- HasRedZone = false;
- }
void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI);
unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; }
@@ -347,6 +357,13 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
CalleeSaveBaseToFrameRecordOffset = Offset;
}
+ bool shouldSignReturnAddress() const;
+ bool shouldSignReturnAddress(bool SpillsLR) const;
+
+ bool shouldSignWithBKey() const { return SignWithBKey; }
+
+ bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
+
private:
// Hold the lists of LOHs.
MILOHContainer LOHContainerSet;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
index 5bfed7e472b0..4ab940c1f26a 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -789,7 +789,7 @@ static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect,
// When BTI is enabled, we need to use TCRETURNriBTI to make sure that we use
// x16 or x17.
- if (CallerF.getFunction().hasFnAttribute("branch-target-enforcement"))
+ if (CallerF.getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
return AArch64::TCRETURNriBTI;
return AArch64::TCRETURNri;
@@ -809,7 +809,7 @@ bool AArch64CallLowering::lowerTailCall(
// TODO: Right now, regbankselect doesn't know how to handle the rtcGPR64
// register class. Until we can do that, we should fall back here.
- if (F.hasFnAttribute("branch-target-enforcement")) {
+ if (MF.getInfo<AArch64FunctionInfo>()->branchTargetEnforcement()) {
LLVM_DEBUG(
dbgs() << "Cannot lower indirect tail calls with BTI enabled yet.\n");
return false;
diff --git a/llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll b/llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll
index 3fb9e320f890..702d9dfc8fae 100644
--- a/llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll
+++ b/llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll
@@ -20,7 +20,7 @@ entry:
ret void
}
-define void @bti_enabled(void ()* %p) "branch-target-enforcement" {
+define void @bti_enabled(void ()* %p) "branch-target-enforcement"="true" {
entry:
tail call void %p()
; CHECK: br {{x16|x17}}
diff --git a/llvm/test/CodeGen/AArch64/branch-target-enforcement.mir b/llvm/test/CodeGen/AArch64/branch-target-enforcement.mir
index 4879a268407d..f34fb2b84bcc 100644
--- a/llvm/test/CodeGen/AArch64/branch-target-enforcement.mir
+++ b/llvm/test/CodeGen/AArch64/branch-target-enforcement.mir
@@ -3,29 +3,29 @@
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-arm-none-eabi"
- define hidden i32 @simple_external() "branch-target-enforcement" {
+ define hidden i32 @simple_external() "branch-target-enforcement"="true" {
entry:
ret i32 0
}
- define internal i32 @simple_internal() "branch-target-enforcement" {
+ define internal i32 @simple_internal() "branch-target-enforcement"="true" {
entry:
ret i32 0
}
- define hidden i32 @ptr_auth() "branch-target-enforcement" {
+ define hidden i32 @ptr_auth() "branch-target-enforcement"="true" {
entry:
tail call void asm sideeffect "", "~{lr}"()
ret i32 0
}
- define hidden i32 @ptr_auth_b() "branch-target-enforcement" {
+ define hidden i32 @ptr_auth_b() "branch-target-enforcement"="true" {
entry:
tail call void asm sideeffect "", "~{lr}"()
ret i32 0
}
- define hidden i32 @jump_table(i32 %a) "branch-target-enforcement" {
+ define hidden i32 @jump_table(i32 %a) "branch-target-enforcement"="true" {
entry:
switch i32 %a, label %sw.epilog [
i32 1, label %sw.bb
@@ -61,7 +61,7 @@
@label_address.addr = internal unnamed_addr global i8* blockaddress(@label_address, %return), align 8
- define hidden i32 @label_address() "branch-target-enforcement" {
+ define hidden i32 @label_address() "branch-target-enforcement"="true" {
entry:
%0 = load i8*, i8** @label_address.addr, align 8
indirectbr i8* %0, [label %return, label %lab2]
@@ -79,7 +79,7 @@
ret i32 %merge2
}
- define hidden i32 @label_address_entry() "branch-target-enforcement" {
+ define hidden i32 @label_address_entry() "branch-target-enforcement"="true" {
entry:
%0 = load i8*, i8** @label_address.addr, align 8
indirectbr i8* %0, [label %return, label %lab2]
@@ -97,7 +97,7 @@
ret i32 %merge2
}
- define hidden i32 @debug_ptr_auth() "branch-target-enforcement" {
+ define hidden i32 @debug_ptr_auth() "branch-target-enforcement"="true" {
entry:
tail call void asm sideeffect "", "~{lr}"()
ret i32 0
diff --git a/llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll b/llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll
index 93cbc3b85bb4..20749f3efd47 100644
--- a/llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll
+++ b/llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll
@@ -61,4 +61,4 @@ declare dso_local void @e(...) local_unnamed_addr #0
declare dso_local i64 @llvm.aarch64.space(i32, i64) local_unnamed_addr #0
-attributes #0 = { nounwind "branch-target-enforcement" "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+v8.5a" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #0 = { nounwind "branch-target-enforcement"="true" "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+v8.5a" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-2fixup-blr-terminator.mir b/llvm/test/CodeGen/AArch64/machine-outliner-2fixup-blr-terminator.mir
index 2111704c0898..958c28879710 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-2fixup-blr-terminator.mir
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-2fixup-blr-terminator.mir
@@ -8,7 +8,7 @@
define void @f2() #0 { ret void }
define void @f3() #0 { ret void }
define void @f4() #0 { ret void }
- attributes #0 = { minsize noredzone "branch-target-enforcement" }
+ attributes #0 = { minsize noredzone "branch-target-enforcement"="true" }
...
---
name: f1
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-bti.mir b/llvm/test/CodeGen/AArch64/machine-outliner-bti.mir
index d15657ee4998..885c326fd91e 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-bti.mir
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-bti.mir
@@ -15,7 +15,7 @@
--- |
@g = hidden local_unnamed_addr global i32 0, align 4
- define hidden void @bar(void ()* nocapture %f) "branch-target-enforcement" {
+ define hidden void @bar(void ()* nocapture %f) "branch-target-enforcement"="true" {
entry:
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll b/llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll
index bc1521c6c80d..c30d31fa91b2 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll
@@ -5,7 +5,7 @@
@g = hidden global i32 0, align 4
-define hidden void @foo() minsize "branch-target-enforcement" {
+define hidden void @foo() minsize "branch-target-enforcement"="true" {
entry:
; CHECK: hint #34
; CHECK: b OUTLINED_FUNCTION_0
@@ -13,7 +13,7 @@ entry:
ret void
}
-define hidden void @bar() minsize "branch-target-enforcement" {
+define hidden void @bar() minsize "branch-target-enforcement"="true" {
entry:
; CHECK: hint #34
; CHECK: b OUTLINED_FUNCTION_0
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
index 798cd72c5be6..fdd1d63b267b 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll
@@ -4,7 +4,7 @@
; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ
@x = common dso_local global i32 0, align 4
-attributes #0 = { "branch-target-enforcement" }
+attributes #0 = { "branch-target-enforcement"="true" }
; Both attributes present in a file with no functions.
; ASM: .word 3221225472
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
index 747836cab832..9757dec1f844 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll
@@ -8,7 +8,7 @@ entry:
ret i32 0
}
-attributes #0 = { "branch-target-enforcement" }
+attributes #0 = { "branch-target-enforcement"="true" }
; BTI attribute present
; ASM: .word 3221225472
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
index ad222e8b4e48..5082fa01f1d4 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll
@@ -8,7 +8,7 @@ entry:
ret i32 0
}
-attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" }
+attributes #0 = { "branch-target-enforcement"="true" "sign-return-address"="non-leaf" }
; Both attribute present
; ASM: .word 3221225472
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
index 83da5305e249..5d81669db7ff 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll
@@ -13,9 +13,9 @@ entry:
ret i32 0
}
-attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" }
+attributes #0 = { "branch-target-enforcement"="true" "sign-return-address"="non-leaf" }
-attributes #1 = { "branch-target-enforcement" }
+attributes #1 = { "branch-target-enforcement"="true" }
; Only the common atttribute (BTI)
; ASM: .word 3221225472
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
index 083f8b38f676..942eb5970c59 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll
@@ -13,7 +13,7 @@ entry:
ret i32 0
}
-attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" }
+attributes #0 = { "branch-target-enforcement"="true" "sign-return-address"="non-leaf" }
attributes #1 = { "sign-return-address"="all" }
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
index 6768252feff1..67f0b2b71c4c 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll
@@ -15,7 +15,7 @@ entry:
attributes #0 = { "sign-return-address"="non-leaf" }
-attributes #1 = { "branch-target-enforcement" }
+attributes #1 = { "branch-target-enforcement"="true" }
; No common attribute, no note section
; ASM: warning: not setting BTI in feature flags
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
index 44545b413ad4..8549491186f5 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll
@@ -11,7 +11,7 @@ entry:
declare dso_local i32 @g()
-attributes #0 = { "branch-target-enforcement" }
+attributes #0 = { "branch-target-enforcement"="true" }
; Declarations don't prevent setting BTI
; ASM: .word 3221225472
diff --git a/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-1.ll b/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-1.ll
new file mode 100644
index 000000000000..98dcd16fadd4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-1.ll
@@ -0,0 +1,33 @@
+;; RUN: llc %s -o -| FileCheck %s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux"
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }]
+
+define dso_local i32 @f() #0 {
+entry:
+ ret i32 0
+}
+;; CHECK-LABEL: f:
+;; CHECK: hint #34
+
+declare void @__asan_init()
+declare void @__asan_version_mismatch_check_v8()
+
+define internal void @asan.module_ctor() {
+ call void @__asan_init()
+ call void @__asan_version_mismatch_check_v8()
+ ret void
+}
+;; CHECK-LABEL: asan.module_ctor:
+;; CHECK: hint #34
+
+attributes #0 = { noinline nounwind optnone sanitize_address uwtable "branch-target-enforcement"="true" }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 4, !"branch-target-enforcement", i32 1}
+!2 = !{i32 4, !"sign-return-address", i32 0}
+!3 = !{i32 4, !"sign-return-address-all", i32 0}
+!4 = !{i32 4, !"sign-return-address-with-bkey", i32 0}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll b/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll
new file mode 100644
index 000000000000..b302a3d55add
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll
@@ -0,0 +1,71 @@
+;; RUN: llc --mattr=+v8.3a %s -o - | FileCheck %s
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux"
+
+ at __llvm_gcov_ctr = internal global [1 x i64] zeroinitializer
+ at 0 = private unnamed_addr constant [7 x i8] c"m.gcda\00", align 1
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__llvm_gcov_init, i8* null }]
+
+define dso_local i32 @f() local_unnamed_addr #0 {
+entry:
+ ret i32 0
+}
+;; CHECK-LABEL: f:
+;; CHECK: pacibsp
+
+declare void @llvm_gcda_start_file(i8*, i32, i32) local_unnamed_addr
+
+declare void @llvm_gcda_emit_function(i32, i32, i32) local_unnamed_addr
+
+declare void @llvm_gcda_emit_arcs(i32, i64*) local_unnamed_addr
+
+declare void @llvm_gcda_summary_info() local_unnamed_addr
+
+declare void @llvm_gcda_end_file() local_unnamed_addr
+
+define internal void @__llvm_gcov_writeout() unnamed_addr #1 {
+entry:
+ tail call void @llvm_gcda_start_file(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @0, i64 0, i64 0), i32 875575338, i32 0)
+ tail call void @llvm_gcda_emit_function(i32 0, i32 0, i32 0)
+ tail call void @llvm_gcda_emit_arcs(i32 1, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__llvm_gcov_ctr, i64 0, i64 0))
+ tail call void @llvm_gcda_summary_info()
+ tail call void @llvm_gcda_end_file()
+ ret void
+}
+;; CHECK-LABEL: __llvm_gcov_writeout:
+;; CHECK: .cfi_b_key_frame
+;; CHECK-NEXT: pacibsp
+;; CHECK-NEXT: .cfi_negate_ra_state
+
+define internal void @__llvm_gcov_reset() unnamed_addr #2 {
+entry:
+ store i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__llvm_gcov_ctr, i64 0, i64 0), align 8
+ ret void
+}
+;; CHECK-LABEL: __llvm_gcov_reset:
+;; CHECK: pacibsp
+
+declare void @llvm_gcov_init(void ()*, void ()*) local_unnamed_addr
+
+define internal void @__llvm_gcov_init() unnamed_addr #1 {
+entry:
+ tail call void @llvm_gcov_init(void ()* nonnull @__llvm_gcov_writeout, void ()* nonnull @__llvm_gcov_reset)
+ ret void
+}
+;; CHECK-LABEL: __llvm_gcov_init:
+;; CHECK: .cfi_b_key_frame
+;; CHECK-NEXT: pacibsp
+;; CHECK-NEXT: .cfi_negate_ra_state
+
+attributes #0 = { norecurse nounwind readnone "sign-return-address"="all" "sign-return-address-key"="b_key" }
+attributes #1 = { noinline }
+attributes #2 = { nofree noinline norecurse nounwind writeonly }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !{i32 1, !"wchar_size", i32 4}
+!2 = !{i32 1, !"branch-target-enforcement", i32 0}
+!3 = !{i32 1, !"sign-return-address", i32 1}
+!4 = !{i32 1, !"sign-return-address-all", i32 1}
+!5 = !{i32 1, !"sign-return-address-with-bkey", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/pacbti-module-attrs.ll b/llvm/test/CodeGen/AArch64/pacbti-module-attrs.ll
new file mode 100644
index 000000000000..8fe20d5ebbb1
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/pacbti-module-attrs.ll
@@ -0,0 +1,77 @@
+;; RUN: llc -mtriple=aarch64-eabi -mattr=+v8.5a %s -o - | FileCheck %s
+
+declare i32 @g(i32) #5
+
+define i32 @f0(i32 %x) #0 {
+entry:
+ %call = tail call i32 @g(i32 %x) #5
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+;; CHECK-LABEL: f0:
+;; CHECK-NOT: bti
+;; CHECK-NOT: pacia
+;; CHECK-NOT: reta
+
+define i32 @f1(i32 %x) #1 {
+entry:
+ %call = tail call i32 @g(i32 %x) #5
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+;; CHECK-LABEL: f1:
+;; CHECK: bti c
+;; CHECK-NOT: reta
+
+define i32 @f2(i32 %x) #2 {
+entry:
+ %call = tail call i32 @g(i32 %x) #5
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+;; CHECK-LABEL: f2:
+;; CHECK: paciasp
+;; CHECK: retaa
+
+define i32 @f3(i32 %x) #3 {
+entry:
+ %call = tail call i32 @g(i32 %x) #5
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+;; CHECK-LABEL: f3:
+;; CHECK: pacibsp
+;; CHECK: retab
+
+define i32 @f4(i32 %x) #4 {
+entry:
+ ret i32 1
+}
+;; CHECK-LABEL: f4:
+;; CHECK: paciasp
+;; CHECK: retaa
+
+define i32 @f5(i32 %x) #5 {
+entry:
+ %call = tail call i32 @g(i32 %x) #5
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+;; CHECK-LABEL: f5:
+;; CHECK: paciasp
+;; CHECK: retaa
+
+attributes #0 = { nounwind "branch-target-enforcement"="false" "sign-return-address"="none" }
+attributes #1 = { nounwind "branch-target-enforcement"="true" "sign-return-address"="none" }
+attributes #2 = { nounwind "branch-target-enforcement"="false" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" }
+attributes #3 = { nounwind "branch-target-enforcement"="false" "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" }
+attributes #4 = { nounwind "branch-target-enforcement"="false" "sign-return-address"="all" "sign-return-address-key"="a_key" }
+attributes #5 = { nounwind }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"branch-target-enforcement", i32 1}
+!2 = !{i32 1, !"sign-return-address", i32 1}
+!3 = !{i32 1, !"sign-return-address-all", i32 0}
+!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
diff --git a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
index 4d55eb8bb7d2..01c3d2b0666a 100644
--- a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
+++ b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
@@ -1,6 +1,6 @@
; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s
-define void @f0() "patchable-function-entry"="0" "branch-target-enforcement" {
+define void @f0() "patchable-function-entry"="0" "branch-target-enforcement"="true" {
; CHECK-LABEL: f0:
; CHECK-NEXT: .Lfunc_begin0:
; CHECK: // %bb.0:
@@ -12,7 +12,7 @@ define void @f0() "patchable-function-entry"="0" "branch-target-enforcement" {
;; -fpatchable-function-entry=1 -mbranch-protection=bti
;; For M=0, place the label .Lpatch0 after the initial BTI.
-define void @f1() "patchable-function-entry"="1" "branch-target-enforcement" {
+define void @f1() "patchable-function-entry"="1" "branch-target-enforcement"="true" {
; CHECK-LABEL: f1:
; CHECK-NEXT: .Lfunc_begin1:
; CHECK-NEXT: .cfi_startproc
@@ -28,7 +28,7 @@ define void @f1() "patchable-function-entry"="1" "branch-target-enforcement" {
}
;; -fpatchable-function-entry=2,1 -mbranch-protection=bti
-define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="1" "branch-target-enforcement" {
+define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="1" "branch-target-enforcement"="true" {
; CHECK-LABEL: .type f2_1, at function
; CHECK-NEXT: .Ltmp0:
; CHECK-NEXT: nop
@@ -50,7 +50,7 @@ define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="
;; -fpatchable-function-entry=1 -mbranch-protection=bti
;; For M=0, don't create .Lpatch0 if the initial instruction is not BTI,
;; even if other basic blocks may have BTI.
-define internal void @f1i(i64 %v) "patchable-function-entry"="1" "branch-target-enforcement" {
+define internal void @f1i(i64 %v) "patchable-function-entry"="1" "branch-target-enforcement"="true" {
; CHECK-LABEL: f1i:
; CHECK-NEXT: .Lfunc_begin3:
; CHECK: // %bb.0:
More information about the cfe-commits
mailing list