aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorVictor Do Nascimento <victor.donascimento@arm.com>2023-07-10 20:16:07 +0100
committerVictor Do Nascimento <victor.donascimento@arm.com>2023-12-06 10:39:14 +0000
commit5af697d72d79db7ad5713c18dea8f52cfc79612f (patch)
tree43682a7b91b33a4a6ff413813844ec07428d9593 /gcc
parentfc42900d21abd5eacb7537c3c8ffc5278d510195 (diff)
downloadgcc-5af697d72d79db7ad5713c18dea8f52cfc79612f.zip
gcc-5af697d72d79db7ad5713c18dea8f52cfc79612f.tar.gz
gcc-5af697d72d79db7ad5713c18dea8f52cfc79612f.tar.bz2
aarch64: Add front-end argument type checking for target builtins
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: * config/aarch64/aarch64-builtins.cc (aarch64_general_check_builtin_call): New. * config/aarch64/aarch64-c.cc (aarch64_check_builtin_call): Add `aarch64_general_check_builtin_call' call. * config/aarch64/aarch64-protos.h (aarch64_general_check_builtin_call): New. gcc/testsuite/ChangeLog: * gcc.target/aarch64/acle/rwsr-3.c: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/aarch64/aarch64-builtins.cc31
-rw-r--r--gcc/config/aarch64/aarch64-c.cc4
-rw-r--r--gcc/config/aarch64/aarch64-protos.h4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/acle/rwsr-3.c18
4 files changed, 55 insertions, 2 deletions
diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
index a004e06..f780b10 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -2127,6 +2127,37 @@ aarch64_general_builtin_decl (unsigned code, bool)
return aarch64_builtin_decls[code];
}
+bool
+aarch64_general_check_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:
+ tree addr = STRIP_NOPS (args[0]);
+ if (TREE_CODE (TREE_TYPE (addr)) != POINTER_TYPE
+ || TREE_CODE (addr) != ADDR_EXPR
+ || TREE_CODE (TREE_OPERAND (addr, 0)) != STRING_CST)
+ {
+ error_at (location, "first argument to %qD must be a string literal",
+ fndecl);
+ 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 dd4b325..18422bb 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -394,8 +394,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 aarch64_general_check_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 9e09cf7..60ff61f 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -1002,6 +1002,10 @@ tree aarch64_general_builtin_rsqrt (unsigned int);
void handle_arm_acle_h (void);
void handle_arm_neon_h (void);
+bool aarch64_general_check_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-3.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-3.c
new file mode 100644
index 0000000..aadd04a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-3.c
@@ -0,0 +1,18 @@
+/* Test the __arm_[r,w]sr ACLE intrinsics family. */
+/* Ensure that illegal behavior is rejected by the compiler. */
+
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -O3 -march=armv8-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" } */
+
+ long long b = __arm_rsr64 (nullptr); /* { dg-error "first argument to '__builtin_aarch64_rsr64' must be a string literal" } */
+ __arm_wsr64 (nullptr, b); /* { dg-error "first argument to '__builtin_aarch64_wsr64' must be a string literal" } */
+}