diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -384,7 +384,9 @@ getTriple().getOSName(), getTriple().getEnvironmentName()); - return a.isArmT32(); + 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, diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -6398,8 +6398,7 @@ BPI.BranchTargetEnforcement ? "true" : "false"); } } else if (CGM.getLangOpts().BranchTargetEnforcement || - CGM.getLangOpts().hasSignReturnAddress() || - CGM.getLangOpts().isSignReturnAddressScopeAll()) { + CGM.getLangOpts().hasSignReturnAddress()) { // If the Branch Protection attribute is missing, validate the target // Architecture attribute against Branch Protection command line // settings. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1637,7 +1637,7 @@ const Driver &D = TC.getDriver(); const llvm::Triple &Triple = TC.getEffectiveTriple(); - if (!Triple.isArmT32()) + if (!(isAArch64 || (Triple.isArmT32() && Triple.isArmMClass()))) D.Diag(diag::warn_target_unsupported_branch_protection_option) << Triple.getArchName(); diff --git a/clang/test/Driver/aarch64-security-options.c b/clang/test/Driver/aarch64-security-options.c --- 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 --- a/clang/test/Driver/arm-security-options.c +++ b/clang/test/Driver/arm-security-options.c @@ -69,6 +69,9 @@ // 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 diff --git a/clang/test/Sema/arm-branch-protection-attr-warn.c b/clang/test/Sema/arm-branch-protection-attr-warn.c --- a/clang/test/Sema/arm-branch-protection-attr-warn.c +++ b/clang/test/Sema/arm-branch-protection-attr-warn.c @@ -11,3 +11,6 @@ // expected-warning@+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@+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/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -723,20 +723,39 @@ /// Tests whether the target is T32. bool isArmT32() const { - if (!isARM()) + 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; - - if (getArch() == Triple::aarch64) + default: return true; + } + } - if (isThumb()) + /// 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; - - return (getSubArch() == Triple::ARMSubArch_v8_1m_mainline) || - (getSubArch() == Triple::ARMSubArch_v8m_mainline) || - (getSubArch() == Triple::ARMSubArch_v7m) || - (getSubArch() == Triple::ARMSubArch_v7em); + 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 --- a/llvm/unittests/ADT/TripleTest.cpp +++ b/llvm/unittests/ADT/TripleTest.cpp @@ -1702,4 +1702,148 @@ 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