[committed,1/2] RISC-V: Allow to add numbers in the prefixed extension names.

Message ID 20210928114138.2049-1-nelson.chu@sifive.com
State New
Headers show
Series
  • [committed,1/2] RISC-V: Allow to add numbers in the prefixed extension names.
Related show

Commit Message

Nelson Chu Sept. 28, 2021, 11:41 a.m.
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                             | 82 ++++++++++---------
 .../gas/riscv/march-fail-invalid-x-01.d       |  3 +
 .../gas/riscv/march-fail-invalid-x-02.d       |  3 +
 .../gas/riscv/march-fail-invalid-z-01.d       |  3 +
 .../gas/riscv/march-fail-invalid-z-02.d       |  3 +
 gas/testsuite/gas/riscv/march-fail-invalid.l  |  2 +
 .../gas/riscv/march-fail-version-x.d          |  3 -
 .../gas/riscv/march-fail-version-z.d          |  3 -
 gas/testsuite/gas/riscv/march-fail-version.l  |  3 -
 9 files changed, 58 insertions(+), 47 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/march-fail-invalid-x-01.d
 create mode 100644 gas/testsuite/gas/riscv/march-fail-invalid-x-02.d
 create mode 100644 gas/testsuite/gas/riscv/march-fail-invalid-z-01.d
 create mode 100644 gas/testsuite/gas/riscv/march-fail-invalid-z-02.d
 create mode 100644 gas/testsuite/gas/riscv/march-fail-invalid.l
 delete mode 100644 gas/testsuite/gas/riscv/march-fail-version-x.d
 delete mode 100644 gas/testsuite/gas/riscv/march-fail-version-z.d
 delete mode 100644 gas/testsuite/gas/riscv/march-fail-version.l

-- 
2.30.2

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index b467bceb919..c3d019c03a6 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -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
index 00000000000..929cfac7a74
--- /dev/null
+++ b/gas/testsuite/gas/riscv/march-fail-invalid-x-01.d
@@ -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
index 00000000000..d85f16a42fa
--- /dev/null
+++ b/gas/testsuite/gas/riscv/march-fail-invalid-x-02.d
@@ -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
index 00000000000..5ecc72aa312
--- /dev/null
+++ b/gas/testsuite/gas/riscv/march-fail-invalid-z-01.d
@@ -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
index 00000000000..38e8def0eb6
--- /dev/null
+++ b/gas/testsuite/gas/riscv/march-fail-invalid-z-02.d
@@ -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
index 00000000000..804c3617f6f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/march-fail-invalid.l
@@ -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
index 8e140e3d5f3..00000000000
--- a/gas/testsuite/gas/riscv/march-fail-version-x.d
+++ /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
index 73ca5794bfe..00000000000
--- a/gas/testsuite/gas/riscv/march-fail-version-z.d
+++ /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
index c7f8a4d5487..00000000000
--- a/gas/testsuite/gas/riscv/march-fail-version.l
+++ /dev/null
@@ -1,3 +0,0 @@ 
-.*Assembler messages:
-.*Error: cannot find default versions of the ISA extension `p'
-.*Error: .*expect number after `2p'