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.
Adds get_target_version helper function to get the target_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_target_version): New function. --- gcc/c-family/c-attribs.cc | 4 ++- gcc/tree.cc | 59 +++++++++++++++++++++++++++++++++++++++ gcc/tree.h | 11 ++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 5a0e3d328ba..5dff489fcca 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 eccfcc89da4..fdcdfb336bc 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -15372,6 +15372,65 @@ 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); +} + +/* If DECL has a target_version attribute, returns a string_slice containing the + attribute value. Otherwise, returns string_slice::invalid. + 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 99f26177628..a89f3cf7189 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. */ @@ -7052,4 +7053,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 */ -- 2.34.1