From 69a61890cb94746e5a564776081c3cefa8fca408 Mon Sep 17 00:00:00 2001 From: Nelson Chu Date: Tue, 28 Sep 2021 16:47:23 +0800 Subject: [PATCH] RISC-V: Allow to add numbers in the prefixed extension names. We need to allow adding numbers in the prefixed extension names, since the zve<32,64> extensions are included in the forzen rvv v1.0 spec recently. But there are two restrictions as follows, * The extension name ends with p is invalid, since this may be confused with extension with .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 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 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 p. */ + 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 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 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' -- 2.30.2