RISC-V: Preserve arch version info during normalizing arch string
authorKito Cheng <kito.cheng@sifive.com>
Mon, 29 Jun 2020 09:52:42 +0000 (17:52 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Wed, 1 Jul 2020 03:30:02 +0000 (11:30 +0800)
- Arch version should preserved if user explicitly specified the version.
  e.g.
    After normalize, -march=rv32if3d should be -march=rv32i_f3p0d
    instead of-march=rv32ifd.

gcc/ChangeLog:

* common/config/riscv/riscv-common.c (riscv_subset_t): New field
added.
(riscv_subset_list::parsing_subset_version): Add parameter for
indicate explicitly version, and handle explicitly version.
(riscv_subset_list::handle_implied_ext): Ditto.
(riscv_subset_list::add): Ditto.
(riscv_subset_t::riscv_subset_t): Init new field.
(riscv_subset_list::to_string): Always output version info if version
explicitly specified.
(riscv_subset_list::parsing_subset_version): Handle explicitly
arch version.
(riscv_subset_list::parse_std_ext): Ditto.
(riscv_subset_list::parse_multiletter_ext): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/attribute-13.c: New.

gcc/common/config/riscv/riscv-common.c
gcc/testsuite/gcc.target/riscv/attribute-13.c [new file with mode: 0644]

index 2df93460165b2fdf4211456b999e7a8270931b73..82c5154b61183499afc43535845ef0d9a8efb71f 100644 (file)
@@ -42,6 +42,8 @@ struct riscv_subset_t
   int major_version;
   int minor_version;
   struct riscv_subset_t *next;
+
+  bool explicit_version_p;
 };
 
 /* Type for implied ISA info.  */
@@ -80,19 +82,19 @@ private:
   riscv_subset_list (const char *, location_t);
 
   const char *parsing_subset_version (const char *, unsigned *, unsigned *,
-                                     unsigned, unsigned, bool);
+                                     unsigned, unsigned, bool, bool *);
 
   const char *parse_std_ext (const char *);
 
   const char *parse_multiletter_ext (const char *, const char *,
                                     const char *);
 
-  void handle_implied_ext (const char *, int, int);
+  void handle_implied_ext (const char *, int, int, bool);
 
 public:
   ~riscv_subset_list ();
 
-  void add (const char *, int, int);
+  void add (const char *, int, int, bool);
 
   riscv_subset_t *lookup (const char *,
                          int major_version = RISCV_DONT_CARE_VERSION,
@@ -111,7 +113,8 @@ static const char *riscv_supported_std_ext (void);
 static riscv_subset_list *current_subset_list = NULL;
 
 riscv_subset_t::riscv_subset_t ()
-  : name (), major_version (0), minor_version (0), next (NULL)
+  : name (), major_version (0), minor_version (0), next (NULL),
+    explicit_version_p (false)
 {
 }
 
@@ -138,7 +141,7 @@ riscv_subset_list::~riscv_subset_list ()
 
 void
 riscv_subset_list::add (const char *subset, int major_version,
-                       int minor_version)
+                       int minor_version, bool explicit_version_p)
 {
   riscv_subset_t *s = new riscv_subset_t ();
 
@@ -148,6 +151,7 @@ riscv_subset_list::add (const char *subset, int major_version,
   s->name = subset;
   s->major_version = major_version;
   s->minor_version = minor_version;
+  s->explicit_version_p = explicit_version_p;
   s->next = NULL;
 
   if (m_tail != NULL)
@@ -173,13 +177,15 @@ riscv_subset_list::to_string (bool version_p) const
       /* For !version_p, we only separate extension with underline for
         multi-letter extension.  */
       if (!first &&
-         (version_p || subset->name.length() > 1))
+         (version_p
+          || subset->explicit_version_p
+          || subset->name.length() > 1))
        oss << '_';
       first = false;
 
       oss << subset->name;
 
-      if (version_p)
+      if (version_p || subset->explicit_version_p)
        oss  << subset->major_version
             << 'p'
             << subset->minor_version;
@@ -240,7 +246,8 @@ riscv_supported_std_ext (void)
      `major_version` using default_major_version.
      `default_major_version`: Default major version.
      `default_minor_version`: Default minor version.
-     `std_ext_p`: True if parsing std extension.  */
+     `std_ext_p`: True if parsing std extension.
+     `explicit_version_p`: True if this subset is not using default version.  */
 
 const char *
 riscv_subset_list::parsing_subset_version (const char *p,
@@ -248,13 +255,15 @@ riscv_subset_list::parsing_subset_version (const char *p,
                                           unsigned *minor_version,
                                           unsigned default_major_version,
                                           unsigned default_minor_version,
-                                          bool std_ext_p)
+                                          bool std_ext_p,
+                                          bool *explicit_version_p)
 {
   bool major_p = true;
   unsigned version = 0;
   unsigned major = 0;
   unsigned minor = 0;
   char np;
+  *explicit_version_p = false;
 
   for (; *p; ++p)
     {
@@ -269,6 +278,7 @@ riscv_subset_list::parsing_subset_version (const char *p,
                {
                  *major_version = version;
                  *minor_version = 0;
+                 *explicit_version_p = true;
                  return p;
                }
              else
@@ -302,6 +312,7 @@ riscv_subset_list::parsing_subset_version (const char *p,
     }
   else
     {
+      *explicit_version_p = true;
       *major_version = major;
       *minor_version = minor;
     }
@@ -325,6 +336,7 @@ riscv_subset_list::parse_std_ext (const char *p)
   unsigned major_version = 0;
   unsigned minor_version = 0;
   char std_ext = '\0';
+  bool explicit_version_p = false;
 
   /* First letter must start with i, e or g.  */
   switch (*p)
@@ -334,8 +346,9 @@ riscv_subset_list::parse_std_ext (const char *p)
       p = parsing_subset_version (p, &major_version, &minor_version,
                                  /* default_major_version= */ 2,
                                  /* default_minor_version= */ 0,
-                                 /* std_ext_p= */ true);
-      add ("i", major_version, minor_version);
+                                 /* std_ext_p= */ true,
+                                 &explicit_version_p);
+      add ("i", major_version, minor_version, explicit_version_p);
       break;
 
     case 'e':
@@ -343,9 +356,10 @@ riscv_subset_list::parse_std_ext (const char *p)
       p = parsing_subset_version (p, &major_version, &minor_version,
                                  /* default_major_version= */ 1,
                                  /* default_minor_version= */ 9,
-                                 /* std_ext_p= */ true);
+                                 /* std_ext_p= */ true,
+                                 &explicit_version_p);
 
-      add ("e", major_version, minor_version);
+      add ("e", major_version, minor_version, explicit_version_p);
 
       if (m_xlen > 32)
        {
@@ -360,13 +374,14 @@ riscv_subset_list::parse_std_ext (const char *p)
       p = parsing_subset_version (p, &major_version, &minor_version,
                                  /* default_major_version= */ 2,
                                  /* default_minor_version= */ 0,
-                                 /* std_ext_p= */ true);
-      add ("i", major_version, minor_version);
+                                 /* std_ext_p= */ true,
+                                 &explicit_version_p);
+      add ("i", major_version, minor_version, explicit_version_p);
 
       for (; *std_exts != 'q'; std_exts++)
        {
          const char subset[] = {*std_exts, '\0'};
-         add (subset, major_version, minor_version);
+         add (subset, major_version, minor_version, explicit_version_p);
        }
       break;
 
@@ -413,24 +428,28 @@ riscv_subset_list::parse_std_ext (const char *p)
       p = parsing_subset_version (p, &major_version, &minor_version,
                                  /* default_major_version= */ 2,
                                  /* default_minor_version= */ 0,
-                                 /* std_ext_p= */ true);
+                                 /* std_ext_p= */ true,
+                                 &explicit_version_p);
 
       subset[0] = std_ext;
 
-      handle_implied_ext (subset, major_version, minor_version);
+      handle_implied_ext (subset, major_version,
+                         minor_version, explicit_version_p);
 
-      add (subset, major_version, minor_version);
+      add (subset, major_version, minor_version, explicit_version_p);
     }
   return p;
 }
 
 
 /* Check any implied extensions for EXT with version
-   MAJOR_VERSION.MINOR_VERSION.  */
+   MAJOR_VERSION.MINOR_VERSION, EXPLICIT_VERSION_P indicate the version is
+   explicitly given by user or not.  */
 void
 riscv_subset_list::handle_implied_ext (const char *ext,
                                       int major_version,
-                                      int minor_version)
+                                      int minor_version,
+                                      bool explicit_version_p)
 {
   riscv_implied_info_t *implied_info;
   for (implied_info = &riscv_implied_info[0];
@@ -445,7 +464,8 @@ riscv_subset_list::handle_implied_ext (const char *ext,
        continue;
 
       /* TODO: Implied extension might use different version.  */
-      add (implied_info->implied_ext, major_version, minor_version);
+      add (implied_info->implied_ext, major_version, minor_version,
+          explicit_version_p);
     }
 }
 
@@ -482,6 +502,7 @@ riscv_subset_list::parse_multiletter_ext (const char *p,
       char *subset = xstrdup (p);
       char *q = subset;
       const char *end_of_version;
+      bool explicit_version_p = false;
 
       while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
        ;
@@ -490,11 +511,12 @@ riscv_subset_list::parse_multiletter_ext (const char *p,
        = parsing_subset_version (q, &major_version, &minor_version,
                                  /* default_major_version= */ 2,
                                  /* default_minor_version= */ 0,
-                                 /* std_ext_p= */ FALSE);
+                                 /* std_ext_p= */ FALSE,
+                                 &explicit_version_p);
 
       *q = '\0';
 
-      add (subset, major_version, minor_version);
+      add (subset, major_version, minor_version, explicit_version_p);
       free (subset);
       p += end_of_version - subset;
 
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-13.c b/gcc/testsuite/gcc.target/riscv/attribute-13.c
new file mode 100644 (file)
index 0000000..1e86001
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_f3p0_d2p0\"" } } */