[clang] 1f08b08 - [clang][ARM] Emit warnings when PACBTI-M is used with unsupported architectures

Amilendra Kodithuwakku via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 28 02:00:05 PST 2022


Author: Amilendra Kodithuwakku
Date: 2022-01-28T09:59:58Z
New Revision: 1f08b0867412d5696ed624a2da78bdba2cc672c3

URL: https://github.com/llvm/llvm-project/commit/1f08b0867412d5696ed624a2da78bdba2cc672c3
DIFF: https://github.com/llvm/llvm-project/commit/1f08b0867412d5696ed624a2da78bdba2cc672c3.diff

LOG: [clang][ARM] Emit warnings when PACBTI-M is used with unsupported architectures

Branch protection in M-class is supported by
 - Armv8.1-M.Main
 - Armv8-M.Main
 - Armv7-M

Attempting to enable this for other architectures, either by
command-line (e.g -mbranch-protection=bti) or by target attribute
in source code (e.g.  __attribute__((target("branch-protection=..."))) )
will generate a warning.

In both cases function attributes related to branch protection will not
be emitted. Regardless of the warning, module level attributes related to
branch protection will be emitted when it is enabled via the command-line.

The following people also contributed to this patch:
- Victor Campos

Reviewed By: chill

Differential Revision: https://reviews.llvm.org/D115501

Added: 
    clang/test/Frontend/arm-branch-protection-default-arch.c
    clang/test/Frontend/arm-ignore-branch-protection-option.c
    clang/test/Sema/arm-branch-protection-attr-warn.c
    clang/test/Sema/arm-branch-protection.c

Modified: 
    clang/include/clang/Basic/DiagnosticCommonKinds.td
    clang/include/clang/Basic/TargetInfo.h
    clang/lib/Basic/Targets/AArch64.cpp
    clang/lib/Basic/Targets/AArch64.h
    clang/lib/Basic/Targets/ARM.cpp
    clang/lib/Basic/Targets/ARM.h
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/CodeGen/TargetInfo.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/test/CodeGen/arm-branch-protection-attr-2.c
    clang/test/CodeGen/arm_acle.c
    clang/test/Driver/aarch64-security-options.c
    clang/test/Driver/arm-security-options.c
    clang/test/Frontend/arm-invalid-branch-protection.c
    llvm/include/llvm/ADT/Triple.h
    llvm/unittests/ADT/TripleTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index fe4ac5ed6cb03..5ea55b0fd31ba 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -145,6 +145,13 @@ def warn_conflicting_nullability_attr_overriding_param_types : Warning<
 def err_nullability_conflicting : Error<
   "nullability specifier %0 conflicts with existing specifier %1">;
 
+def warn_target_unsupported_branch_protection_option: Warning <
+  "ignoring '-mbranch-protection=' option because the '%0' architecture does not support it">,
+  InGroup<BranchProtection>;
+
+def warn_target_unsupported_branch_protection_attribute: Warning <
+  "ignoring the 'branch-protection' attribute because the '%0' architecture does not support it">,
+  InGroup<BranchProtection>;
 }
 
 // OpenCL Section 6.8.g

diff  --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 686a365b8c12d..642c8500364bb 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1289,9 +1289,15 @@ class TargetInfo : public virtual TransferrableTargetInfo,
     bool BranchTargetEnforcement = false;
   };
 
+  /// Determine if the Architecture in this TargetInfo supports branch
+  /// protection
+  virtual bool isBranchProtectionSupportedArch(StringRef Arch) const {
+    return false;
+  }
+
   /// Determine if this TargetInfo supports the given branch protection
   /// specification
-  virtual bool validateBranchProtection(StringRef Spec,
+  virtual bool validateBranchProtection(StringRef Spec, StringRef Arch,
                                         BranchProtectionInfo &BPI,
                                         StringRef &Err) const {
     Err = "";

diff  --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 8e23cc4c421a5..34bdb58dffc1c 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -138,7 +138,7 @@ bool AArch64TargetInfo::setABI(const std::string &Name) {
   return true;
 }
 
-bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
+bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
                                                  BranchProtectionInfo &BPI,
                                                  StringRef &Err) const {
   llvm::ARM::ParsedBranchProtection PBP;

diff  --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index ebddce0c1c73e..9e22aeaff251f 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -70,8 +70,9 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
   StringRef getABI() const override;
   bool setABI(const std::string &Name) override;
 
-  bool validateBranchProtection(StringRef, BranchProtectionInfo &,
-                                StringRef &) const override;
+  bool validateBranchProtection(StringRef Spec, StringRef Arch,
+                                BranchProtectionInfo &BPI,
+                                StringRef &Err) const override;
 
   bool isValidCPUName(StringRef Name) const override;
   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;

diff  --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp
index 478a0233398dc..9c9d198e8f324 100644
--- a/clang/lib/Basic/Targets/ARM.cpp
+++ b/clang/lib/Basic/Targets/ARM.cpp
@@ -371,13 +371,34 @@ bool ARMTargetInfo::setABI(const std::string &Name) {
   return false;
 }
 
-bool ARMTargetInfo::validateBranchProtection(StringRef Spec,
+bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {
+  llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(Arch);
+  if (CPUArch == llvm::ARM::ArchKind::INVALID)
+    CPUArch = llvm::ARM::parseArch(getTriple().getArchName());
+
+  if (CPUArch == llvm::ARM::ArchKind::INVALID)
+    return false;
+
+  StringRef ArchFeature = llvm::ARM::getArchName(CPUArch);
+  auto a =
+      llvm::Triple(ArchFeature, getTriple().getVendorName(),
+                   getTriple().getOSName(), getTriple().getEnvironmentName());
+
+  StringRef SubArch = llvm::ARM::getSubArch(CPUArch);
+  llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(SubArch);
+  return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);
+}
+
+bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,
                                              BranchProtectionInfo &BPI,
                                              StringRef &Err) const {
   llvm::ARM::ParsedBranchProtection PBP;
   if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
     return false;
 
+  if (!isBranchProtectionSupportedArch(Arch))
+    return false;
+
   BPI.SignReturnAddr =
       llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
           .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)

diff  --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h
index f074dac57f9b3..e85336b6e32f9 100644
--- a/clang/lib/Basic/Targets/ARM.h
+++ b/clang/lib/Basic/Targets/ARM.h
@@ -126,8 +126,10 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
   StringRef getABI() const override;
   bool setABI(const std::string &Name) override;
 
-  bool validateBranchProtection(StringRef, BranchProtectionInfo &,
-                                StringRef &) const override;
+  bool isBranchProtectionSupportedArch(StringRef Arch) const override;
+  bool validateBranchProtection(StringRef Spec, StringRef Arch,
+                                BranchProtectionInfo &BPI,
+                                StringRef &Err) const override;
 
   // FIXME: This should be based on Arch attributes, not CPU names.
   bool

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index d534cf182f5a7..2346176a15628 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -731,6 +731,7 @@ void CodeGenModule::Release() {
                               "tag-stack-memory-buildattr", 1);
 
   if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
+      Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
       Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
       Arch == llvm::Triple::aarch64_be) {
     getModule().addModuleFlag(llvm::Module::Error, "branch-target-enforcement",
@@ -742,11 +743,9 @@ void CodeGenModule::Release() {
     getModule().addModuleFlag(llvm::Module::Error, "sign-return-address-all",
                               LangOpts.isSignReturnAddressScopeAll());
 
-    if (Arch != llvm::Triple::thumb && Arch != llvm::Triple::thumbeb) {
-      getModule().addModuleFlag(llvm::Module::Error,
-                                "sign-return-address-with-bkey",
-                                !LangOpts.isSignReturnAddressWithAKey());
-    }
+    getModule().addModuleFlag(llvm::Module::Error,
+                              "sign-return-address-with-bkey",
+                              !LangOpts.isSignReturnAddressWithAKey());
   }
 
   if (!CodeGenOpts.MemoryProfileOutput.empty()) {

diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index fb81169003fc0..3b5389ee36702 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -5563,8 +5563,8 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
 
     TargetInfo::BranchProtectionInfo BPI;
     StringRef Error;
-    (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
-                                                   BPI, Error);
+    (void)CGM.getTarget().validateBranchProtection(
+        Attr.BranchProtection, Attr.Architecture, BPI, Error);
     assert(Error.empty());
 
     auto *Fn = cast<llvm::Function>(GV);
@@ -6377,17 +6377,36 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
       if (!Attr.BranchProtection.empty()) {
         TargetInfo::BranchProtectionInfo BPI;
         StringRef DiagMsg;
-        (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
-                                                       BPI, DiagMsg);
-
-        static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
-        assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
-               "Unexpected SignReturnAddressScopeKind");
-        Fn->addFnAttr("sign-return-address",
-                      SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
-
-        Fn->addFnAttr("branch-target-enforcement",
-                      BPI.BranchTargetEnforcement ? "true" : "false");
+        StringRef Arch = Attr.Architecture.empty()
+                             ? CGM.getTarget().getTargetOpts().CPU
+                             : Attr.Architecture;
+        if (!CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
+                                                      Arch, BPI, DiagMsg)) {
+          CGM.getDiags().Report(
+              D->getLocation(),
+              diag::warn_target_unsupported_branch_protection_attribute)
+              << Arch;
+        } else {
+          static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
+          assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
+                 "Unexpected SignReturnAddressScopeKind");
+          Fn->addFnAttr(
+              "sign-return-address",
+              SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
+
+          Fn->addFnAttr("branch-target-enforcement",
+                        BPI.BranchTargetEnforcement ? "true" : "false");
+        }
+      } else if (CGM.getLangOpts().BranchTargetEnforcement ||
+                 CGM.getLangOpts().hasSignReturnAddress()) {
+        // If the Branch Protection attribute is missing, validate the target
+        // Architecture attribute against Branch Protection command line
+        // settings.
+        if (!CGM.getTarget().isBranchProtectionSupportedArch(Attr.Architecture))
+          CGM.getDiags().Report(
+              D->getLocation(),
+              diag::warn_target_unsupported_branch_protection_attribute)
+              << Attr.Architecture;
       }
     }
 

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 4386e395bc6ce..7acb70e0a3966 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1627,7 +1627,7 @@ void RenderARMABI(const Driver &D, const llvm::Triple &Triple,
 }
 }
 
-static void CollectARMPACBTIOptions(const Driver &D, const ArgList &Args,
+static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
                                     ArgStringList &CmdArgs, bool isAArch64) {
   const Arg *A = isAArch64
                      ? Args.getLastArg(options::OPT_msign_return_address_EQ,
@@ -1636,6 +1636,12 @@ static void CollectARMPACBTIOptions(const Driver &D, const ArgList &Args,
   if (!A)
     return;
 
+  const Driver &D = TC.getDriver();
+  const llvm::Triple &Triple = TC.getEffectiveTriple();
+  if (!(isAArch64 || (Triple.isArmT32() && Triple.isArmMClass())))
+    D.Diag(diag::warn_target_unsupported_branch_protection_option)
+        << Triple.getArchName();
+
   StringRef Scope, Key;
   bool IndirectBranches;
 
@@ -1713,8 +1719,7 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
   AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
 
   // Enable/disable return address signing and indirect branch targets.
-  CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
-                          false /*isAArch64*/);
+  CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, false /*isAArch64*/);
 }
 
 void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@@ -1841,8 +1846,7 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
   }
 
   // Enable/disable return address signing and indirect branch targets.
-  CollectARMPACBTIOptions(getToolChain().getDriver(), Args, CmdArgs,
-                          true /*isAArch64*/);
+  CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/);
 
   // Handle -msve_vector_bits=<bits>
   if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index f04236ab96c31..e76e7c608e0c6 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3393,7 +3393,8 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
   if (ParsedAttrs.BranchProtection.empty())
     return false;
   if (!Context.getTargetInfo().validateBranchProtection(
-          ParsedAttrs.BranchProtection, BPI, DiagMsg)) {
+          ParsedAttrs.BranchProtection, ParsedAttrs.Architecture, BPI,
+          DiagMsg)) {
     if (DiagMsg.empty())
       return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
              << Unsupported << None << "branch-protection" << Target;

diff  --git a/clang/test/CodeGen/arm-branch-protection-attr-2.c b/clang/test/CodeGen/arm-branch-protection-attr-2.c
index 2a309cdb9b04a..18a15b8534b50 100644
--- a/clang/test/CodeGen/arm-branch-protection-attr-2.c
+++ b/clang/test/CodeGen/arm-branch-protection-attr-2.c
@@ -1,9 +1,9 @@
 // REQUIRES: arm-registered-target
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=none %s          | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret       %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf  %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
-// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -S -emit-llvm -o - -mbranch-protection=bti %s           | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=none %s          | FileCheck %s --check-prefix=CHECK --check-prefix=NONE
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret       %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf  %s | FileCheck %s --check-prefix=CHECK --check-prefix=ALL
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=bti %s           | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
 
 // Check there are no branch protection function attributes
 

diff  --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c
index 9be0e50136fe4..99c281633fc3b 100644
--- a/clang/test/CodeGen/arm_acle.c
+++ b/clang/test/CodeGen/arm_acle.c
@@ -1535,12 +1535,12 @@ uint32_t test_crc32cd(uint32_t a, uint64_t b) {
 /* 10.1 Special register intrinsics */
 // AArch32-LABEL: @test_rsr(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !5)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32RSR32:!.*]])
 // AArch32-NEXT:    ret i32 [[TMP0]]
 //
 // AArch64-LABEL: @test_rsr(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR:!.*]])
 // AArch64-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
 // AArch64-NEXT:    ret i32 [[TMP1]]
 //
@@ -1554,12 +1554,12 @@ uint32_t test_rsr() {
 
 // AArch32-LABEL: @test_rsr64(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !6)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A32RSR64:!.*]])
 // AArch32-NEXT:    ret i64 [[TMP0]]
 //
 // AArch64-LABEL: @test_rsr64(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    ret i64 [[TMP0]]
 //
 uint64_t test_rsr64() {
@@ -1572,13 +1572,13 @@ uint64_t test_rsr64() {
 
 // AArch32-LABEL: @test_rsrp(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !7)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32SYSREG:!.*]])
 // AArch32-NEXT:    [[TMP1:%.*]] = inttoptr i32 [[TMP0]] to i8*
 // AArch32-NEXT:    ret i8* [[TMP1]]
 //
 // AArch64-LABEL: @test_rsrp(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !9)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64SYSREG:!.*]])
 // AArch64-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to i8*
 // AArch64-NEXT:    ret i8* [[TMP1]]
 //
@@ -1588,13 +1588,13 @@ void *test_rsrp() {
 
 // AArch32-LABEL: @test_wsr(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !5, i32 [[V:%.*]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32RSR32]], i32 [[V:%.*]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsr(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[TMP0:%.*]] = zext i32 [[V:%.*]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP0]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP0]])
 // AArch64-NEXT:    ret void
 //
 void test_wsr(uint32_t v) {
@@ -1607,12 +1607,12 @@ void test_wsr(uint32_t v) {
 
 // AArch32-LABEL: @test_wsr64(
 // AArch32-NEXT:  entry:
-// AArch32-NEXT:    call void @llvm.write_register.i64(metadata !6, i64 [[V:%.*]])
+// AArch32-NEXT:    call void @llvm.write_register.i64(metadata [[A32RSR64]], i64 [[V:%.*]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsr64(
 // AArch64-NEXT:  entry:
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[V:%.*]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[V:%.*]])
 // AArch64-NEXT:    ret void
 //
 void test_wsr64(uint64_t v) {
@@ -1626,13 +1626,13 @@ void test_wsr64(uint64_t v) {
 // AArch32-LABEL: @test_wsrp(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[TMP0:%.*]] = ptrtoint i8* [[V:%.*]] to i32
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !7, i32 [[TMP0]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32SYSREG]], i32 [[TMP0]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrp(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[TMP0:%.*]] = ptrtoint i8* [[V:%.*]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !9, i64 [[TMP0]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64SYSREG]], i64 [[TMP0]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrp(void *v) {
@@ -1642,7 +1642,7 @@ void test_wsrp(void *v) {
 // AArch32-LABEL: @test_rsrf(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[REF_TMP:%.*]] = alloca i32, align 4
-// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata !5)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.read_volatile_register.i32(metadata [[A32RSR32]])
 // AArch32-NEXT:    store i32 [[TMP0]], i32* [[REF_TMP]], align 4
 // AArch32-NEXT:    [[TMP1:%.*]] = bitcast i32* [[REF_TMP]] to float*
 // AArch32-NEXT:    [[TMP2:%.*]] = load float, float* [[TMP1]], align 4
@@ -1651,7 +1651,7 @@ void test_wsrp(void *v) {
 // AArch64-LABEL: @test_rsrf(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[REF_TMP:%.*]] = alloca i32, align 4
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
 // AArch64-NEXT:    store i32 [[TMP1]], i32* [[REF_TMP]], align 4
 // AArch64-NEXT:    [[TMP2:%.*]] = bitcast i32* [[REF_TMP]] to float*
@@ -1669,7 +1669,7 @@ float test_rsrf() {
 // AArch32-LABEL: @test_rsrf64(
 // AArch32-NEXT:  entry:
 // AArch32-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !6)
+// AArch32-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A32RSR64]])
 // AArch32-NEXT:    store i64 [[TMP0]], i64* [[REF_TMP]], align 8
 // AArch32-NEXT:    [[TMP1:%.*]] = bitcast i64* [[REF_TMP]] to double*
 // AArch32-NEXT:    [[TMP2:%.*]] = load double, double* [[TMP1]], align 8
@@ -1678,7 +1678,7 @@ float test_rsrf() {
 // AArch64-LABEL: @test_rsrf64(
 // AArch64-NEXT:  entry:
 // AArch64-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata !8)
+// AArch64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.read_volatile_register.i64(metadata [[A64RSR]])
 // AArch64-NEXT:    store i64 [[TMP0]], i64* [[REF_TMP]], align 8
 // AArch64-NEXT:    [[TMP1:%.*]] = bitcast i64* [[REF_TMP]] to double*
 // AArch64-NEXT:    [[TMP2:%.*]] = load double, double* [[TMP1]], align 8
@@ -1698,7 +1698,7 @@ double test_rsrf64() {
 // AArch32-NEXT:    store float [[V:%.*]], float* [[V_ADDR]], align 4
 // AArch32-NEXT:    [[TMP0:%.*]] = bitcast float* [[V_ADDR]] to i32*
 // AArch32-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
-// AArch32-NEXT:    call void @llvm.write_register.i32(metadata !5, i32 [[TMP1]])
+// AArch32-NEXT:    call void @llvm.write_register.i32(metadata [[A32RSR32]], i32 [[TMP1]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrf(
@@ -1708,7 +1708,7 @@ double test_rsrf64() {
 // AArch64-NEXT:    [[TMP0:%.*]] = bitcast float* [[V_ADDR]] to i32*
 // AArch64-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
 // AArch64-NEXT:    [[TMP2:%.*]] = zext i32 [[TMP1]] to i64
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP2]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP2]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrf(float v) {
@@ -1725,7 +1725,7 @@ void test_wsrf(float v) {
 // AArch32-NEXT:    store double [[V:%.*]], double* [[V_ADDR]], align 8
 // AArch32-NEXT:    [[TMP0:%.*]] = bitcast double* [[V_ADDR]] to i64*
 // AArch32-NEXT:    [[TMP1:%.*]] = load i64, i64* [[TMP0]], align 8
-// AArch32-NEXT:    call void @llvm.write_register.i64(metadata !6, i64 [[TMP1]])
+// AArch32-NEXT:    call void @llvm.write_register.i64(metadata [[A32RSR64]], i64 [[TMP1]])
 // AArch32-NEXT:    ret void
 //
 // AArch64-LABEL: @test_wsrf64(
@@ -1734,7 +1734,7 @@ void test_wsrf(float v) {
 // AArch64-NEXT:    store double [[V:%.*]], double* [[V_ADDR]], align 8
 // AArch64-NEXT:    [[TMP0:%.*]] = bitcast double* [[V_ADDR]] to i64*
 // AArch64-NEXT:    [[TMP1:%.*]] = load i64, i64* [[TMP0]], align 8
-// AArch64-NEXT:    call void @llvm.write_register.i64(metadata !8, i64 [[TMP1]])
+// AArch64-NEXT:    call void @llvm.write_register.i64(metadata [[A64RSR]], i64 [[TMP1]])
 // AArch64-NEXT:    ret void
 //
 void test_wsrf64(double v) {
@@ -1786,9 +1786,9 @@ int test_rndrrs(uint64_t *__addr) {
 }
 #endif
 
-// AArch32: !5 = !{!"cp1:2:c3:c4:5"}
-// AArch32: !6 = !{!"cp1:2:c3"}
-// AArch32: !7 = !{!"sysreg"}
+// AArch32: [[A32RSR32]] = !{!"cp1:2:c3:c4:5"}
+// AArch32: [[A32RSR64]] = !{!"cp1:2:c3"}
+// AArch32: [[A32SYSREG]] = !{!"sysreg"}
 
-// AArch64: !8 = !{!"1:2:3:4:5"}
-// AArch64: !9 = !{!"sysreg"}
+// AArch64: [[A64RSR]] = !{!"1:2:3:4:5"}
+// AArch64: [[A64SYSREG]] = !{!"sysreg"}

diff  --git a/clang/test/Driver/aarch64-security-options.c b/clang/test/Driver/aarch64-security-options.c
index ae2e3130cf6af..6ea4b8ae58385 100644
--- a/clang/test/Driver/aarch64-security-options.c
+++ b/clang/test/Driver/aarch64-security-options.c
@@ -1,31 +1,33 @@
 // Check the -msign-return-address= option, which has a required argument to
 // select scope.
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=none                             2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf                         2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=all                              2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-ALL      --check-prefix=KEY-A --check-prefix=BTE-OFF
+// RUN: FileCheck %s --check-prefix=RA-ALL      --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN
 
 // -mbranch-protection with standard
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=standard                                2>&1 | \
-// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON --check-prefix=WARN
 
 // If the -msign-return-address and -mbranch-protection are both used, the
 // right-most one controls return address signing.
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=non-leaf -mbranch-protection=none     2>&1 | \
-// RUN: FileCheck %s --check-prefix=CONFLICT
+// RUN: FileCheck %s --check-prefix=CONFLICT --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=pac-ret -msign-return-address=none     2>&1 | \
-// RUN: FileCheck %s --check-prefix=CONFLICT
+// RUN: FileCheck %s --check-prefix=CONFLICT --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -msign-return-address=foo     2>&1 | \
-// RUN: FileCheck %s --check-prefix=BAD-RA-PROTECTION
+// RUN: FileCheck %s --check-prefix=BAD-RA-PROTECTION --check-prefix=WARN
 
 // RUN: %clang -target aarch64--none-eabi -c %s -### -mbranch-protection=bar     2>&1 | \
-// RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION
+// RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION --check-prefix=WARN
+
+// WARN-NOT: warning: ignoring '-mbranch-protection=' option because the 'aarch64' architecture does not support it [-Wbranch-protection]
 
 // RA-OFF: "-msign-return-address=none"
 // RA-NON-LEAF: "-msign-return-address=non-leaf"

diff  --git a/clang/test/Driver/arm-security-options.c b/clang/test/Driver/arm-security-options.c
index 99f9d15b943f4..79367d7bbb965 100644
--- a/clang/test/Driver/arm-security-options.c
+++ b/clang/test/Driver/arm-security-options.c
@@ -1,48 +1,80 @@
 // Check the -mbranch-protection=option
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+leaf+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+leaf+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-B --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-B --check-prefix=BTE-OFF
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-B --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bti+pac-ret+leaf+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bti+pac-ret+leaf+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-B --check-prefix=BTE-ON
 
 // -mbranch-protection with standard
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=standard 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=standard 2>&1 | \
 // RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=bar 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=bar 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-BP-PROTECTION
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+bti+b-key 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+bti+b-key 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-B-KEY-COMBINATION
 
-// RUN: %clang -target arm-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+bti+leaf 2>&1 | \
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -c %s -### -mbranch-protection=pac-ret+bti+leaf 2>&1 | \
 // RUN: FileCheck %s --check-prefix=BAD-LEAF-COMBINATION
 
+// -mbranch-protection with supported architectures other than v8.1-m.main
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.main -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7e-m -c %s -### -mbranch-protection=pac-ret 2>&1 | \
+// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF
+
+// -mbranch-protection with unsupported architectures
+// RUN: %clang -target arm-arm-none-eabi -march=armv6-m -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-m.base -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-a -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv8-r -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-a -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+/// RUN: %clang -target arm-arm-none-eabi -march=armv7-a -mthumb -c %s -### -mbranch-protection=bti 2>&1 | \
+/// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-r -c %s -### -mbranch-protection=bti 2>&1 | \
+// RUN: FileCheck %s --check-prefix=INCOMPATIBLE-ARCH
+
 // RA-OFF: "-msign-return-address=none"
 // RA-NON-LEAF: "-msign-return-address=non-leaf"
 // RA-ALL: "-msign-return-address=all"
@@ -57,3 +89,5 @@
 
 // BAD-B-KEY-COMBINATION: invalid branch protection option 'b-key' in '-mbranch-protection={{.*}}'
 // BAD-LEAF-COMBINATION: invalid branch protection option 'leaf' in '-mbranch-protection={{.*}}'
+
+// INCOMPATIBLE-ARCH: ignoring '-mbranch-protection=' option because the '{{.*}}' architecture does not support it

diff  --git a/clang/test/Frontend/arm-branch-protection-default-arch.c b/clang/test/Frontend/arm-branch-protection-default-arch.c
new file mode 100644
index 0000000000000..1f12cba1820d6
--- /dev/null
+++ b/clang/test/Frontend/arm-branch-protection-default-arch.c
@@ -0,0 +1,27 @@
+// REQUIRES: arm-registered-target
+
+/// Check warning for
+// RUN: %clang -target arm-arm-none-eabi %s -S -o - 2>&1 | FileCheck %s
+
+__attribute__((target("branch-protection=bti"))) void f1() {}
+__attribute__((target("branch-protection=pac-ret"))) void f2() {}
+__attribute__((target("branch-protection=bti+pac-ret"))) void f3() {}
+__attribute__((target("branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti"))) void f1() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=pac-ret"))) void f2() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti+pac-ret"))) void f3() {}
+
+// CHECK: warning: unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored [-Wignored-attributes]
+// CHECK-NEXT: __attribute__((target("branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+/// Check there are no branch protection function attributes
+
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address"
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address-key"
+// CHECK-NOT:  attributes { {{.*}} "branch-target-enforcement"

diff  --git a/clang/test/Frontend/arm-ignore-branch-protection-option.c b/clang/test/Frontend/arm-ignore-branch-protection-option.c
new file mode 100644
index 0000000000000..9a7c0aca25d3c
--- /dev/null
+++ b/clang/test/Frontend/arm-ignore-branch-protection-option.c
@@ -0,0 +1,18 @@
+// REQUIRES: arm-registered-target
+
+/// Check warning for
+// RUN: %clang -target arm-arm-none-eabi -march=armv7-m -mbranch-protection=bti %s -S -emit-llvm -o - 2>&1 | FileCheck %s
+
+__attribute__((target("arch=cortex-m0"))) void f() {}
+
+// CHECK: warning: ignoring the 'branch-protection' attribute because the 'cortex-m0' architecture does not support it [-Wbranch-protection]
+// CHECK-NEXT: __attribute__((target("arch=cortex-m0"))) void f() {}
+
+/// Check there are no branch protection function attributes
+
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address"
+// CHECK-NOT:  attributes { {{.*}} "sign-return-address-key"
+// CHECK-NOT:  attributes { {{.*}} "branch-target-enforcement"
+
+/// Check that there are branch protection module attributes despite the warning.
+// CHECK: !{i32 1, !"branch-target-enforcement", i32 1}

diff  --git a/clang/test/Frontend/arm-invalid-branch-protection.c b/clang/test/Frontend/arm-invalid-branch-protection.c
index f7bbd5941b024..ef43f5770ea30 100644
--- a/clang/test/Frontend/arm-invalid-branch-protection.c
+++ b/clang/test/Frontend/arm-invalid-branch-protection.c
@@ -1,7 +1,7 @@
 // REQUIRES: arm-registered-target
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=bti+pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
-// RUN: %clang -target arm-arm-none-eabi -mbranch-protection=bti+pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=bti+pac-ret+b-key -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -mbranch-protection=bti+pac-ret+b-key+leaf -c %s -o /dev/null 2>&1 | FileCheck %s
 
 // CHECK: warning: invalid branch protection option 'b-key' in '-mbranch-protection={{[a-z+-]*}}' [-Wbranch-protection]

diff  --git a/clang/test/Sema/arm-branch-protection-attr-warn.c b/clang/test/Sema/arm-branch-protection-attr-warn.c
new file mode 100644
index 0000000000000..2a380eed940b2
--- /dev/null
+++ b/clang/test/Sema/arm-branch-protection-attr-warn.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple thumbv6m -verify -fsyntax-only %s
+
+// expected-warning at +1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti"))) void f1() {}
+
+// expected-warning at +1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=pac-ret"))) void f2() {}
+
+// expected-warning at +1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti+pac-ret"))) void f3() {}
+
+// expected-warning at +1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-m0,branch-protection=bti+pac-ret+leaf"))) void f4() {}
+
+// expected-warning at +1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
+__attribute__((target("arch=cortex-a17,thumb,branch-protection=bti+pac-ret+leaf"))) void f5() {}

diff  --git a/clang/test/Sema/arm-branch-protection.c b/clang/test/Sema/arm-branch-protection.c
new file mode 100644
index 0000000000000..4fcfeb5df535e
--- /dev/null
+++ b/clang/test/Sema/arm-branch-protection.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple thumbv6m -verify -fsyntax-only %s
+
+// expected-no-diagnostics
+// Armv8.1-M.Main
+__attribute__((target("arch=cortex-m55,branch-protection=bti"))) void f1() {}
+__attribute__((target("arch=cortex-m55,branch-protection=pac-ret"))) void f2() {}
+__attribute__((target("arch=cortex-m55,branch-protection=bti+pac-ret"))) void f3() {}
+__attribute__((target("arch=cortex-m55,branch-protection=bti+pac-ret+leaf"))) void f4() {}
+// Armv8-M.Main
+__attribute__((target("arch=cortex-m33,branch-protection=bti"))) void f5() {}
+__attribute__((target("arch=cortex-m33,branch-protection=pac-ret"))) void f6() {}
+__attribute__((target("arch=cortex-m33,branch-protection=bti+pac-ret"))) void f7() {}
+__attribute__((target("arch=cortex-m33,branch-protection=bti+pac-ret+leaf"))) void f8() {}
+// Armv7-M
+__attribute__((target("arch=cortex-m3,branch-protection=bti"))) void f9() {}
+__attribute__((target("arch=cortex-m3,branch-protection=pac-ret"))) void f10() {}
+__attribute__((target("arch=cortex-m3,branch-protection=bti+pac-ret"))) void f11() {}
+__attribute__((target("arch=cortex-m3,branch-protection=bti+pac-ret+leaf"))) void f12() {}
+// Armv7E-M
+__attribute__((target("arch=cortex-m4,branch-protection=bti"))) void f13() {}
+__attribute__((target("arch=cortex-m4,branch-protection=pac-ret"))) void f14() {}
+__attribute__((target("arch=cortex-m4,branch-protection=bti+pac-ret"))) void f15() {}
+__attribute__((target("arch=cortex-m4,branch-protection=bti+pac-ret+leaf"))) void f16() {}

diff  --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
index 0f0a7b08b5d30..f002e75e0cc73 100644
--- a/llvm/include/llvm/ADT/Triple.h
+++ b/llvm/include/llvm/ADT/Triple.h
@@ -721,6 +721,41 @@ class Triple {
            isOSBinFormatELF();
   }
 
+  /// Tests whether the target is T32.
+  bool isArmT32() const {
+    switch (auto SubArch = getSubArch()) {
+    case Triple::ARMSubArch_v8m_baseline:
+    case Triple::ARMSubArch_v7s:
+    case Triple::ARMSubArch_v7k:
+    case Triple::ARMSubArch_v7ve:
+    case Triple::ARMSubArch_v6:
+    case Triple::ARMSubArch_v6m:
+    case Triple::ARMSubArch_v6k:
+    case Triple::ARMSubArch_v6t2:
+    case Triple::ARMSubArch_v5:
+    case Triple::ARMSubArch_v5te:
+    case Triple::ARMSubArch_v4t:
+      return false;
+    default:
+      return true;
+    }
+  }
+
+  /// Tests whether the target is an M-class.
+  bool isArmMClass() const {
+    switch (auto SubArch = getSubArch()) {
+    case Triple::ARMSubArch_v6m:
+    case Triple::ARMSubArch_v7m:
+    case Triple::ARMSubArch_v7em:
+    case Triple::ARMSubArch_v8m_mainline:
+    case Triple::ARMSubArch_v8m_baseline:
+    case Triple::ARMSubArch_v8_1m_mainline:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   /// Tests whether the target is AArch64 (little and big endian).
   bool isAArch64() const {
     return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be ||

diff  --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp
index 4853dfc13558b..3006ab6d40e85 100644
--- a/llvm/unittests/ADT/TripleTest.cpp
+++ b/llvm/unittests/ADT/TripleTest.cpp
@@ -1702,4 +1702,148 @@ TEST(TripleTest, ParseARMArch) {
     EXPECT_EQ(Triple::AArch64SubArch_arm64e, T.getSubArch());
   }
 }
+
+TEST(TripleTest, isArmT32) {
+  // Not isArmT32
+  {
+    Triple T = Triple("thumbv6m");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8m.base");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7s");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7k");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7ve");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6m");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6k");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv6t2");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv5");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv5te");
+    EXPECT_FALSE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv4t");
+    EXPECT_FALSE(T.isArmT32());
+  }
+
+  // isArmT32
+  {
+    Triple T = Triple("arm");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7m");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv7em");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8m.main");
+    EXPECT_TRUE(T.isArmT32());
+  }
+  {
+    Triple T = Triple("armv8.1m.main");
+    EXPECT_TRUE(T.isArmT32());
+  }
+}
+
+TEST(TripleTest, isArmMClass) {
+  // not M-class
+  {
+    Triple T = Triple("armv7s");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7k");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7ve");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6k");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv6t2");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv5");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv5te");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv4t");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("arm");
+    EXPECT_FALSE(T.isArmMClass());
+  }
+
+  // is M-class
+  {
+    Triple T = Triple("armv6m");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7m");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv7em");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8m.base");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8m.main");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+  {
+    Triple T = Triple("armv8.1m.main");
+    EXPECT_TRUE(T.isArmMClass());
+  }
+}
 } // end anonymous namespace


        


More information about the cfe-commits mailing list