diff mbox series

[v2] Introduce TARGET_CLONES_ATTR_SEPARATOR for RISC-V

Message ID 20241015181607.3689413-1-chenyangyu@isrc.iscas.ac.cn
State New
Headers show
Series [v2] Introduce TARGET_CLONES_ATTR_SEPARATOR for RISC-V | expand

Commit Message

Yangyu Chen Oct. 15, 2024, 6:16 p.m. UTC
Some architectures may use ',' in the attribute string, but it is not
used as the separator for different targets. To avoid conflict, we
introduce a new macro TARGET_CLONES_ATTR_SEPARATOR to separate different
clones.

As an example, according to RISC-V C-API Specification [1], RISC-V allows
',' in the attribute string in the "arch=" option to specify one more
ISA extensions in the same target function, which conflict with the
default separator to separate different clones. This patch introduces
TARGET_CLONES_ATTR_SEPARATOR for RISC-V and choose '#' as the separator,
since '#' is not allowed in the target_clones option string.

[1] https://github.com/riscv-non-isa/riscv-c-api-doc/blob/c6c5d6d9cf96b342293315a5dff3d25e96ef8191/src/c-api.adoc#__attribute__targetattr-string

gcc/ChangeLog:

        * defaults.h (TARGET_CLONES_ATTR_SEPARATOR): Define new macro.
        * multiple_target.cc (get_attr_str): Use
          TARGET_CLONES_ATTR_SEPARATOR to separate attributes.
        (separate_attrs): Likewise.
        * config/riscv/riscv.h (TARGET_CLONES_ATTR_SEPARATOR): Define
          TARGET_CLONES_ATTR_SEPARATOR for RISC-V.
---
 gcc/config/riscv/riscv.h |  5 +++++
 gcc/defaults.h           |  4 ++++
 gcc/multiple_target.cc   | 19 ++++++++++++-------
 3 files changed, 21 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index ca1b8329cdc..2ff9c1024f3 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1298,4 +1298,9 @@  extern void riscv_remove_unneeded_save_restore_calls (void);
 		STACK_BOUNDARY / BITS_PER_UNIT)		   \
     : (crtl->outgoing_args_size + STACK_POINTER_OFFSET))
 
+/* According to the RISC-V C API, the arch string may contains ','. To avoid
+   the conflict with the default separator, we choose '#' as the separator for
+   the target attribute.  */
+#define TARGET_CLONES_ATTR_SEPARATOR '#'
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index ac2d25852ab..918e3ec2f24 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -874,6 +874,10 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_HAS_FMV_TARGET_ATTRIBUTE 1
 #endif
 
+/* Select a attribute separator for function multiversioning.  */
+#ifndef TARGET_CLONES_ATTR_SEPARATOR
+#define TARGET_CLONES_ATTR_SEPARATOR ','
+#endif
 
 /* Select a format to encode pointers in exception handling data.  We
    prefer those that result in fewer dynamic relocations.  Assume no
diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc
index 1fdd279da04..c1e358dfc1e 100644
--- a/gcc/multiple_target.cc
+++ b/gcc/multiple_target.cc
@@ -180,7 +180,7 @@  create_dispatcher_calls (struct cgraph_node *node)
     }
 }
 
-/* Create string with attributes separated by comma.
+/* Create string with attributes separated by TARGET_CLONES_ATTR_SEPARATOR.
    Return number of attributes.  */
 
 static int
@@ -194,17 +194,21 @@  get_attr_str (tree arglist, char *attr_str)
     {
       const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
       size_t len = strlen (str);
-      for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
+      for (const char *p = strchr (str, TARGET_CLONES_ATTR_SEPARATOR);
+	   p;
+	   p = strchr (p + 1, TARGET_CLONES_ATTR_SEPARATOR))
 	argnum++;
       memcpy (attr_str + str_len_sum, str, len);
-      attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
+      attr_str[str_len_sum + len]
+	= TREE_CHAIN (arg) ? TARGET_CLONES_ATTR_SEPARATOR : '\0';
       str_len_sum += len + 1;
       argnum++;
     }
   return argnum;
 }
 
-/* Return number of attributes separated by comma and put them into ARGS.
+/* Return number of attributes separated by TARGET_CLONES_ATTR_SEPARATOR
+   and put them into ARGS.
    If there is no DEFAULT attribute return -1.
    If there is an empty string in attribute return -2.
    If there are multiple DEFAULT attributes return -3.
@@ -215,9 +219,10 @@  separate_attrs (char *attr_str, char **attrs, int attrnum)
 {
   int i = 0;
   int default_count = 0;
+  static const char separator_str[] = { TARGET_CLONES_ATTR_SEPARATOR, 0 };
 
-  for (char *attr = strtok (attr_str, ",");
-       attr != NULL; attr = strtok (NULL, ","))
+  for (char *attr = strtok (attr_str, separator_str);
+       attr != NULL; attr = strtok (NULL, separator_str))
     {
       if (strcmp (attr, "default") == 0)
 	{
@@ -305,7 +310,7 @@  static bool
 expand_target_clones (struct cgraph_node *node, bool definition)
 {
   int i;
-  /* Parsing target attributes separated by comma.  */
+  /* Parsing target attributes separated by TARGET_CLONES_ATTR_SEPARATOR.  */
   tree attr_target = lookup_attribute ("target_clones",
 				       DECL_ATTRIBUTES (node->decl));
   /* No targets specified.  */