v6 -> v7 changes:

* committed the patch after fixing the documentation.
-----------------
v5 -> v6 changes:

* Fix the wrong conditional check in aarch64_valid_sysreg_name_p.

---------------
v4 -> v5 changes:

* Modify check_effective_target_aarch64_sysreg_guarding_ok
  to check all the ELF targets have the require assembler
  support for -menable-sysreg-checking flag.
* Update the dg-do directive in the tests.
-----------------
v3 -> v4 changes:

 * Fixed target in check_effective_target_aarch64_sysreg_guarding_ok
------------------
v2 -> v3 changes:

* Replaced the explicit bool cast with a != 0 check when testing
  bitmasks.
* Restricted the inlined assembly tests to run only on ELF and
  Linux targets.
* Added an effective-target check to ensure the assembler (binutils)
  supports the -menable-sysreg-checking flag before running the
  inlined assembly tests.
-------------------
v1 -> v2 changes:

* Fixed the wrong conditional check.
* Fixed the typos in the testcases.
* Added support for inline assembly checking.
* Added new tests for inline assembly sysreg checking.
-------------------

Hi All,

In the current Binutils we have disabled the feature gating for sysreg
by default and we have introduced a new flag "-menable-sysreg-checking"
to renable some of this checking.

However in GCC, we have disabled the feature gating of sysreg to read/write
intrinsics __arm_[wr]sr* and we have not added any mechanism to check the
feature gating if needed similar to Binutils.

This patch adds the support for the flag "-menable-sysreg-checking" which
renables some of the feature checking of sysreg to read/write intrinsics
__arm_[wr]sr* similar to Binutils.

For inline assembly, sysreg checks are not performed by CC1 and are
instead delegated to the assembler. By default, the assembler does not
perform these checks either. With this patch, the -menable-sysreg-checking
flag passed to the compiler will also be propagated to the assembler,
enabling sysreg checking for inline assembly.

Regression tested on aarch64-none-elf and aarch64-linux-gnu and
found no regressions.

Ok for trunk?

Regards,
Srinath.

gcc/ChangeLog:

        * config/aarch64/aarch64-elf.h (ASM_SPEC): Update the macro.
        * config/aarch64/aarch64.cc (aarch64_valid_sysreg_name_p):
        Add feature check condition.
        (aarch64_retrieve_sysreg): Likewise.
        * config/aarch64/aarch64.opt (menable-sysreg-checking):
        Define new flag.
        * doc/invoke.texi (menable-sysreg-checking): Document new flag.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/acle/asm-inlined-sysreg-1.c: New test.
        * gcc.target/aarch64/acle/asm-inlined-sysreg-2.c: Likewise.
        * gcc.target/aarch64/acle/rwsr-gated-1.c: Likewise.
        * gcc.target/aarch64/acle/rwsr-gated-2.c: Likewise.
        * lib/target-supports.exp
        (check_effective_target_aarch64_sysreg_guarding_ok): Check
        assembler support of -menable-sysreg-checking flag.
---
 gcc/config/aarch64/aarch64-elf.h              |  1 +
 gcc/config/aarch64/aarch64.cc                 |  7 ++++-
 gcc/config/aarch64/aarch64.opt                |  5 ++++
 gcc/doc/invoke.texi                           |  6 ++++
 .../aarch64/acle/asm-inlined-sysreg-1.c       | 28 ++++++++++++++++++
 .../aarch64/acle/asm-inlined-sysreg-2.c       | 29 +++++++++++++++++++
 .../gcc.target/aarch64/acle/rwsr-gated-1.c    | 14 +++++++++
 .../gcc.target/aarch64/acle/rwsr-gated-2.c    | 14 +++++++++
 gcc/testsuite/lib/target-supports.exp         | 10 +++++++
 9 files changed, 113 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c

diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h
index f6ebb723715..57c5a319d7c 100644
--- a/gcc/config/aarch64/aarch64-elf.h
+++ b/gcc/config/aarch64/aarch64-elf.h
@@ -136,6 +136,7 @@
 #define ASM_SPEC "\
 %{mbig-endian:-EB} \
 %{mlittle-endian:-EL} \
+%{menable-sysreg-checking} \
 %(asm_cpu_spec)" \
 ASM_MABI_SPEC
 #endif
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index f28d670b55f..b86064148fe 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -31663,7 +31663,9 @@ aarch64_valid_sysreg_name_p (const char *regname)
   const sysreg_t *sysreg = aarch64_lookup_sysreg_map (regname);
   if (sysreg == NULL)
     return aarch64_is_implem_def_reg (regname);
-  return true;
+
+  return (!aarch64_enable_sysreg_guarding
+         || ((~aarch64_isa_flags & sysreg->arch_reqs) == 0));
 }
 
 /* Return the generic sysreg specification for a valid system register
@@ -31686,6 +31688,9 @@ aarch64_retrieve_sysreg (const char *regname, bool 
write_p, bool is128op)
   if ((write_p && (sysreg->properties & F_REG_READ))
       || (!write_p && (sysreg->properties & F_REG_WRITE)))
     return NULL;
+  if (aarch64_enable_sysreg_guarding
+      && ((~aarch64_isa_flags & sysreg->arch_reqs) != 0))
+    return NULL;
   return sysreg->encoding;
 }
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 8aae953e60d..fc3f632d93b 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -82,6 +82,11 @@ mbig-endian
 Target RejectNegative Mask(BIG_END)
 Assume target CPU is configured as big endian.
 
+menable-sysreg-checking
+Target RejectNegative Var(aarch64_enable_sysreg_guarding) Init(0)
+Generates an error message if an attempt is made to access a system register
+which is not available on the target architecture.
+
 mgeneral-regs-only
 Target RejectNegative Mask(GENERAL_REGS_ONLY) Save
 Generate code which uses only the general registers.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9c64acb5daf..189b2662012 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -826,6 +826,7 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{AArch64 Options} (@ref{AArch64 Options})
 @gccoptlist{-mabi=@var{name}  -mbig-endian  -mlittle-endian
+-menable-sysreg-checking
 -mgeneral-regs-only
 -mcmodel=tiny  -mcmodel=small  -mcmodel=large
 -mstrict-align  -mno-strict-align
@@ -22159,6 +22160,11 @@ The @samp{ilp32} model is deprecated.
 Generate big-endian code.  This is the default when GCC is configured for an
 @samp{aarch64_be-*-*} target.
 
+@opindex menable-sysreg-checking
+@item -menable-sysreg-checking
+Generates an error message if an attempt is made to access a system register
+which is not available on the target architecture.
+
 @opindex mgeneral-regs-only
 @item -mgeneral-regs-only
 Generate code which uses only the general-purpose registers.  This will prevent
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c 
b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c
new file mode 100644
index 00000000000..3912c75b315
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c
@@ -0,0 +1,28 @@
+/* { dg-do assemble { target elf } } */
+/* { dg-require-effective-target aarch64_sysreg_guarding_ok } */
+/* { dg-additional-options "-march=armv8-a -menable-sysreg-checking -###" } */
+/* Ensure the system registers passed through inline assembly are rejected by
+   assembler when guarding is enabled through "-menable-sysreg-checking" 
command
+   line flag and proper feature flags are not passed.  */
+
+#define INPUT 1
+
+static inline void
+read_write_using_sysreg (int mode)
+{
+  int b;
+
+  /* write to gcspr_el0.  */
+  asm volatile ("msr gcspr_el0, %[r]" ::[r] "r" (mode):);
+
+  /* Read from gcspr_el0.  */
+  asm volatile ("mrs %[r], gcspr_el0" :[r] "=r"(b)::);
+}
+
+int main()
+{
+  read_write_using_sysreg (INPUT);
+  return 0;
+}
+/* { dg-prune-output "^(COMPILER_PATH|LIBRARY_PATH|COLLECT_GCC_OPTIONS)=.*" } 
*/
+/* { dg-message ".*\/.*as .*-menable-sysreg-checking" "assembler options" 
{target aarch64-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c 
b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c
new file mode 100644
index 00000000000..e6c96005705
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c
@@ -0,0 +1,29 @@
+/* { dg-do assemble { target elf} } */
+/* { dg-require-effective-target aarch64_sysreg_guarding_ok } */
+/* { dg-options "-save-temps -O2 -menable-sysreg-checking -march=armv8-a+gcs" 
} */
+/* Ensure that system registers passed through inline assembly are properly
+   gated on the feature flags, when the guarding is enabled through
+   "-menable-sysreg-checking" command line flag.  */
+
+#define INPUT 1
+
+static inline void
+read_write_using_sysreg (int mode)
+{
+  int b;
+
+  /* write to gcspr_el0.  */
+  asm volatile ("msr gcspr_el0, %[r]" ::[r] "r" (mode):);
+
+  /* Read from gcspr_el0.  */
+  asm volatile ("mrs %[r], gcspr_el0" :[r] "=r"(b)::);
+}
+
+int main()
+{
+  read_write_using_sysreg (INPUT);
+  return 0;
+}
+
+/* { { dg-final { scan-assembler {msr\s+gcspr_el0,\s+x0} } } */
+/* { { dg-final { scan-assembler {mrs\s+x0,\s+gcspr_el0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c 
b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c
new file mode 100644
index 00000000000..35a54597cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-menable-sysreg-checking -march=armv8-a+sve2+sme" } */
+/* Ensure that system registers are properly gated on the feature flags, when
+   the guarding is enabled through "-menable-sysreg-checking" command line
+   flag.  */
+
+#include <arm_acle.h>
+
+uint64_t
+foo (uint64_t a)
+{
+  __arm_wsr64 ("zcr_el1", a); /* { { dg-final { scan-assembler 
"msr\ts3_0_c1_c2_0, x0" } } */
+  return __arm_rsr64 ("smcr_el1"); /* { { dg-final { scan-assembler "mrs\tx0, 
s3_0_c1_c2_6" } } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c 
b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c
new file mode 100644
index 00000000000..49e9769f710
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-menable-sysreg-checking -march=armv8-a" } */
+/* Ensure the system registers are rejected by compiler when guarding is
+   enabled through "-menable-sysreg-checking" command line flag and proper
+   feature flags are not passed.  */
+
+#include <arm_acle.h>
+
+uint64_t
+foo (uint64_t a)
+{
+  __arm_wsr64 ("zcr_el1", a); /* { dg-error "invalid system register name 
'zcr_el1'" } */
+  return __arm_rsr64 ("smcr_el1"); /* { dg-error "invalid system register name 
'smcr_el1'" } */
+}
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 4ee8d12362d..2d45ddaadc0 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -12573,6 +12573,16 @@ foreach { aarch64_ext } $exts_sve2 {
     }]
 }
 
+proc check_effective_target_aarch64_sysreg_guarding_ok { } {
+    if { [istarget aarch64*-*-*] && [check_effective_target_elf] } {
+       return [check_no_compiler_messages aarch64_assembler object {
+           __asm__ ("msr\ts3_3_c9_c13_4, x0");
+       } "-menable-sysreg-checking"]
+    } else {
+       return 0
+    }
+}
+
 proc check_effective_target_aarch64_asm_sve2p1_ok { } {
     if { [istarget aarch64*-*-*] } {
        return [check_no_compiler_messages aarch64_sve2p1_assembler object {
-- 
2.25.1

Reply via email to