diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -145,6 +145,13 @@ 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; + +def warn_target_unsupported_branch_protection_attribute: Warning < + "ignoring the 'branch-protection' attribute because the '%0' architecture does not support it">, + InGroup; } // OpenCL Section 6.8.g diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1288,9 +1288,15 @@ 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.h b/clang/lib/Basic/Targets/AArch64.h --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -67,7 +67,7 @@ StringRef getABI() const override; bool setABI(const std::string &Name) override; - bool validateBranchProtection(StringRef, BranchProtectionInfo &, + bool validateBranchProtection(StringRef, StringRef, BranchProtectionInfo &, StringRef &) const override; bool isValidCPUName(StringRef Name) const override; diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -137,7 +137,7 @@ 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/ARM.h b/clang/lib/Basic/Targets/ARM.h --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -125,7 +125,8 @@ StringRef getABI() const override; bool setABI(const std::string &Name) override; - bool validateBranchProtection(StringRef, BranchProtectionInfo &, + bool isBranchProtectionSupportedArch(StringRef) const override; + bool validateBranchProtection(StringRef, StringRef, BranchProtectionInfo &, StringRef &) const override; // FIXME: This should be based on Arch attributes, not CPU names. 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 @@ -367,13 +367,30 @@ return false; } -bool ARMTargetInfo::validateBranchProtection(StringRef Spec, +bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const { + if (Arch.empty()) + return false; + + llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(Arch); + if (ArchKind != llvm::ARM::ArchKind::ARMV8_1MMainline && + ArchKind != llvm::ARM::ArchKind::ARMV8MMainline && + ArchKind != llvm::ARM::ArchKind::ARMV7M && + ArchKind != llvm::ARM::ArchKind::ARMV7EM) + return false; + + return true; +} + +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 (!Arch.empty() && !isBranchProtectionSupportedArch(Arch)) + return false; + BPI.SignReturnAddr = llvm::StringSwitch(PBP.Scope) .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -726,6 +726,7 @@ "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", @@ -737,11 +738,9 @@ 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 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5563,8 +5563,8 @@ 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(GV); @@ -6377,17 +6377,38 @@ 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(BPI.SignReturnAddr) <= 2 && - "Unexpected SignReturnAddressScopeKind"); - Fn->addFnAttr("sign-return-address", - SignReturnAddrStr[static_cast(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(BPI.SignReturnAddr) <= 2 && + "Unexpected SignReturnAddressScopeKind"); + Fn->addFnAttr( + "sign-return-address", + SignReturnAddrStr[static_cast(BPI.SignReturnAddr)]); + + Fn->addFnAttr("branch-target-enforcement", + BPI.BranchTargetEnforcement ? "true" : "false"); + } + } else if (CGM.getLangOpts().BranchTargetEnforcement || + CGM.getLangOpts().hasSignReturnAddress() || + CGM.getLangOpts().isSignReturnAddressScopeAll()) { + // If the Branch Protection attribute is missing, validate the target + // Architecture attribute against Branch Protection command line + // settings. + if (!Attr.Architecture.empty() && + !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 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1603,7 +1603,7 @@ } } -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, @@ -1612,6 +1612,18 @@ if (!A) return; + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); + if (!isAArch64 && + (!Triple.isThumb() || + (Triple.getSubArch() != llvm::Triple::ARMSubArch_v8_1m_mainline && + Triple.getSubArch() != llvm::Triple::ARMSubArch_v8m_mainline && + Triple.getSubArch() != llvm::Triple::ARMSubArch_v7m && + Triple.getSubArch() != llvm::Triple::ARMSubArch_v7em))) { + D.Diag(diag::warn_target_unsupported_branch_protection_option) + << Triple.getArchName(); + } + StringRef Scope, Key; bool IndirectBranches; @@ -1689,8 +1701,7 @@ 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, @@ -1830,8 +1841,7 @@ } // 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= 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 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3275,7 +3275,8 @@ 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 --- 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 --- a/clang/test/CodeGen/arm_acle.c +++ b/clang/test/CodeGen/arm_acle.c @@ -1535,7 +1535,7 @@ /* 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 !9) // AArch32-NEXT: ret i32 [[TMP0]] // // AArch64-LABEL: @test_rsr( @@ -1554,7 +1554,7 @@ // 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 !10) // AArch32-NEXT: ret i64 [[TMP0]] // // AArch64-LABEL: @test_rsr64( @@ -1572,7 +1572,7 @@ // 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 !11) // AArch32-NEXT: [[TMP1:%.*]] = inttoptr i32 [[TMP0]] to i8* // AArch32-NEXT: ret i8* [[TMP1]] // @@ -1588,7 +1588,7 @@ // 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 !9, i32 [[V:%.*]]) // AArch32-NEXT: ret void // // AArch64-LABEL: @test_wsr( @@ -1607,7 +1607,7 @@ // 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 !10, i64 [[V:%.*]]) // AArch32-NEXT: ret void // // AArch64-LABEL: @test_wsr64( @@ -1626,7 +1626,7 @@ // 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 !11, i32 [[TMP0]]) // AArch32-NEXT: ret void // // AArch64-LABEL: @test_wsrp( @@ -1642,7 +1642,7 @@ // 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 !9) // 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 @@ -1669,7 +1669,7 @@ // 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 !10) // 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 @@ -1698,7 +1698,7 @@ // 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 !9, i32 [[TMP1]]) // AArch32-NEXT: ret void // // AArch64-LABEL: @test_wsrf( @@ -1725,7 +1725,7 @@ // 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 !10, i64 [[TMP1]]) // AArch32-NEXT: ret void // // AArch64-LABEL: @test_wsrf64( @@ -1786,9 +1786,9 @@ } #endif -// AArch32: !5 = !{!"cp1:2:c3:c4:5"} -// AArch32: !6 = !{!"cp1:2:c3"} -// AArch32: !7 = !{!"sysreg"} +// AArch32: !9 = !{!"cp1:2:c3:c4:5"} +// AArch32: !10 = !{!"cp1:2:c3"} +// AArch32: !11 = !{!"sysreg"} // AArch64: !8 = !{!"1:2:3:4:5"} // AArch64: !9 = !{!"sysreg"} 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 @@ -1,48 +1,77 @@ // 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-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 +86,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 --- /dev/null +++ b/clang/test/Frontend/arm-branch-protection-default-arch.c @@ -0,0 +1,31 @@ +// 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: ignoring the 'branch-protection' attribute because the 'arm7tdmi' architecture does not support it [-Wbranch-protection] +// CHECK-NEXT: __attribute__((target("branch-protection=bti"))) void f1() {} + +// CHECK: warning: ignoring the 'branch-protection' attribute because the 'arm7tdmi' architecture does not support it [-Wbranch-protection] +// CHECK-NEXT: __attribute__((target("branch-protection=pac-ret"))) void f2() {} + +// CHECK: warning: ignoring the 'branch-protection' attribute because the 'arm7tdmi' architecture does not support it [-Wbranch-protection] +// CHECK-NEXT: __attribute__((target("branch-protection=bti+pac-ret"))) void f3() {} + +// CHECK: warning: ignoring the 'branch-protection' attribute because the 'arm7tdmi' architecture does not support it [-Wbranch-protection] +// 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 --- /dev/null +++ b/clang/test/Frontend/arm-ignore-branch-protection-option.c @@ -0,0 +1,20 @@ +// 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 --- 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 --- /dev/null +++ b/clang/test/Sema/arm-branch-protection-attr-warn.c @@ -0,0 +1,13 @@ +// 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() {} diff --git a/clang/test/Sema/arm-branch-protection.c b/clang/test/Sema/arm-branch-protection.c new file mode 100644 --- /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() {}