In implementing the ACLE read/write system register builtins it was observed that leaving argument type checking to be done at expand-time meant that poorly-formed function calls were being "fixed" by certain optimization passes, meaning bad code wasn't being properly picked up in checking.
Example: const char *regname = "amcgcr_el0"; long long a = __builtin_aarch64_rsr64 (regname); is reduced by the ccp1 pass to long long a = __builtin_aarch64_rsr64 ("amcgcr_el0"); As these functions require an argument of STRING_CST type, there needs to be a check carried out by the front-end capable of picking this up. The introduced `check_general_builtin_call' function will be called by the TARGET_CHECK_BUILTIN_CALL hook whenever a call to a builtin belonging to the AARCH64_BUILTIN_GENERAL category is encountered, carrying out any appropriate checks associated with a particular builtin function code. gcc/ChangeLog: * gcc/config/aarch64/aarch64-builtins.cc (check_general_builtin_call): New. * gcc/config/aarch64/aarch64-c.cc (aarch64_check_builtin_call): Add check_general_builtin_call call. * gcc/config/aarch64/aarch64-protos.h (check_general_builtin_call): New. gcc/testsuite/ChangeLog: * gcc/testsuite/gcc.target/aarch64/acle/rwsr-2.c: New. --- gcc/config/aarch64/aarch64-builtins.cc | 33 +++++++++++++++++++ gcc/config/aarch64/aarch64-c.cc | 4 +-- gcc/config/aarch64/aarch64-protos.h | 3 ++ .../gcc.target/aarch64/acle/rwsr-2.c | 15 +++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-2.c diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index d8bb2a989a5..6734361f4f4 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -2126,6 +2126,39 @@ aarch64_general_builtin_decl (unsigned code, bool) return aarch64_builtin_decls[code]; } +bool +check_general_builtin_call (location_t location, vec<location_t>, + unsigned int code, tree fndecl, + unsigned int nargs ATTRIBUTE_UNUSED, tree *args) +{ + switch (code) + { + case AARCH64_RSR: + case AARCH64_RSRP: + case AARCH64_RSR64: + case AARCH64_RSRF: + case AARCH64_RSRF64: + case AARCH64_WSR: + case AARCH64_WSRP: + case AARCH64_WSR64: + case AARCH64_WSRF: + case AARCH64_WSRF64: + if (TREE_CODE (args[0]) == VAR_DECL + || TREE_CODE (TREE_TYPE (args[0])) != POINTER_TYPE + || TREE_CODE (TREE_OPERAND (TREE_OPERAND (args[0], 0) , 0)) + != STRING_CST) + { + const char *fn_name, *err_msg; + fn_name = IDENTIFIER_POINTER (DECL_NAME (fndecl)); + err_msg = "first argument to %<%s%> must be a string literal"; + error_at (location, err_msg, fn_name); + return false; + } + } + /* Default behavior. */ + return true; +} + typedef enum { SIMD_ARG_COPY_TO_REG, diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 578ec6f45b0..6e2b83b8308 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -338,8 +338,8 @@ aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc, switch (code & AARCH64_BUILTIN_CLASS) { case AARCH64_BUILTIN_GENERAL: - return true; - + return check_general_builtin_call (loc, arg_loc, subcode, orig_fndecl, + nargs, args); case AARCH64_BUILTIN_SVE: return aarch64_sve::check_builtin_call (loc, arg_loc, subcode, orig_fndecl, nargs, args); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index a134e2fcf8e..9ef96ff511f 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -990,6 +990,9 @@ tree aarch64_general_builtin_rsqrt (unsigned int); void handle_arm_acle_h (void); void handle_arm_neon_h (void); +bool check_general_builtin_call (location_t, vec<location_t>, unsigned int, + tree, unsigned int, tree *); + namespace aarch64_sve { void init_builtins (); void handle_arm_sve_h (); diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-2.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-2.c new file mode 100644 index 00000000000..72e5fb75b21 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-2.c @@ -0,0 +1,15 @@ +/* Test the __arm_[r,w]sr ACLE intrinsics family. */ +/* Ensure that illegal behavior is rejected by the compiler. */ + +/* { dg-do compile } */ +/* { dg-options "-O3 -march=armv8.4-a" } */ + +#include <arm_acle.h> + +void +test_non_const_sysreg_name () +{ + const char *regname = "trcseqstr"; + long long a = __arm_rsr64 (regname); /* { dg-error "first argument to '__builtin_aarch64_rsr64' must be a string literal" } */ + __arm_wsr64 (regname, a); /* { dg-error "first argument to '__builtin_aarch64_wsr64' must be a string literal" } */ +} -- 2.41.0