This is a quick refactor of the riscv target processing code
to take a string_slice rather than a decl.

The reason for this is to enable it to work with target_clones
where merging logic requires reasoning about each version string
individually in the front end.

This refactor primarily serves just to get this working. Ideally the
logic here would be further refactored as currenly there is no way to
check if a parse fails or not without emitting an error.
This makes things difficult for later patches which intends to emit a
warning and ignoring unrecognised/not parsed target_clone values rather
than erroring which can't currenly be achieved with the current riscv
code.

gcc/ChangeLog:

        * config/riscv/riscv-protos.h (riscv_process_target_version_str): New 
function..
        * config/riscv/riscv-target-attr.cc (riscv_process_target_attr): 
Refactor to take
        string_slice.
        (riscv_process_target_version_str): Ditto.
        * config/riscv/riscv.cc (parse_features_for_version): Refactor to take
        string_slice.
        (riscv_compare_version_priority): Ditto.
        (dispatch_function_versions): Change to pass location.
---
 gcc/config/riscv/riscv-protos.h       |  2 ++
 gcc/config/riscv/riscv-target-attr.cc | 14 +++++---
 gcc/config/riscv/riscv.cc             | 50 ++++++++++++++-------------
 3 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 2bedd878a04..1efe45d63e6 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -813,6 +813,8 @@ riscv_option_valid_attribute_p (tree, tree, tree, int);
 extern bool
 riscv_option_valid_version_attribute_p (tree, tree, tree, int);
 extern bool
+riscv_process_target_version_str (string_slice, location_t);
+extern bool
 riscv_process_target_version_attr (tree, location_t);
 extern void
 riscv_override_options_internal (struct gcc_options *);
diff --git a/gcc/config/riscv/riscv-target-attr.cc 
b/gcc/config/riscv/riscv-target-attr.cc
index 1d968655f95..d3f06fb15d4 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -354,11 +354,11 @@ num_occurrences_in_str (char c, char *str)
    and update the global target options space.  */
 
 bool
-riscv_process_target_attr (const char *args,
+riscv_process_target_attr (string_slice args,
                           location_t loc,
                           const struct riscv_attribute_info *attrs)
 {
-  size_t len = strlen (args);
+  size_t len = args.size ();
 
   /* No need to emit warning or error on empty string here, generic code 
already
      handle this case.  */
@@ -369,7 +369,7 @@ riscv_process_target_attr (const char *args,
 
   std::unique_ptr<char[]> buf (new char[len+1]);
   char *str_to_check = buf.get ();
-  strcpy (str_to_check, args);
+  strncpy (str_to_check, args.begin (), args.size ());
 
   /* Used to catch empty spaces between semi-colons i.e.
      attribute ((target ("attr1;;attr2"))).  */
@@ -391,8 +391,7 @@ riscv_process_target_attr (const char *args,
 
   if (num_attrs != num_semicolons + 1)
     {
-      error_at (loc, "malformed %<target(\"%s\")%> attribute",
-               args);
+      error_at (loc, "malformed %<target(\"%B\")%> attribute", &args);
       return false;
     }
 
@@ -513,6 +512,11 @@ riscv_process_target_version_attr (tree args, location_t 
loc)
   return riscv_process_target_attr (str, loc, riscv_target_version_attrs);
 }
 
+bool
+riscv_process_target_version_str (string_slice str, location_t loc)
+{
+  return riscv_process_target_attr (str, loc, riscv_target_version_attrs);
+}
 
 /* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P.  This is used to
    process attribute ((target_version ("..."))).  */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 946658e0d5e..ddeb321cb44 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13092,31 +13092,22 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
   return default_mode_for_floating_type (ti);
 }
 
-/* This parses the attribute arguments to target_version in DECL and modifies
-   the feature mask and priority required to select those targets.  */
-static void
-parse_features_for_version (tree decl,
+/* This parses STR and modifies the feature mask and priority required to
+   select those targets.  */
+static bool
+parse_features_for_version (string_slice version_str,
+                           location_t loc,
                            struct riscv_feature_bits &res,
                            int &priority)
 {
-  tree version_attr = lookup_attribute ("target_version",
-                                       DECL_ATTRIBUTES (decl));
-  if (version_attr == NULL_TREE)
+  gcc_assert (version_str.is_valid ());
+  if (version_str == "default")
     {
       res.length = 0;
       priority = 0;
-      return;
+      return true;
     }
 
-  const char *version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE
-                                                   (version_attr)));
-  gcc_assert (version_string != NULL);
-  if (strcmp (version_string, "default") == 0)
-    {
-      res.length = 0;
-      priority = 0;
-      return;
-    }
   struct cl_target_option cur_target;
   cl_target_option_save (&cur_target, &global_options,
                         &global_options_set);
@@ -13126,21 +13117,20 @@ parse_features_for_version (tree decl,
   cl_target_option_restore (&global_options, &global_options_set,
                            default_opts);
 
-  riscv_process_target_version_attr (TREE_VALUE (version_attr),
-                                    DECL_SOURCE_LOCATION (decl));
+  riscv_process_target_version_str (version_str, loc);
 
   priority = global_options.x_riscv_fmv_priority;
   const char *arch_string = global_options.x_riscv_arch_string;
   bool parse_res
     = riscv_minimal_hwprobe_feature_bits (arch_string, &res,
-                                         DECL_SOURCE_LOCATION (decl));
-  gcc_assert (parse_res);
+                                         loc);
 
   if (arch_string != default_opts->x_riscv_arch_string)
     free (CONST_CAST (void *, (const void *) arch_string));
 
   cl_target_option_restore (&global_options, &global_options_set,
                            &cur_target);
+  return parse_res;
 }
 
 /* Compare priorities of two feature masks.  Return:
@@ -13193,8 +13183,16 @@ riscv_compare_version_priority (tree decl1, tree decl2)
   struct riscv_feature_bits mask1, mask2;
   int prio1, prio2;
 
-  parse_features_for_version (decl1, mask1, prio1);
-  parse_features_for_version (decl2, mask2, prio2);
+  string_slice v1 = get_target_version (decl1);
+  string_slice v2 = get_target_version (decl2);
+
+  if (!v1.is_valid ())
+    v1 = "default";
+  if (!v2.is_valid ())
+    v2 = "default";
+
+  parse_features_for_version (v1, DECL_SOURCE_LOCATION (decl1), mask1, prio1);
+  parse_features_for_version (v2, DECL_SOURCE_LOCATION (decl1), mask2, prio2);
 
   return compare_fmv_features (mask1, mask2, prio1, prio2);
 }
@@ -13495,7 +13493,11 @@ dispatch_function_versions (tree dispatch_decl,
       struct function_version_info version_info;
       version_info.version_decl = version_decl;
       // Get attribute string, parse it and find the right features.
-      parse_features_for_version (version_decl,
+      string_slice v = get_target_version (version_decl);
+      if (!v.is_valid ())
+       v = "default";
+      parse_features_for_version (v,
+                                 DECL_SOURCE_LOCATION (version_decl),
                                  version_info.features,
                                  version_info.prio);
       function_versions.push_back (version_info);
-- 
2.34.1

Reply via email to