[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
This commit is contained in:
Amilendra Kodithuwakku 2022-01-28 09:58:08 +00:00
parent a584b1a4d1
commit 1f08b08674
21 changed files with 445 additions and 86 deletions

View File

@ -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

View File

@ -1289,9 +1289,15 @@ public:
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 = "";

View File

@ -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;

View File

@ -70,8 +70,9 @@ public:
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;

View File

@ -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)

View File

@ -126,8 +126,10 @@ public:
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

View File

@ -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()) {

View File

@ -5563,8 +5563,8 @@ public:
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 @@ public:
if (!Attr.BranchProtection.empty()) {
TargetInfo::BranchProtectionInfo BPI;
StringRef DiagMsg;
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
BPI, DiagMsg);
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)]);
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");
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;
}
}

View File

@ -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)) {

View File

@ -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;

View File

@ -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

View File

@ -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"}

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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}

View File

@ -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]

View File

@ -0,0 +1,16 @@
// RUN: %clang_cc1 -triple thumbv6m -verify -fsyntax-only %s
// expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}}
__attribute__((target("arch=cortex-m0,branch-protection=bti"))) void f1() {}
// expected-warning@+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@+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@+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() {}

View File

@ -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() {}

View File

@ -721,6 +721,41 @@ public:
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 ||

View File

@ -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