RISC-V: Allow to add numbers in the prefixed extension names.
authorNelson Chu <nelson.chu@sifive.com>
Tue, 28 Sep 2021 08:47:23 +0000 (16:47 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Tue, 28 Sep 2021 11:39:12 +0000 (19:39 +0800)
We need to allow adding numbers in the prefixed extension names, since
the zve<32,64><d,f,x> extensions are included in the forzen rvv v1.0 spec
recently.  But there are two restrictions as follows,

* The extension name ends with <number>p is invalid, since this may
be confused with extension with <number>.0 version.  We report errors
for this case.

Invalid format: [z|h|s|zvm|x][0-9a-z]+[0-9]+p

* The extension name ends with numbers is valid, but the numbers will
be parsed as major version, so try to avoid naming extensions like this.

bfd/
* elfxx-riscv.c (riscv_recognized_prefixed_ext): Renamed from
riscv_valid_prefixed_ext/
(riscv_parsing_subset_version): The extensions end with <number>p
is forbidden, we already report the detailed errors in the
riscv_parse_prefixed_ext, so clean the code and unused parameters.
(riscv_parse_std_ext): Updated.
(riscv_parse_prefixed_ext): Rewrite the parser to allow numbers
in the prefixed extension names.
gas/
* testsuite/gas/riscv/march-fail-invalid-x-01.d: New testcases.
* testsuite/gas/riscv/march-fail-invalid-x-02.d: Likewise.
* testsuite/gas/riscv/march-fail-invalid-z-01.d: Likewise.
* testsuite/gas/riscv/march-fail-invalid-z-02.d: Likewise.
* testsuite/gas/riscv/march-fail-invalid.l: Likewise.
* testsuite/gas/riscv/march-fail-version-x.d: Removed.
* testsuite/gas/riscv/march-fail-version-z.d: Likewise.
* testsuite/gas/riscv/march-fail-version.l: Likewise.

bfd/elfxx-riscv.c
gas/testsuite/gas/riscv/march-fail-invalid-x-01.d [new file with mode: 0644]
gas/testsuite/gas/riscv/march-fail-invalid-x-02.d [new file with mode: 0644]
gas/testsuite/gas/riscv/march-fail-invalid-z-01.d [new file with mode: 0644]
gas/testsuite/gas/riscv/march-fail-invalid-z-02.d [new file with mode: 0644]
gas/testsuite/gas/riscv/march-fail-invalid.l [new file with mode: 0644]
gas/testsuite/gas/riscv/march-fail-version-x.d [deleted file]
gas/testsuite/gas/riscv/march-fail-version-z.d [deleted file]
gas/testsuite/gas/riscv/march-fail-version.l [deleted file]

index b467bceb919de1236b6b878af81e72146e1bffb7..c3d019c03a6a57fb44d2d275e976bfa9b04ac5fc 100644 (file)
@@ -1236,11 +1236,11 @@ riscv_known_prefixed_ext (const char *ext,
   return false;
 }
 
-/* Check whether the prefixed extension is valid or not.  Return
-   true if valid, otehrwise return false.  */
+/* Check whether the prefixed extension is recognized or not.  Return
+   true if recognized, otehrwise return false.  */
 
 static bool
-riscv_valid_prefixed_ext (const char *ext)
+riscv_recognized_prefixed_ext (const char *ext)
 {
   enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
   switch (class)
@@ -1254,7 +1254,7 @@ riscv_valid_prefixed_ext (const char *ext)
   case RV_ISA_CLASS_H:
     return riscv_known_prefixed_ext (ext, riscv_supported_std_h_ext);
   case RV_ISA_CLASS_X:
-    /* Only the single x is invalid.  */
+    /* Only the single x is unrecognized.  */
     if (strcmp (ext, "x") != 0)
       return true;
   default:
@@ -1515,20 +1515,14 @@ riscv_release_subset_list (riscv_subset_list_t *subset_list)
      Points to the end of version
 
    Arguments:
-     `rps`: Hooks and status for parsing extensions.
-     `arch`: Full ISA string.
      `p`: Curent parsing position.
      `major_version`: Parsed major version.
-     `minor_version`: Parsed minor version.
-     `std_ext_p`: True if parsing standard extension.  */
+     `minor_version`: Parsed minor version.  */
 
 static const char *
-riscv_parsing_subset_version (riscv_parse_subset_t *rps,
-                             const char *arch,
-                             const char *p,
+riscv_parsing_subset_version (const char *p,
                              int *major_version,
-                             int *minor_version,
-                             bool std_ext_p)
+                             int *minor_version)
 {
   bool major_p = true;
   int version = 0;
@@ -1545,19 +1539,9 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
          if (!ISDIGIT (np))
            {
              /* Might be beginning of `p` extension.  */
-             if (std_ext_p)
-               {
-                 *major_version = version;
-                 *minor_version = 0;
-                 return p;
-               }
-             else
-               {
-                 rps->error_handler
-                   (_("%s: expect number after `%dp'"),
-                    arch, version);
-                 return NULL;
-               }
+             *major_version = version;
+             *minor_version = 0;
+             return p;
            }
 
          *major_version = version;
@@ -1648,7 +1632,7 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
          return NULL;
        }
 
-      p = riscv_parsing_subset_version (rps, arch, ++p, &major, &minor, true);
+      p = riscv_parsing_subset_version (++p, &major, &minor);
       /* Added g as an implicit extension.  */
       if (subset[0] == 'g')
        {
@@ -1703,29 +1687,51 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
       char *q = subset;
       const char *end_of_version;
 
-      while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
+      /* Extract the whole prefixed extension by '_'.  */
+      while (*++q != '\0' && *q != '_')
        ;
+      /* Look forward to the first letter which is not <major>p<minor>.  */
+      bool find_any_version = false;
+      bool find_minor_version = false;
+      while (1)
+       {
+         q--;
+         if (ISDIGIT (*q))
+           find_any_version = true;
+         else if (find_any_version
+                  && !find_minor_version
+                  && *q == 'p'
+                  && ISDIGIT (*(q - 1)))
+           find_minor_version = true;
+         else
+           break;
+       }
+      q++;
+
+      /* Check if the end of extension is 'p' or not.  If yes, then
+        the second letter from the end cannot be number.  */
+      if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
+       {
+         *q = '\0';
+         rps->error_handler
+           (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
+            arch, subset);
+         free (subset);
+         return NULL;
+       }
 
       end_of_version =
-       riscv_parsing_subset_version (rps, arch, q,
-                                     &major_version,
-                                     &minor_version, false);
+       riscv_parsing_subset_version (q, &major_version, &minor_version);
       *q = '\0';
-
       if (end_of_version == NULL)
        {
          free (subset);
          return NULL;
        }
 
-      /* Check if the prefix extension is known.
-        For 'x', anything goes but it cannot simply be 'x'.
-        For other prefixed extensions, it must be known from a list
-        and cannot simply be the prefixed name.  */
-
       /* Check that the extension name is well-formed.  */
       if (rps->check_unknown_prefixed_ext
-         && !riscv_valid_prefixed_ext (subset))
+         && !riscv_recognized_prefixed_ext (subset))
        {
          rps->error_handler
            (_("%s: unknown prefixed ISA extension `%s'"),
diff --git a/gas/testsuite/gas/riscv/march-fail-invalid-x-01.d b/gas/testsuite/gas/riscv/march-fail-invalid-x-01.d
new file mode 100644 (file)
index 0000000..929cfac
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv32i_zicsr2p0_xargle2p
+#source: empty.s
+#error_output: march-fail-invalid.l
diff --git a/gas/testsuite/gas/riscv/march-fail-invalid-x-02.d b/gas/testsuite/gas/riscv/march-fail-invalid-x-02.d
new file mode 100644 (file)
index 0000000..d85f16a
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv32i_zicsr2p0_xargle2p3p0
+#source: empty.s
+#error_output: march-fail-invalid.l
diff --git a/gas/testsuite/gas/riscv/march-fail-invalid-z-01.d b/gas/testsuite/gas/riscv/march-fail-invalid-z-01.d
new file mode 100644 (file)
index 0000000..5ecc72a
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv32i_zicsr2p
+#source: empty.s
+#error_output: march-fail-invalid.l
diff --git a/gas/testsuite/gas/riscv/march-fail-invalid-z-02.d b/gas/testsuite/gas/riscv/march-fail-invalid-z-02.d
new file mode 100644 (file)
index 0000000..38e8def
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -march=rv32i_zicsr2p4p0
+#source: empty.s
+#error_output: march-fail-invalid.l
diff --git a/gas/testsuite/gas/riscv/march-fail-invalid.l b/gas/testsuite/gas/riscv/march-fail-invalid.l
new file mode 100644 (file)
index 0000000..804c361
--- /dev/null
@@ -0,0 +1,2 @@
+.*Assembler messages:
+.*Error: .*invalid prefixed ISA extension `[0-9a-z]+' ends with <number>p
diff --git a/gas/testsuite/gas/riscv/march-fail-version-x.d b/gas/testsuite/gas/riscv/march-fail-version-x.d
deleted file mode 100644 (file)
index 8e140e3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#as: -march=rv32i2p_zicsr2p0_xargle2p
-#source: empty.s
-#error_output: march-fail-version.l
diff --git a/gas/testsuite/gas/riscv/march-fail-version-z.d b/gas/testsuite/gas/riscv/march-fail-version-z.d
deleted file mode 100644 (file)
index 73ca579..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#as: -march=rv32i2p_zicsr2p
-#source: empty.s
-#error_output: march-fail-version.l
diff --git a/gas/testsuite/gas/riscv/march-fail-version.l b/gas/testsuite/gas/riscv/march-fail-version.l
deleted file mode 100644 (file)
index c7f8a4d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.*Assembler messages:
-.*Error: cannot find default versions of the ISA extension `p'
-.*Error: .*expect number after `2p'