diff mbox series

[v2,3/4] RISC-V: Extend riscv_subset_list, preparatory for target attribute support

Message ID 20231010041305.9111-4-kito.cheng@sifive.com
State New
Headers show
Series RISC-V target attribute | expand

Commit Message

Kito Cheng Oct. 10, 2023, 4:13 a.m. UTC
riscv_subset_list only accept a full arch string before, but we need to
parse single extension when supporting target attribute, also we may set
a riscv_subset_list directly rather than re-parsing the ISA string
again.

gcc/ChangeLog:

	* config/riscv/riscv-subset.h (riscv_subset_list::parse_single_std_ext):
	New.
	(riscv_subset_list::parse_single_multiletter_ext): Ditto.
	(riscv_subset_list::clone): Ditto.
	(riscv_subset_list::parse_single_ext): Ditto.
	(riscv_subset_list::set_loc): Ditto.
	(riscv_set_arch_by_subset_list): Ditto.
	* common/config/riscv/riscv-common.cc
	(riscv_subset_list::parse_single_std_ext): New.
	(riscv_subset_list::parse_single_multiletter_ext): Ditto.
	(riscv_subset_list::clone): Ditto.
	(riscv_subset_list::parse_single_ext): Ditto.
	(riscv_subset_list::set_loc): Ditto.
	(riscv_set_arch_by_subset_list): Ditto.
---
 gcc/common/config/riscv/riscv-common.cc | 203 ++++++++++++++++++++++++
 gcc/config/riscv/riscv-subset.h         |  11 ++
 2 files changed, 214 insertions(+)

Comments

Jeff Law Oct. 10, 2023, 2 p.m. UTC | #1
On 10/9/23 22:13, Kito Cheng wrote:
> riscv_subset_list only accept a full arch string before, but we need to
> parse single extension when supporting target attribute, also we may set
> a riscv_subset_list directly rather than re-parsing the ISA string
> again.
> 
> gcc/ChangeLog:
> 
> 	* config/riscv/riscv-subset.h (riscv_subset_list::parse_single_std_ext):
> 	New.
> 	(riscv_subset_list::parse_single_multiletter_ext): Ditto.
> 	(riscv_subset_list::clone): Ditto.
> 	(riscv_subset_list::parse_single_ext): Ditto.
> 	(riscv_subset_list::set_loc): Ditto.
> 	(riscv_set_arch_by_subset_list): Ditto.
> 	* common/config/riscv/riscv-common.cc
> 	(riscv_subset_list::parse_single_std_ext): New.
> 	(riscv_subset_list::parse_single_multiletter_ext): Ditto.
> 	(riscv_subset_list::clone): Ditto.
> 	(riscv_subset_list::parse_single_ext): Ditto.
> 	(riscv_subset_list::set_loc): Ditto.
> 	(riscv_set_arch_by_subset_list): Ditto.
> ---
>   gcc/common/config/riscv/riscv-common.cc | 203 ++++++++++++++++++++++++
>   gcc/config/riscv/riscv-subset.h         |  11 ++
>   2 files changed, 214 insertions(+)
> 
> diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
> index 9a0a68fe5db..25630d5923e 100644
> --- a/gcc/common/config/riscv/riscv-common.cc
> +++ b/gcc/common/config/riscv/riscv-common.cc
> @@ -1138,6 +1173,102 @@ riscv_subset_list::handle_combine_ext ()
>       }
>   }
>   
> +/* Parsing function for multi-letter extensions.
> +
> +   Return Value:
> +     Points to the end of extensions.
> +
> +   Arguments:
> +     `p`: Current parsing position.
> +     `ext_type`: What kind of extensions, 's', 'z' or 'x'.
> +     `ext_type_str`: Full name for kind of extension.  */
> +
> +
> +const char *
> +riscv_subset_list::parse_single_multiletter_ext (const char *p,
> +						 const char *ext_type,
> +						 const char *ext_type_str)
[ ... ]




> +
> +  if (end_of_version == NULL)
> +    return NULL;
I think when we hit this path we leak SUBSET.




>   
>   std::string
> @@ -1498,6 +1673,34 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
>     {NULL, NULL, 0}
>   };
>   
> +void
> +riscv_set_arch_by_subset_list (riscv_subset_list *subset_list,
> +			       struct gcc_options *opts)
Needs a function comment.

OK with those two minor issues fixed.

jeff
Kito Cheng Oct. 11, 2023, 9:19 p.m. UTC | #2
Thanks, committed with fixup for those two comments :)


On Tue, Oct 10, 2023 at 7:01 AM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
> On 10/9/23 22:13, Kito Cheng wrote:
> > riscv_subset_list only accept a full arch string before, but we need to
> > parse single extension when supporting target attribute, also we may set
> > a riscv_subset_list directly rather than re-parsing the ISA string
> > again.
> >
> > gcc/ChangeLog:
> >
> >       * config/riscv/riscv-subset.h (riscv_subset_list::parse_single_std_ext):
> >       New.
> >       (riscv_subset_list::parse_single_multiletter_ext): Ditto.
> >       (riscv_subset_list::clone): Ditto.
> >       (riscv_subset_list::parse_single_ext): Ditto.
> >       (riscv_subset_list::set_loc): Ditto.
> >       (riscv_set_arch_by_subset_list): Ditto.
> >       * common/config/riscv/riscv-common.cc
> >       (riscv_subset_list::parse_single_std_ext): New.
> >       (riscv_subset_list::parse_single_multiletter_ext): Ditto.
> >       (riscv_subset_list::clone): Ditto.
> >       (riscv_subset_list::parse_single_ext): Ditto.
> >       (riscv_subset_list::set_loc): Ditto.
> >       (riscv_set_arch_by_subset_list): Ditto.
> > ---
> >   gcc/common/config/riscv/riscv-common.cc | 203 ++++++++++++++++++++++++
> >   gcc/config/riscv/riscv-subset.h         |  11 ++
> >   2 files changed, 214 insertions(+)
> >
> > diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
> > index 9a0a68fe5db..25630d5923e 100644
> > --- a/gcc/common/config/riscv/riscv-common.cc
> > +++ b/gcc/common/config/riscv/riscv-common.cc
> > @@ -1138,6 +1173,102 @@ riscv_subset_list::handle_combine_ext ()
> >       }
> >   }
> >
> > +/* Parsing function for multi-letter extensions.
> > +
> > +   Return Value:
> > +     Points to the end of extensions.
> > +
> > +   Arguments:
> > +     `p`: Current parsing position.
> > +     `ext_type`: What kind of extensions, 's', 'z' or 'x'.
> > +     `ext_type_str`: Full name for kind of extension.  */
> > +
> > +
> > +const char *
> > +riscv_subset_list::parse_single_multiletter_ext (const char *p,
> > +                                              const char *ext_type,
> > +                                              const char *ext_type_str)
> [ ... ]
>
>
>
>
> > +
> > +  if (end_of_version == NULL)
> > +    return NULL;
> I think when we hit this path we leak SUBSET.
>
>
>
>
> >
> >   std::string
> > @@ -1498,6 +1673,34 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
> >     {NULL, NULL, 0}
> >   };
> >
> > +void
> > +riscv_set_arch_by_subset_list (riscv_subset_list *subset_list,
> > +                            struct gcc_options *opts)
> Needs a function comment.
>
> OK with those two minor issues fixed.
>
> jeff
diff mbox series

Patch

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 9a0a68fe5db..25630d5923e 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -1036,6 +1036,41 @@  riscv_subset_list::parse_std_ext (const char *p)
   return p;
 }
 
+/* Parsing function for one standard extensions.
+
+   Return Value:
+     Points to the end of extensions.
+
+   Arguments:
+     `p`: Current parsing position.  */
+
+const char *
+riscv_subset_list::parse_single_std_ext (const char *p)
+{
+  if (*p == 'x' || *p == 's' || *p == 'z')
+    {
+      error_at (m_loc,
+		"%<-march=%s%>: Not single-letter extension. "
+		"%<%c%>",
+		m_arch, *p);
+      return nullptr;
+    }
+
+  unsigned major_version = 0;
+  unsigned minor_version = 0;
+  bool explicit_version_p = false;
+  char subset[2] = {0, 0};
+
+  subset[0] = *p;
+
+  p++;
+
+  p = parsing_subset_version (subset, p, &major_version, &minor_version,
+			      /* std_ext_p= */ true, &explicit_version_p);
+
+  add (subset, major_version, minor_version, explicit_version_p, false);
+  return p;
+}
 
 /* Check any implied extensions for EXT.  */
 void
@@ -1138,6 +1173,102 @@  riscv_subset_list::handle_combine_ext ()
     }
 }
 
+/* Parsing function for multi-letter extensions.
+
+   Return Value:
+     Points to the end of extensions.
+
+   Arguments:
+     `p`: Current parsing position.
+     `ext_type`: What kind of extensions, 's', 'z' or 'x'.
+     `ext_type_str`: Full name for kind of extension.  */
+
+
+const char *
+riscv_subset_list::parse_single_multiletter_ext (const char *p,
+						 const char *ext_type,
+						 const char *ext_type_str)
+{
+  unsigned major_version = 0;
+  unsigned minor_version = 0;
+  size_t ext_type_len = strlen (ext_type);
+
+  if (strncmp (p, ext_type, ext_type_len) != 0)
+    return NULL;
+
+  char *subset = xstrdup (p);
+  const char *end_of_version;
+  bool explicit_version_p = false;
+  char *ext;
+  char backup;
+  size_t len = strlen (p);
+  size_t end_of_version_pos, i;
+  bool found_any_number = false;
+  bool found_minor_version = false;
+
+  end_of_version_pos = len;
+  /* Find the begin of version string.  */
+  for (i = len -1; i > 0; --i)
+    {
+      if (ISDIGIT (subset[i]))
+	{
+	  found_any_number = true;
+	  continue;
+	}
+      /* Might be version seperator, but need to check one more char,
+	 we only allow <major>p<minor>, so we could stop parsing if found
+	 any more `p`.  */
+      if (subset[i] == 'p' &&
+	  !found_minor_version &&
+	  found_any_number && ISDIGIT (subset[i-1]))
+	{
+	  found_minor_version = true;
+	  continue;
+	}
+
+      end_of_version_pos = i + 1;
+      break;
+    }
+
+  backup = subset[end_of_version_pos];
+  subset[end_of_version_pos] = '\0';
+  ext = xstrdup (subset);
+  subset[end_of_version_pos] = backup;
+
+  end_of_version
+    = parsing_subset_version (ext, subset + end_of_version_pos, &major_version,
+			      &minor_version, /* std_ext_p= */ false,
+			      &explicit_version_p);
+  free (ext);
+
+  if (end_of_version == NULL)
+    return NULL;
+
+  subset[end_of_version_pos] = '\0';
+
+  if (strlen (subset) == 1)
+    {
+      error_at (m_loc, "%<-march=%s%>: name of %s must be more than 1 letter",
+		m_arch, ext_type_str);
+      free (subset);
+      return NULL;
+    }
+
+  add (subset, major_version, minor_version, explicit_version_p, false);
+  p += end_of_version - subset;
+  free (subset);
+
+  if (*p != '\0' && *p != '_')
+    {
+      error_at (m_loc, "%<-march=%s%>: %s must separate with %<_%>",
+		m_arch, ext_type_str);
+      return NULL;
+    }
+
+  return p;
+
+}
+
 /* Parsing function for multi-letter extensions.
 
    Return Value:
@@ -1250,6 +1381,30 @@  riscv_subset_list::parse_multiletter_ext (const char *p,
   return p;
 }
 
+/* Parsing function for a single-letter or multi-letter extensions.
+
+   Return Value:
+     Points to the end of extensions.
+
+   Arguments:
+     `p`: Current parsing position.  */
+
+const char *
+riscv_subset_list::parse_single_ext (const char *p)
+{
+  switch (p[0])
+    {
+    case 'x':
+      return parse_single_multiletter_ext (p, "x", "non-standard extension");
+    case 'z':
+      return parse_single_multiletter_ext (p, "z", "sub-extension");
+    case 's':
+      return parse_single_multiletter_ext (p, "s", "supervisor extension");
+    default:
+      return parse_single_std_ext (p);
+    }
+}
+
 /* Parsing arch string to subset list, return NULL if parsing failed.  */
 
 riscv_subset_list *
@@ -1342,6 +1497,26 @@  fail:
   return NULL;
 }
 
+/* Clone whole subset list.  */
+
+riscv_subset_list *
+riscv_subset_list::clone () const
+{
+  riscv_subset_list *new_list = new riscv_subset_list (m_arch, m_loc);
+  for (riscv_subset_t *itr = m_head; itr != NULL; itr = itr->next)
+    new_list->add (itr->name.c_str (), itr->major_version, itr->minor_version,
+		   itr->explicit_version_p, true);
+
+  new_list->m_xlen = m_xlen;
+  return new_list;
+}
+
+void
+riscv_subset_list::set_loc (location_t loc)
+{
+  m_loc = loc;
+}
+
 /* Return the current arch string.  */
 
 std::string
@@ -1498,6 +1673,34 @@  static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {NULL, NULL, 0}
 };
 
+void
+riscv_set_arch_by_subset_list (riscv_subset_list *subset_list,
+			       struct gcc_options *opts)
+{
+  if (opts)
+    {
+      const riscv_ext_flag_table_t *arch_ext_flag_tab;
+      /* Clean up target flags before we set.  */
+      for (arch_ext_flag_tab = &riscv_ext_flag_table[0]; arch_ext_flag_tab->ext;
+	   ++arch_ext_flag_tab)
+	opts->*arch_ext_flag_tab->var_ref &= ~arch_ext_flag_tab->mask;
+
+      if (subset_list->xlen () == 32)
+	opts->x_target_flags &= ~MASK_64BIT;
+      else if (subset_list->xlen () == 64)
+	opts->x_target_flags |= MASK_64BIT;
+
+      for (arch_ext_flag_tab = &riscv_ext_flag_table[0]; arch_ext_flag_tab->ext;
+	   ++arch_ext_flag_tab)
+	{
+	  if (subset_list->lookup (arch_ext_flag_tab->ext))
+	    opts->*arch_ext_flag_tab->var_ref |= arch_ext_flag_tab->mask;
+	}
+    }
+
+  current_subset_list = subset_list;
+}
+
 /* Parse a RISC-V ISA string into an option mask.  Must clear or set all arch
    dependent mask bits, in case more than one -march string is passed.  */
 
diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
index dca07284efa..d2a4bd20530 100644
--- a/gcc/config/riscv/riscv-subset.h
+++ b/gcc/config/riscv/riscv-subset.h
@@ -69,8 +69,12 @@  private:
 
   const char *parse_std_ext (const char *);
 
+  const char *parse_single_std_ext (const char *);
+
   const char *parse_multiletter_ext (const char *, const char *,
 				     const char *);
+  const char *parse_single_multiletter_ext (const char *, const char *,
+					    const char *);
 
   void handle_implied_ext (const char *);
   bool check_implied_ext ();
@@ -91,14 +95,21 @@  public:
 
   unsigned xlen () const {return m_xlen;};
 
+  riscv_subset_list *clone () const;
+
   static riscv_subset_list *parse (const char *, location_t);
+  const char *parse_single_ext (const char *);
 
   const riscv_subset_t *begin () const {return m_head;};
   const riscv_subset_t *end () const {return NULL;};
 
   int match_score (riscv_subset_list *) const;
+
+  void set_loc (location_t);
 };
 
 extern const riscv_subset_list *riscv_current_subset_list (void);
+extern void
+riscv_set_arch_by_subset_list (riscv_subset_list *, struct gcc_options *);
 
 #endif /* ! GCC_RISCV_SUBSET_H */