From: Alfie Richards <alfie.richa...@arm.com>

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 currently 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 currently 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): New function.
        * 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 | 25 +++++++++++------
 gcc/config/riscv/riscv.cc             | 39 ++++++++++++++-------------
 3 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 2d60a0ad44b..aa719c84ef4 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -838,6 +838,8 @@ extern bool
 riscv_option_valid_version_attribute_p (tree, tree, tree, int);
 extern bool
 riscv_process_target_version_attr (tree, location_t *);
+extern bool
+riscv_process_target_version_str (string_slice, location_t *);
 extern void
 riscv_override_options_internal (struct gcc_options *);
 extern void riscv_option_override (void);
diff --git a/gcc/config/riscv/riscv-target-attr.cc 
b/gcc/config/riscv/riscv-target-attr.cc
index 5e01c921454..54edeebf93c 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -356,11 +356,11 @@ num_occurrences_in_str (char c, char *str)
    diagnostics against location *LOC, otherwise remain silent.  */
 
 bool
-riscv_process_target_attr (const char *args,
-                          location_t *loc,
-                          const struct riscv_attribute_info *attrs)
+riscv_process_target_str (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.  */
@@ -371,7 +371,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"))).  */
@@ -394,7 +394,7 @@ riscv_process_target_attr (const char *args,
   if (num_attrs != num_semicolons + 1)
     {
       if (loc)
-       error_at (*loc, "malformed %<target(\"%s\")%> attribute", args);
+       error_at (*loc, "malformed %<target(\"%B\")%> attribute", &args);
       return false;
     }
 
@@ -436,7 +436,7 @@ riscv_process_target_attr (tree args,
       return false;
     }
 
-  return riscv_process_target_attr (TREE_STRING_POINTER (args), loc, attrs);
+  return riscv_process_target_str (TREE_STRING_POINTER (args), loc, attrs);
 }
 
 /* Implement TARGET_OPTION_VALID_ATTRIBUTE_P.
@@ -518,9 +518,18 @@ riscv_process_target_version_attr (tree args, location_t 
*loc)
   if (strcmp (str, "default") == 0)
     return true;
 
-  return riscv_process_target_attr (str, loc, riscv_target_version_attrs);
+  return riscv_process_target_str (str, loc, riscv_target_version_attrs);
 }
 
+/* Parse the version string in STR and update the global target options space.
+   If LOC is nonnull, report diagnostics against location *LOC, otherwise
+   remain silent.  */
+
+bool
+riscv_process_target_version_str (string_slice str, location_t *loc)
+{
+  return riscv_process_target_str (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 8d321c21ccb..c5574453cf8 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13965,34 +13965,24 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
   return default_mode_for_floating_type (ti);
 }
 
-/* Parse the attribute arguments to target_version in DECL and modify
-   the feature mask and priority required to select those targets.
+/* This parses the version string STR and modifies the feature mask and
+   priority required to select those targets.
    If LOC is nonnull, report diagnostics against *LOC, otherwise
    remain silent.  */
 static void
-parse_features_for_version (tree decl,
+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;
     }
 
-  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);
@@ -14002,7 +13992,7 @@ 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), loc);
+  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;
@@ -14064,8 +14054,16 @@ riscv_compare_version_priority (tree decl1, tree decl2)
   struct riscv_feature_bits mask1, mask2;
   int prio1, prio2;
 
-  parse_features_for_version (decl1, nullptr, mask1, prio1);
-  parse_features_for_version (decl2, nullptr, 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, nullptr, mask1, prio1);
+  parse_features_for_version (v2, nullptr, mask2, prio2);
 
   return compare_fmv_features (mask1, mask2, prio1, prio2);
 }
@@ -14366,7 +14364,10 @@ 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);
-- 
2.34.1

Reply via email to