https://gcc.gnu.org/g:17c466b660b798e22702e8ac5e3d6f840e1c6896

commit 17c466b660b798e22702e8ac5e3d6f840e1c6896
Author: Alfie Richards <alfie.richa...@arm.com>
Date:   Fri Jan 31 10:51:14 2025 +0000

    Add get_clone_versions and get_version functions.
    
    This is a reimplementation of get_target_clone_attr_len,
    get_attr_str, and separate_attrs using string_slice and auto_vec to make
    memory management and use simpler.
    
    This also adds get_version which is a helper function to get the version
    string from a decl.
    
    gcc/c-family/ChangeLog:
    
            * c-attribs.cc (handle_target_clones_attribute): Change to use
            get_clone_versions.
    
    gcc/ChangeLog:
    
            * tree.cc (get_clone_versions): New function.
            (get_clone_attr_versions): New function.
            (get_version): New function.
            * tree.h (get_clone_versions): New function.
            (get_clone_attr_versions): New function.
            (get_version): New function.

Diff:
---
 gcc/c-family/c-attribs.cc |  4 +++-
 gcc/tree.cc               | 57 +++++++++++++++++++++++++++++++++++++++++++++++
 gcc/tree.h                | 11 +++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 5a0e3d328ba7..5dff489fccae 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -6132,7 +6132,9 @@ handle_target_clones_attribute (tree *node, tree name, 
tree ARG_UNUSED (args),
            }
        }
 
-      if (get_target_clone_attr_len (args) == -1)
+      auto_vec<string_slice> versions= get_clone_attr_versions (args, NULL);
+
+      if (versions.length () == 1)
        {
          warning (OPT_Wattributes,
                   "single %<target_clones%> attribute is ignored");
diff --git a/gcc/tree.cc b/gcc/tree.cc
index eccfcc89da40..ddbe98e1a74f 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15372,6 +15372,63 @@ get_target_clone_attr_len (tree arglist)
   return str_len_sum;
 }
 
+/* Returns an auto_vec of string_slices containing the version strings from
+   ARGLIST.  DEFAULT_COUNT is incremented for each default version found.  */
+
+auto_vec<string_slice>
+get_clone_attr_versions (const tree arglist, int *default_count)
+{
+  gcc_assert (TREE_CODE (arglist) == TREE_LIST);
+  auto_vec<string_slice> versions;
+
+  static const char separator_str[] = {TARGET_CLONES_ATTR_SEPARATOR, 0};
+  string_slice separators = string_slice (separator_str);
+
+  for (tree arg = arglist; arg; arg = TREE_CHAIN (arg))
+    {
+      string_slice str = string_slice (TREE_STRING_POINTER (TREE_VALUE (arg)));
+      while (str.is_valid ())
+       {
+         string_slice attr = string_slice::tokenize (&str, separators);
+         attr = attr.strip ();
+
+         if (attr == "default" && default_count)
+           (*default_count)++;
+         versions.safe_push (attr);
+       }
+    }
+  return versions;
+}
+
+/* Returns an auto_vec of string_slices containing the version strings from
+   the target_clone attribute from DECL.  DEFAULT_COUNT is incremented for each
+   default version found.  */
+auto_vec<string_slice>
+get_clone_versions (const tree decl, int *default_count)
+{
+  tree attr = lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl));
+  if (!attr)
+    return auto_vec<string_slice> ();
+  tree arglist = TREE_VALUE (attr);
+  return get_clone_attr_versions (arglist, default_count);
+}
+
+/* Only works for target_version due to target attributes allowing multiple
+   string arguments to specify one target.  */
+string_slice
+get_target_version (const tree decl)
+{
+  gcc_assert (!TARGET_HAS_FMV_TARGET_ATTRIBUTE);
+
+  tree attr = lookup_attribute ("target_version", DECL_ATTRIBUTES (decl));
+
+  if (!attr)
+    return string_slice::invalid ();
+
+  return string_slice (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))))
+          .strip ();
+}
+
 void
 tree_cc_finalize (void)
 {
diff --git a/gcc/tree.h b/gcc/tree.h
index 55f97f9f9994..e34a49a9ed9e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "tree-core.h"
 #include "options.h"
+#include "vec.h"
 
 /* Convert a target-independent built-in function code to a combined_fn.  */
 
@@ -7041,4 +7042,14 @@ extern tree get_attr_nonstring_decl (tree, tree * = 
NULL);
 
 extern int get_target_clone_attr_len (tree);
 
+/* Returns the version string for a decl with target_version attribute.
+   Returns an invalid string_slice if no attribute is present.  */
+extern string_slice get_target_version (const tree);
+/* Returns a vector of the version strings from a target_clones attribute on
+   a decl.  Can also record the number of default versions found.  */
+extern auto_vec<string_slice> get_clone_versions (const tree, int * = NULL);
+/* Returns a vector of the version strings from a target_clones attribute
+   directly.  */
+extern auto_vec<string_slice> get_clone_attr_versions (const tree, int *);
+
 #endif  /* GCC_TREE_H  */

Reply via email to