summaryrefslogtreecommitdiff
path: root/bfd/elfxx-riscv.c
diff options
context:
space:
mode:
authorNelson Chu <nelson.chu@sifive.com>2021-09-28 16:47:23 +0800
committerNelson Chu <nelson.chu@sifive.com>2021-09-28 19:39:12 +0800
commit69a61890cb94746e5a564776081c3cefa8fca408 (patch)
treeed6d38097517c5b08a1af465815426a3733fc2e9 /bfd/elfxx-riscv.c
parent91f2597bd24d171c1337a4629f8237aa47c59082 (diff)
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><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.
Diffstat (limited to 'bfd/elfxx-riscv.c')
-rw-r--r--bfd/elfxx-riscv.c82
1 files changed, 44 insertions, 38 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index b467bceb91..c3d019c03a 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'"),