From: Richard Ball <[email protected]>

This patch rewrites the _Generic in arm_acle.h into a 
resolve_overloaded_builtin.
The reason for this was the lack of support in C++ for _Generic.
---
 gcc/config/aarch64/aarch64-builtins.cc        |  64 ++++++
 gcc/config/aarch64/aarch64-c.cc               |   3 +-
 gcc/config/aarch64/arm_acle.h                 |  24 +--
 .../aarch64/atomic_store_with_stshh.C         | 185 ++++++++++++++++++
 4 files changed, 254 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/aarch64/atomic_store_with_stshh.C

diff --git a/gcc/config/aarch64/aarch64-builtins.cc 
b/gcc/config/aarch64/aarch64-builtins.cc
index c2a9e3d3412..8149c440536 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -902,6 +902,7 @@ enum aarch64_builtins
   AARCH64_BUILTIN_GCSPOPM,
   AARCH64_BUILTIN_GCSSS,
   /* Armv9.6-A builtins.  */
+  AARCH64_BUILTIN_STSHH,
   AARCH64_BUILTIN_STSHH_QI,
   AARCH64_BUILTIN_STSHH_HI,
   AARCH64_BUILTIN_STSHH_SI,
@@ -2481,6 +2482,14 @@ aarch64_init_pcdphint_builtins (void)
 {
   tree ftype;
 
+  ftype = build_function_type_list (void_type_node, ptr_type_node,
+                                   void_type_node,
+                                   unsigned_type_node,
+                                   unsigned_type_node, NULL_TREE);
+  aarch64_builtin_decls[AARCH64_BUILTIN_STSHH]
+    = aarch64_general_add_builtin ("__builtin_aarch64_stshh", ftype,
+                                  AARCH64_BUILTIN_STSHH);
+
   ftype = build_function_type_list (void_type_node, ptr_type_node,
                                    unsigned_char_type_node,
                                    unsigned_type_node,
@@ -5767,6 +5776,58 @@ aarch64_resolve_overloaded_memtag (location_t loc,
   return NULL_TREE;
 }
 
+static tree
+aarch64_resolve_overloaded_builtin_stshh (void *pass_params)
+{
+  vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (pass_params);
+  if (vec_safe_length (params) != 4)
+    return NULL_TREE;
+
+  tree addr = (*params)[0];
+  tree val = (*params)[1];
+  addr = tree_strip_nop_conversions (addr);
+  val = tree_strip_nop_conversions (val);
+
+  tree addr_type = TREE_TYPE (addr);
+  if (!POINTER_TYPE_P (addr_type))
+    return NULL_TREE;
+
+  tree ptr_type = TYPE_MAIN_VARIANT (TREE_TYPE (addr_type));
+  enum aarch64_builtins decl;
+
+  if (INTEGRAL_TYPE_P (ptr_type) && POINTER_TYPE_P (TREE_TYPE (val)))
+    {
+      val = convert (size_type_node, val);
+      if (val == error_mark_node)
+       return NULL_TREE;
+      (*params)[1] = val;
+    }
+
+  if (ptr_type == char_type_node
+      || ptr_type == signed_char_type_node
+      || ptr_type == unsigned_char_type_node)
+    decl = AARCH64_BUILTIN_STSHH_QI;
+  else if (ptr_type == short_integer_type_node
+          || ptr_type == short_unsigned_type_node)
+    decl = AARCH64_BUILTIN_STSHH_HI;
+  else if (ptr_type == integer_type_node
+          || ptr_type == unsigned_type_node)
+    decl = AARCH64_BUILTIN_STSHH_SI;
+  else if (ptr_type == long_long_integer_type_node
+          || ptr_type == long_long_unsigned_type_node
+          || ptr_type == long_integer_type_node
+          || ptr_type == long_unsigned_type_node)
+    decl = AARCH64_BUILTIN_STSHH_DI;
+  else if (ptr_type == float_type_node)
+    decl = AARCH64_BUILTIN_STSHH_SF;
+  else if (ptr_type == double_type_node)
+    decl = AARCH64_BUILTIN_STSHH_DF;
+  else
+    return NULL_TREE;
+
+  return aarch64_builtin_decls[decl];
+}
+
 /* Called at aarch64_resolve_overloaded_builtin in aarch64-c.cc.  */
 tree
 aarch64_resolve_overloaded_builtin_general (location_t loc, tree function,
@@ -5778,6 +5839,9 @@ aarch64_resolve_overloaded_builtin_general (location_t 
loc, tree function,
       && fcode <= AARCH64_MEMTAG_BUILTIN_END)
     return aarch64_resolve_overloaded_memtag(loc, function, pass_params);
 
+  if (fcode == AARCH64_BUILTIN_STSHH)
+    return aarch64_resolve_overloaded_builtin_stshh (pass_params);
+
   return NULL_TREE;
 }
 
diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index b52ea7649f9..ecb37bd525f 100644
--- a/gcc/config/aarch64/aarch64-c.cc
+++ b/gcc/config/aarch64/aarch64-c.cc
@@ -429,8 +429,9 @@ aarch64_resolve_overloaded_builtin (location_t location,
   switch (code & AARCH64_BUILTIN_CLASS)
     {
     case AARCH64_BUILTIN_GENERAL:
-      return aarch64_resolve_overloaded_builtin_general (location, fndecl,
+      new_fndecl = aarch64_resolve_overloaded_builtin_general (location, 
fndecl,
                                                         uncast_arglist);
+      break;
     case AARCH64_BUILTIN_SVE:
       new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode,
                                                            arglist);
diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h
index 651f4cb8b60..a99756542ef 100644
--- a/gcc/config/aarch64/arm_acle.h
+++ b/gcc/config/aarch64/arm_acle.h
@@ -139,27 +139,9 @@ __sqrtf (float __x)
   return __builtin_aarch64_sqrtsf (__x);
 }
 
-#define __atomic_store_with_stshh(addr, value, memory_order, ret)      \
-({                                                                     \
-  __auto_type ptr = (addr);                                            \
-  typedef __typeof__ (*ptr) ptr_type;                                  \
-  _Generic ((*ptr),                                                    \
-    char:                __builtin_aarch64_stshh_qi,   \
-    unsigned char:       __builtin_aarch64_stshh_qi,   \
-    signed char:         __builtin_aarch64_stshh_qi,   \
-    unsigned short:       __builtin_aarch64_stshh_hi,  \
-    short:               __builtin_aarch64_stshh_hi,   \
-    unsigned int:        __builtin_aarch64_stshh_si,   \
-    int:                 __builtin_aarch64_stshh_si,   \
-    unsigned long:       __builtin_aarch64_stshh_di,   \
-    long:                __builtin_aarch64_stshh_di,   \
-    unsigned long long:   __builtin_aarch64_stshh_di,  \
-    long long:           __builtin_aarch64_stshh_di,   \
-    float:               __builtin_aarch64_stshh_sf,   \
-    double:              __builtin_aarch64_stshh_df,   \
-    default:             __builtin_aarch64_stshh_di    \
-  )((ptr), (ptr_type)(value), (memory_order), (ret));  \
-})
+#define __atomic_store_with_stshh(__addr, __value, __memory_order, __ret) \
+  __builtin_aarch64_stshh ((__addr), (__value), \
+                                            (__memory_order), (__ret))
 
 #pragma GCC push_options
 #pragma GCC target ("+nothing+jscvt")
diff --git a/gcc/testsuite/g++.target/aarch64/atomic_store_with_stshh.C 
b/gcc/testsuite/g++.target/aarch64/atomic_store_with_stshh.C
new file mode 100644
index 00000000000..a4b6650bb39
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/atomic_store_with_stshh.C
@@ -0,0 +1,185 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8-a -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_acle.h>
+
+/*
+** _Z8testFun1v:
+** ...
+**     stshh   keep
+**     strb    w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun1 ()
+{
+  char item1 = 0;
+  char* ptr1 = &item1;
+  char test1 = 1;
+
+  __atomic_store_with_stshh (ptr1, test1, __ATOMIC_RELAXED, 0);
+}
+
+/*
+** _Z8testFun2v:
+** ...
+**     stshh   keep
+**     stlrh   w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun2 ()
+{
+  short item2 = 10;
+  short* ptr2 = &item2;
+  short test2 = 11;
+  __atomic_store_with_stshh (ptr2, test2, __ATOMIC_RELEASE, 0);
+}
+
+/*
+** _Z8testFun3v:
+** ...
+**     stshh   strm
+**     stlr    w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun3 ()
+{
+  unsigned int item3 = 10;
+  unsigned int* ptr3 = &item3;
+  unsigned int test3 = 11;
+  __atomic_store_with_stshh (ptr3, test3, __ATOMIC_SEQ_CST, 1);
+}
+
+/*
+** _Z8testFun4v:
+** ...
+**     stshh   strm
+**     str     x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun4 ()
+{
+  long item4 = 10;
+  long* ptr4 = &item4;
+  long test4 = 11;
+  __atomic_store_with_stshh (ptr4, test4, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** _Z8testFun5v:
+** ...
+**     stshh   keep
+**     stlr    x[0-9]+, \[sp\]
+** ...
+*/
+void
+testFun5 ()
+{
+  long item5 = 10;
+  long* ptr5 = &item5;
+  long test5item = 11;
+  long* test5 = &test5item;
+  __atomic_store_with_stshh (ptr5, test5, __ATOMIC_SEQ_CST, 0);
+}
+
+/*
+** _Z8testFun6v:
+** ...
+**     stshh   keep
+**     stlr    w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun6 ()
+{
+  float item6 = 10;
+  float* ptr6 = &item6;
+  float test6 = 11;
+  __atomic_store_with_stshh (ptr6, test6, __ATOMIC_SEQ_CST, 0);
+}
+
+/*
+** _Z8testFun7v:
+** ...
+**     stshh   strm
+**     str     x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun7 ()
+{
+  double item7 = 10;
+  double* ptr7 = &item7;
+  double test7 = 11;
+  __atomic_store_with_stshh (ptr7, test7, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** _Z8testFun8v:
+** ...
+**     stshh   keep
+**     strb    w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun8 ()
+{
+  char item8 = 0;
+  char* ptr8 = &item8;
+  long test8 = 1;
+
+  __atomic_store_with_stshh (ptr8, test8, __ATOMIC_RELAXED, 0);
+}
+
+/*
+** _Z8testFun9v:
+** ...
+**     stshh   strm
+**     str     w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+void
+testFun9 ()
+{
+  int item9 = 0;
+  int* ptr9 = &item9;
+  float test9 = 1;
+
+  __atomic_store_with_stshh (ptr9, test9, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** _Z9testFun10v:
+** ...
+**     add     (x[0-9]+), \1, 1
+**     mov     (w[0-9]+), 7
+**     stshh   strm
+**     strb    \2, \[\1\]
+** ...
+*/
+static char buf[8];
+void
+testFun10 (void)
+{
+  __atomic_store_with_stshh((buf + 1), (char)7, __ATOMIC_RELAXED, 1);
+}
+
+/*
+** _Z9testFun11v:
+** ...
+**     stshh   strm
+**     str     wzr, \[x[0-9]+\]
+** ...
+*/
+void
+testFun11 ()
+{
+  int item11 = 10;
+  int* ptr11 = &item11;
+
+  __atomic_store_with_stshh (ptr11, 0, __ATOMIC_RELAXED, 1);
+}
-- 
2.34.1

Reply via email to