]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
riscv: Refactor riscv target parsing to take string_slice.
authorAlfie Richards <alfie.richards@arm.com>
Mon, 24 Mar 2025 11:45:32 +0000 (11:45 +0000)
committerAlfie Richards <alfie.richards@arm.com>
Tue, 23 Sep 2025 09:47:43 +0000 (09:47 +0000)
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
gcc/config/riscv/riscv-target-attr.cc
gcc/config/riscv/riscv.cc

index 2d3fd0e07626b3aa774a5da3288e3b62ff99608e..e4473f45d0e44c528dc78cd4b5891a208e722eb5 100644 (file)
@@ -840,6 +840,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);
index 5e01c9214548c226afb2bb4c0ed6c8e932ce73c0..54edeebf93c00ebdcab444012b66f4336dd7a9eb 100644 (file)
@@ -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 ("..."))).  */
index 3ca7309ad5cf6a619e5bce94ca25a7b65e9e4da4..5c1753a6f96a555cb43330386cec893329453803 100644 (file)
@@ -14001,34 +14001,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);
@@ -14038,7 +14028,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;
@@ -14100,8 +14090,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);
 }
@@ -14402,7 +14400,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);