[PATCH] Add support for RISC-V Z-extension arch attributes.

Maxim Blinov maxim.blinov@embecosm.com
Mon Jul 29 13:10:00 GMT 2019


Hi all,

This patch adds support for operating with the proposed 
Z-extension architecture attributes. Some examples:

 -march=rv32imfzifencei
 -march=rv32imfzifencei_ztso
 -march=rv32imzbb_zbc_zbt_ztso_xcoolfeature

The new parsing code expects to find zero or more 'z'-prefixed
ISA specifiers at the end of the architecture string, but before
the 'x'-prefixed non-standard extensions. The sequence of the 
Z-extensions must be strictly alphabetical. Duplicate
entries cause an error, and unknown extensions cause an error.

I have changed the order of extension parsing to the following:
1: 's' (standard supervisor extensions)
2: 'sx' (non-standard standard supervisor extensions)
3: 'z' (standard extensions)
4: 'x' (non-standard extensions)

The order before this patch was as follows:
1: 'x'
2: 's'
3: 'sx'

since the spec states that X-prefixed extensions should be at the end,
and from what I understand the Z-prefixed extensions should precede them.

I've added a table specifying all the currently known Z-extensions.
These are:

zam, zbb, zbc, zbe, zbf, zbm, zbp, zbr, zbs, zbt, zifencei, ztso.

With regards to merging two object files into one: New merging
code is added which takes care that the two object files do
not have mismatching Z-extension versions, and also takes
care to output the extension arch string in alphabetical order.

Finally, I've added some tests which demonstrate the error
checking paths.

Best Regards,
Maxim Blinov

bfd/ChangeLog
2019-07-29  Maxim Blinov  <maxim.blinov@embecosm.com>

	* elfnn-riscv.c (riscv_std_z_ext_p): New function.
	(riscv_init_std_z_ext_mergetab): Likewise.
	(riscv_populate_std_z_ext_mergetab): Likewise.
	(riscv_merge_std_z_ext_from_mergetab): Likewise.
	(riscv_merge_std_z_ext): Likewise.
	(riscv_merge_arch_attr_info): Also merge Z-extensions.
	(RISCV_MERGETAB_VER_MATCH_P): New macro.
	* elfxx-riscv.c (riscv_parse_std_ext): Break upon 'z'.
	(riscv_parse_sv_or_non_std_ext): Likewise.
	(z_ext_strtab): New constant string table.
	(riscv_std_z_ext_index): New function.
	(riscv_valid_std_z_ext_p): Likewise.
	(riscv_parse_std_z_ext): Likewise.
	(riscv_parse_subset): Call riscv_parse_std_z_ext.
	* elfxx-riscv.h (RISCV_STD_Z_EXT_COUNT): New define.
	(z_ext_strtab): Declare.
	(riscv_std_z_ext_index): Likewise.

ld/ChangeLog
2019-07-29  Maxim Blinov  <maxim.blinov@embecosm.com>

	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d,
	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s,
	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s: New test.
	* testsuite/ld-riscv-elf/attr-merge-dupl-z-failed-01.d,
	* testsuite/ld-riscv-elf/attr-merge-dupl-z-failed-01.s: New test.
	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-01.d,
	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-01.s: New test.
	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-02.d,
	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-02.s: New test.
	* testsuite/ld-riscv-elf/attr-merge-tooshort-z-failed-01.d,
	* testsuite/ld-riscv-elf/attr-merge-tooshort-z-failed-01.s: New test.
	* testsuite/ld-riscv-elf/attr-merge-unknown-z-failed-01.d,
	* testsuite/ld-riscv-elf/attr-merge-unknown-z-failed-01.s: New test.
	* testsuits/ld-riscv-elf/ld-riscv-elf.exp: Add new tests.
---
 bfd/ChangeLog                                 |  20 +++
 bfd/elfnn-riscv.c                             | 144 ++++++++++++++++
 bfd/elfxx-riscv.c                             | 163 +++++++++++++++++-
 bfd/elfxx-riscv.h                             |   6 +
 ld/ChangeLog                                  |  17 ++
 .../ld-riscv-elf/attr-dupl-arch-z-failed-01.d |   3 +
 .../ld-riscv-elf/attr-dupl-arch-z-failed-01.s |   1 +
 .../attr-merge-arch-z-failed-01.d             |   5 +
 .../attr-merge-arch-z-failed-01a.s            |   1 +
 .../attr-merge-arch-z-failed-01b.s            |   1 +
 .../attr-order-arch-z-failed-01.d             |   3 +
 .../attr-order-arch-z-failed-01.s             |   1 +
 .../attr-order-arch-z-failed-02.d             |   3 +
 .../attr-order-arch-z-failed-02.s             |   1 +
 .../attr-tooshort-arch-z-failed-01.d          |   3 +
 .../attr-tooshort-arch-z-failed-01.s          |   1 +
 .../attr-unknown-arch-z-failed-01.d           |   3 +
 .../attr-unknown-arch-z-failed-01.s           |   1 +
 ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp    |   6 +
 19 files changed, 376 insertions(+), 7 deletions(-)
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.s
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.d
 create mode 100644 ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.s

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4258351792..d0b4a4a348 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,23 @@
+2019-07-29  Maxim Blinov  <maxim.blinov@embecosm.com>
+
+	* elfnn-riscv.c (riscv_std_z_ext_p): New function.
+	(riscv_init_std_z_ext_mergetab): Likewise.
+	(riscv_populate_std_z_ext_mergetab): Likewise.
+	(riscv_merge_std_z_ext_from_mergetab): Likewise.
+	(riscv_merge_std_z_ext): Likewise.
+	(riscv_merge_arch_attr_info): Also merge Z-extensions.
+	(RISCV_MERGETAB_VER_MATCH_P): New macro.
+	* elfxx-riscv.c (riscv_parse_std_ext): Break upon 'z'.
+	(riscv_parse_sv_or_non_std_ext): Likewise.
+	(z_ext_strtab): New constant string table.
+	(riscv_std_z_ext_index): New function.
+	(riscv_valid_std_z_ext_p): Likewise.
+	(riscv_parse_std_z_ext): Likewise.
+	(riscv_parse_subset): Call riscv_parse_std_z_ext.
+	* elfxx-riscv.h (RISCV_STD_Z_EXT_COUNT): New define.
+	(z_ext_strtab): Declare.
+	(riscv_std_z_ext_index): Likewise.
+
 2019-07-29  Martin Liska  <mliska@suse.cz>
 
 	PR 24768
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 003b4f868d..e69526fdff 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -2702,6 +2702,14 @@ riscv_non_std_sv_ext_p (const char *name)
   return (strlen (name) >= 3) && (name[0] == 's') && (name[1] == 'x');
 }
 
+/* Predicator for Z standard extensions. */
+
+static bfd_boolean
+riscv_std_z_ext_p (const char *name)
+{
+  return (strlen (name) >= 2) && (name[0] == 'z');
+}
+
 /* Error handler when version mis-match.  */
 
 static void
@@ -2877,6 +2885,139 @@ riscv_merge_non_std_and_sv_ext (bfd *ibfd,
   return TRUE;
 }
 
+typedef struct riscv_std_z_ext_mergetab {
+  riscv_subset_t *input[RISCV_STD_Z_EXT_COUNT];
+  riscv_subset_t *output[RISCV_STD_Z_EXT_COUNT];
+} riscv_std_z_ext_mergetab_t;
+
+/* True if the two Z extension slots at index IDX of merge table MT
+   have the same version. False if otherwise. */
+
+#define RISCV_MERGETAB_VER_MATCH_P(MT, IDX)				\
+  ((MT->input[IDX]->major_version == MT->output[IDX]->major_version)	\
+   && (MT->input[IDX]->minor_version == MT->output[IDX]->minor_version))
+
+static void
+riscv_init_std_z_ext_mergetab (riscv_std_z_ext_mergetab_t *map)
+{
+  memset ((void *)map, 0, sizeof (riscv_std_z_ext_mergetab_t));
+}
+
+/* Read in the subsets pointed by *pin, and if it's a Z-extension
+   add it to the corresponding slot in `param`.
+   If we're here, then elfxx-riscv.c:riscv_parse_std_z_ext
+   already did all the checking for us. */
+
+static bfd_boolean
+riscv_populate_std_z_ext_mergetab (bfd *ibfd ATTRIBUTE_UNUSED,
+				   riscv_subset_t **pin,
+				   bfd_boolean (*predicate_func) (const char *),
+				   riscv_subset_t **param)
+{
+  riscv_subset_t *in;
+  int ext_idx = -1;
+
+  for (in = *pin; in != NULL && predicate_func (in->name); in = in->next)
+    {
+      ext_idx = riscv_std_z_ext_index (in->name);
+      param[ext_idx] = in;
+    }
+
+  return TRUE;
+}
+
+/* Produce a merged list of Z-extension subsets, in alphabetical order.
+   Report version mismatches. */
+
+static bfd_boolean
+riscv_merge_std_z_ext_from_mergetab (bfd *ibfd,
+				     riscv_subset_list_t *subset,
+				     riscv_std_z_ext_mergetab_t *mt)
+{
+  const riscv_subset_t *selected;
+  int i;
+  bfd_boolean status = TRUE;
+
+  for (i = 0; i < RISCV_STD_Z_EXT_COUNT; ++i)
+    {
+      /* Neither object files use this extension. Skip. */
+      if (!mt->input[i] && !mt->output[i])
+	{
+	  continue;
+	}
+
+      /* Both object files use this extension. */
+      else if (mt->input[i] && mt->output[i])
+	{
+	  if (!RISCV_MERGETAB_VER_MATCH_P(mt, i))
+	    {
+	      riscv_version_mismatch (ibfd, mt->input[i], mt->output[i]);
+	      /* Don't leave immediately; Try to keep going and find
+		 other errors. */
+	      status = FALSE;
+	    }
+
+	  if (status == TRUE)
+	    {
+	      riscv_add_subset (subset, mt->input[i]->name,
+				mt->input[i]->major_version,
+				mt->input[i]->minor_version);
+	    }
+	}
+
+      /* One object file uses this extension. */
+      else
+	{
+	  selected = (mt->input[i] ? mt->input[i] : mt->output[i]);
+
+	  if (status == TRUE)
+	    {
+	      riscv_add_subset (subset, selected->name,
+				selected->major_version,
+				selected->minor_version);
+	    }
+	}
+    }
+
+  return status;
+}
+
+static bfd_boolean
+riscv_merge_std_z_ext (bfd *ibfd,
+		       riscv_subset_t **pin,
+		       riscv_subset_t **pout,
+		       bfd_boolean (*predicate_func) (const char *))
+{
+  riscv_subset_t *in = *pin;
+  riscv_subset_t *out = *pout;
+
+  bfd_boolean status_in = TRUE;
+  bfd_boolean status_out = TRUE;
+
+  riscv_std_z_ext_mergetab_t mt;
+
+  /* Initialize table. */
+  riscv_init_std_z_ext_mergetab (&mt);
+
+  /* Populate table. */
+  status_in = riscv_populate_std_z_ext_mergetab
+    (ibfd, pin, predicate_func, mt.input);
+  status_out = riscv_populate_std_z_ext_mergetab
+    (ibfd, pout, predicate_func, mt.output);
+
+  if ( !(status_in && status_out) )
+    return FALSE;
+
+  /* Generate the combined arch string in alphabetical order from the table. */
+  if (riscv_merge_std_z_ext_from_mergetab
+      (ibfd, &merged_subsets, &mt) == FALSE)
+    return FALSE;
+
+  *pin = in;
+  *pout = out;
+  return TRUE;
+}
+
 /* Merge Tag_RISCV_arch attribute.  */
 
 static char *
@@ -2941,6 +3082,9 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
   /* Merge non-standard supervisor extension.  */
   if (!riscv_merge_non_std_and_sv_ext (ibfd, &in, &out, riscv_non_std_sv_ext_p))
     return NULL;
+  /* Merge standard Z extensions. */
+  if (!riscv_merge_std_z_ext (ibfd, &in, &out, riscv_std_z_ext_p))
+    return NULL;
 
   if (xlen_in != xlen_out)
     {
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 245717f70f..0a31824a65 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1193,7 +1193,7 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
     {
       char subset[2] = {0, 0};
 
-      if (*p == 'x' || *p == 's')
+      if (*p == 'x' || *p == 's' || *p == 'z')
 	break;
 
       if (*p == '_')
@@ -1276,6 +1276,10 @@ riscv_parse_sv_or_non_std_ext (riscv_parse_subset_t *rps,
 	  && (*(p + 1) == 'x'))
 	break;
 
+      /* It's a standard extension if its prefixed with Z. */
+      if (ext_type[0] == 'z')
+	break;
+
       char *subset = xstrdup (p);
       char *q = subset;
       const char *end_of_version;
@@ -1309,6 +1313,145 @@ riscv_parse_sv_or_non_std_ext (riscv_parse_subset_t *rps,
   return p;
 }
 
+const char * const z_ext_strtab[RISCV_STD_Z_EXT_COUNT] =
+  {
+   "zam",
+
+   /* Standard Bitmanip ISA subsets. */
+   "zbb", "zbc", "zbe", "zbf", "zbm", "zbp", "zbr", "zbs", "zbt",
+
+   "zifencei", "ztso"
+  };
+
+int
+riscv_std_z_ext_index (const char *ext)
+{
+  size_t i;
+
+  for (i = 0; i < ARRAY_SIZE (z_ext_strtab); ++i)
+    {
+      if (!strcmp (z_ext_strtab[i], ext))
+	return i;
+    }
+
+  return -1;
+}
+
+static int
+riscv_valid_std_z_ext_p (const char *ext)
+{
+  size_t len = strlen (ext);
+  size_t i;
+  int found = 0;
+  char *lower = (char *) xmalloc (len + 1);
+
+  strcpy (lower, ext);
+
+  /* Convert string to all-lowercase. */
+  for (i = 0; i < len; ++i)
+    {
+      if (ISUPPER (ext[i]))
+	lower[i] += 'a' - 'A';
+    }
+
+  for (i = 0; i < ARRAY_SIZE (z_ext_strtab); ++i)
+    {
+      if (!strcmp (lower, z_ext_strtab[i]))
+	{
+	  found = 1;
+	  break;
+	}
+    }
+
+  free (lower);
+  return found;
+}
+
+static const char *
+riscv_parse_std_z_ext (riscv_parse_subset_t *rps,
+		       const char *arch, const char *p)
+{
+  char *name_buffer;
+  const char *iter;
+  const char *last_name;
+
+  unsigned int major_version;
+  unsigned int minor_version;
+
+  size_t name_len;
+
+ start:
+  /* Assert this is prefixed with 'z' */
+  if (*p != 'z')
+    return p;
+
+  /* Try and get the name */
+  for (iter = p; ISALPHA (*iter); ++iter);
+  name_len = (size_t) (iter - p);
+
+  /* Check we're not just a literal {'z', '\0'}. */
+  if (name_len < 2)
+    {
+      rps->error_handler ("-march=%s: Literal '%c' is an invalid"
+			  " Z ISA extension specifier.",
+			  arch, p[0]);
+      return NULL;
+    }
+
+  name_buffer = (char *) xmalloc (sizeof (char) * (name_len + 1));
+
+  strncpy (name_buffer, p, name_len);
+  name_buffer[name_len] = '\0';
+
+  /* Assert that this is a known Z-extension. */
+  if (!riscv_valid_std_z_ext_p (name_buffer))
+    {
+      rps->error_handler ("-march=%s: Unknown Z ISA extension: \'%s\'",
+			  arch, name_buffer);
+      free (name_buffer);
+      return NULL;
+    }
+
+  /* Assert that the last item is not the same as this. */
+  last_name = rps->subset_list->tail->name;
+
+  if (!strcmp (last_name, name_buffer))
+    {
+      rps->error_handler ("-march=%s: Duplicate Z ISA extension: \'%s\'",
+			  arch, name_buffer);
+      free (name_buffer);
+      return NULL;
+    }
+
+  /* Assert that we are in alphabetical order. */
+  if (riscv_valid_std_z_ext_p (last_name)
+      && strcmp (last_name, name_buffer) > 0)
+    {
+      rps->error_handler ("-march=%s: Z ISA extension not in alphabetical order: "
+			  "\'%s\' must come before \'%s\'.",
+			  arch, name_buffer, last_name);
+      free (name_buffer);
+      return NULL;
+    }
+
+  iter = riscv_parsing_subset_version (
+				       rps,
+				       arch,
+				       iter, &major_version, &minor_version,
+				       /* default_major_version= */ 2,
+				       /* default_minor_version= */ 0,
+				       /* std_ext_p= */TRUE);
+  riscv_add_subset (rps->subset_list, name_buffer, major_version, minor_version);
+  free (name_buffer);
+
+  /* Skip trailing whitespace */
+  for (; *iter == '_'; iter++);
+  p = iter;
+
+  /* Try parsing another Z extension */
+  goto start;
+}
+
 /* Function for parsing arch string.
 
    Return Value:
@@ -1347,23 +1490,29 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
   if (p == NULL)
     return FALSE;
 
-  /* Parsing non-standard extension.  */
+  /* Parsing supervisor extension.  */
   p = riscv_parse_sv_or_non_std_ext (
-	rps, arch, p, "x", "non-standard extension");
+	rps, arch, p, "s", "supervisor extension");
 
   if (p == NULL)
     return FALSE;
 
-  /* Parsing supervisor extension.  */
+  /* Parsing non-standard supervisor extension.  */
   p = riscv_parse_sv_or_non_std_ext (
-	rps, arch, p, "s", "supervisor extension");
+	rps, arch, p, "sx", "non-standard supervisor extension");
+  
+  if (p == NULL)
+    return FALSE;
+  
+  /* Parsing standard extensions. */
+  p = riscv_parse_std_z_ext (rps, arch, p);
 
   if (p == NULL)
     return FALSE;
 
-  /* Parsing non-standard supervisor extension.  */
+  /* Parsing non-standard extension.  */
   p = riscv_parse_sv_or_non_std_ext (
-	rps, arch, p, "sx", "non-standard supervisor extension");
+	rps, arch, p, "x", "non-standard extension");
 
   if (p == NULL)
     return FALSE;
diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
index 19f7bd2ecc..13276d67e5 100644
--- a/bfd/elfxx-riscv.h
+++ b/bfd/elfxx-riscv.h
@@ -86,3 +86,9 @@ riscv_release_subset_list (riscv_subset_list_t *);
 
 extern char *
 riscv_arch_str (unsigned, const riscv_subset_list_t *);
+
+#define RISCV_STD_Z_EXT_COUNT 12
+extern const char * const z_ext_strtab[RISCV_STD_Z_EXT_COUNT];
+
+int
+riscv_std_z_ext_index (const char *ext);
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1309324eed..2b4e6ef4d2 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,20 @@
+2019-07-29  Maxim Blinov  <maxim.blinov@embecosm.com>
+
+	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d,
+	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s,
+	* testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s: New test.
+	* testsuite/ld-riscv-elf/attr-merge-dupl-z-failed-01.d,
+	* testsuite/ld-riscv-elf/attr-merge-dupl-z-failed-01.s: New test.
+	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-01.d,
+	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-01.s: New test.
+	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-02.d,
+	* testsuite/ld-riscv-elf/attr-merge-order-z-failed-02.s: New test.
+	* testsuite/ld-riscv-elf/attr-merge-tooshort-z-failed-01.d,
+	* testsuite/ld-riscv-elf/attr-merge-tooshort-z-failed-01.s: New test.
+	* testsuite/ld-riscv-elf/attr-merge-unknown-z-failed-01.d,
+	* testsuite/ld-riscv-elf/attr-merge-unknown-z-failed-01.s: New test.
+	* testsuits/ld-riscv-elf/ld-riscv-elf.exp: Add new tests.
+
 2019-07-26  Alan Modra  <amodra@gmail.com>
 
 	* testsuite/ld-plugin/lto-3r.d: Accept D for powerpc64 descriptors.
diff --git a/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.d
new file mode 100644
index 0000000000..20b4530f0a
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.d
@@ -0,0 +1,3 @@
+#source: attr-dupl-arch-z-failed-01.s
+#as: -march-attr
+#error: -march=rv32i2p0_zbc_zbc: Duplicate Z ISA extension: 'zbc'
diff --git a/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.s b/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.s
new file mode 100644
index 0000000000..96d67e1833
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-dupl-arch-z-failed-01.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_zbc_zbc"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d
new file mode 100644
index 0000000000..d82c1c2868
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01.d
@@ -0,0 +1,5 @@
+#source: attr-merge-arch-z-failed-01a.s
+#source: attr-merge-arch-z-failed-01b.s
+#as: -march-attr
+#ld: -r -melf32lriscv
+#error: Mis-matched ISA version for 'zbb' extension. 2.1 vs 2.0
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s
new file mode 100644
index 0000000000..6768e78c52
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01a.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_zbb2p0"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s
new file mode 100644
index 0000000000..4279973411
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-z-failed-01b.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_zbb2p1"
diff --git a/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.d
new file mode 100644
index 0000000000..809d8ba607
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.d
@@ -0,0 +1,3 @@
+#source: attr-order-arch-z-failed-01.s
+#as: -march-attr
+#error: -march=rv32i2p0_zbc_zbb: Z ISA extension not in alphabetical order: 'zbb' must come before 'zbc'.
diff --git a/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.s b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.s
new file mode 100644
index 0000000000..e31e3766ca
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-01.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_zbc_zbb"
diff --git a/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.d b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.d
new file mode 100644
index 0000000000..19a5482300
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.d
@@ -0,0 +1,3 @@
+#source: attr-order-arch-z-failed-02.s
+#as: -march-attr
+#error: -march=rv32i2p0_xsillyname_zbb: unexpected ISA string at end: zbb
diff --git a/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.s b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.s
new file mode 100644
index 0000000000..b1abe26891
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-order-arch-z-failed-02.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_xsillyname_zbb"
diff --git a/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.d
new file mode 100644
index 0000000000..4a6885db5e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.d
@@ -0,0 +1,3 @@
+#source: attr-tooshort-arch-z-failed-01.s
+#as: -march-attr
+#error: -march=rv32i2p0_z: Literal 'z' is an invalid Z ISA extension specifier.
diff --git a/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.s b/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.s
new file mode 100644
index 0000000000..7ca87fabf4
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-tooshort-arch-z-failed-01.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_z"
diff --git a/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.d
new file mode 100644
index 0000000000..343db87a41
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.d
@@ -0,0 +1,3 @@
+#source: attr-unknown-arch-z-failed-01.s
+#as: -march-attr
+#error: -march=rv32i2p0_zsillyname: Unknown Z ISA extension: 'zsillyname'
diff --git a/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.s b/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.s
new file mode 100644
index 0000000000..6e16bef91d
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/attr-unknown-arch-z-failed-01.s
@@ -0,0 +1 @@
+	.attribute arch, "rv32i2p0_zsillyname"
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index bce7bfeeba..79990efedf 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -36,6 +36,12 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "attr-merge-priv-spec"
     run_dump_test "attr-merge-arch-failed-01"
     run_dump_test "attr-merge-stack-align-failed"
+    run_dump_test "attr-merge-arch-z-failed-01"
+    run_dump_test "attr-dupl-arch-z-failed-01"
+    run_dump_test "attr-order-arch-z-failed-01"
+    run_dump_test "attr-order-arch-z-failed-02"
+    run_dump_test "attr-tooshort-arch-z-failed-01"
+    run_dump_test "attr-unknown-arch-z-failed-01"
     run_ld_link_tests {
 	{ "Weak reference 32" "-T weakref.ld -melf32lriscv" ""
 	    "-march=rv32i -mabi=ilp32" {weakref32.s}
-- 
2.20.1



More information about the Binutils mailing list