amilendra created this revision. amilendra added reviewers: chill, vhscampos. Herald added a subscriber: kristof.beyls. Herald added a reviewer: aaron.ballman. amilendra requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D115501 Files: 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/arm-security-options.c clang/test/Frontend/arm-branch-protection-default-arch.c clang/test/Frontend/arm-ignore-branch-protection-option.c clang/test/Frontend/arm-invalid-branch-protection.c clang/test/Sema/arm-branch-protection-attr-warn.c clang/test/Sema/arm-branch-protection.c
Index: clang/test/Sema/arm-branch-protection.c =================================================================== --- /dev/null +++ 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() {} Index: clang/test/Sema/arm-branch-protection-attr-warn.c =================================================================== --- /dev/null +++ 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() {} Index: clang/test/Frontend/arm-invalid-branch-protection.c =================================================================== --- clang/test/Frontend/arm-invalid-branch-protection.c +++ 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] Index: clang/test/Frontend/arm-ignore-branch-protection-option.c =================================================================== --- /dev/null +++ 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} Index: clang/test/Frontend/arm-branch-protection-default-arch.c =================================================================== --- /dev/null +++ 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" + + + Index: clang/test/Driver/arm-security-options.c =================================================================== --- clang/test/Driver/arm-security-options.c +++ 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 Index: clang/test/CodeGen/arm_acle.c =================================================================== --- clang/test/CodeGen/arm_acle.c +++ 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"} Index: clang/test/CodeGen/arm-branch-protection-attr-2.c =================================================================== --- clang/test/CodeGen/arm-branch-protection-attr-2.c +++ 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 Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ 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; Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ 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=<bits> if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ 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<llvm::Function>(GV); @@ -6377,17 +6377,37 @@ 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() || + CGM.getLangOpts().isSignReturnAddressScopeAll()) { + // 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; } } Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ 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()) { Index: clang/lib/Basic/Targets/ARM.h =================================================================== --- clang/lib/Basic/Targets/ARM.h +++ 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. Index: clang/lib/Basic/Targets/ARM.cpp =================================================================== --- clang/lib/Basic/Targets/ARM.cpp +++ 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 true; + + 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 (!isBranchProtectionSupportedArch(Arch)) + return false; + BPI.SignReturnAddr = llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope) .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf) Index: clang/lib/Basic/Targets/AArch64.h =================================================================== --- clang/lib/Basic/Targets/AArch64.h +++ 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; Index: clang/lib/Basic/Targets/AArch64.cpp =================================================================== --- clang/lib/Basic/Targets/AArch64.cpp +++ 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; Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ 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 = ""; Index: clang/include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticCommonKinds.td +++ 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<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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits