mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
RISC-V: Minor updates for architecture parser.
* Two add subset functions is redundant. Keep the riscv_add_implicit_subset, and renamed it to riscv_add_subset. Besides, if the subset is added in order, then we just add it at the tail of the subset list. * Removed the "-march:" prefix from the error messages. Since not only the -march= option will use the parser, but also the architecture elf attributes, the default architecture setting and linker will use the same parser. * Use a function, riscv_parse_check_conflicts, to check the conflicts of extensions, including the rv64e and rv32q. The rv32emc-elf/rv32i-elf/rv32gc-linux/rv64gc-elf/rv64gc-linux regressions are tested and passed. bfd/ * elfxx-riscv.c (riscv_lookup_subset): Check the subset tail list first. If the subset is added in order, then we can just add it to the tail without searching the whole list. (riscv_add_subset): Replaced by riscv_add_implicit_subset. (riscv_add_implicit_subset): Renamed to riscv_add_subset. (riscv_parse_add_subset): Updated. (riscv_parsing_subset_version): Removed the "-march:" prefix from the error message. (riscv_parse_prefixed_ext): Likewise. (riscv_parse_std_ext): Likewise. And move the rv<xlen>e check to riscv_parse_check_conflicts. (riscv_parse_check_conflicts): New function used to check conflicts. (riscv_parse_subset): Updated. gas/ * testsuite/gas/riscv/march-fail-base-02.l: Updated. * testsuite/gas/riscv/march-fail-unknown-std.l: Likewise.
This commit is contained in:
@ -1277,6 +1277,14 @@ riscv_lookup_subset (const riscv_subset_list_t *subset_list,
|
||||
{
|
||||
riscv_subset_t *s, *pre_s = NULL;
|
||||
|
||||
/* If the subset is added in order, then just add it at the tail. */
|
||||
if (subset_list->tail != NULL
|
||||
&& riscv_compare_subsets (subset_list->tail->name, subset) < 0)
|
||||
{
|
||||
*current = subset_list->tail;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (s = subset_list->head;
|
||||
s != NULL;
|
||||
pre_s = s, s = s->next)
|
||||
@ -1291,40 +1299,18 @@ riscv_lookup_subset (const riscv_subset_list_t *subset_list,
|
||||
break;
|
||||
}
|
||||
*current = pre_s;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add extension from ISA string to the last of the subset list. */
|
||||
/* Add the extension to the subset list. Search the
|
||||
list first, and then find the right place to add. */
|
||||
|
||||
void
|
||||
riscv_add_subset (riscv_subset_list_t *subset_list,
|
||||
const char *subset,
|
||||
int major,
|
||||
int minor)
|
||||
{
|
||||
riscv_subset_t *s = xmalloc (sizeof *s);
|
||||
|
||||
if (subset_list->head == NULL)
|
||||
subset_list->head = s;
|
||||
|
||||
s->name = xstrdup (subset);
|
||||
s->major_version = major;
|
||||
s->minor_version = minor;
|
||||
s->next = NULL;
|
||||
|
||||
if (subset_list->tail != NULL)
|
||||
subset_list->tail->next = s;
|
||||
subset_list->tail = s;
|
||||
}
|
||||
|
||||
/* Add the implicit extension to the subset list. Search the
|
||||
list first, and then find the right place to add. */
|
||||
|
||||
static void
|
||||
riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
|
||||
const char *subset,
|
||||
int major,
|
||||
int minor)
|
||||
{
|
||||
riscv_subset_t *current, *new;
|
||||
|
||||
@ -1347,14 +1333,12 @@ riscv_add_implicit_subset (riscv_subset_list_t *subset_list,
|
||||
new->next = subset_list->head;
|
||||
subset_list->head = new;
|
||||
}
|
||||
|
||||
if (new->next == NULL)
|
||||
subset_list->tail = new;
|
||||
}
|
||||
|
||||
/* We have to add all extensions from ISA string first, and then start to
|
||||
add their implicit extensions. The extensions from ISA string must be
|
||||
set in order, so we can add them to the last of the subset list
|
||||
directly, without searching.
|
||||
|
||||
Find the default versions for the extension before adding them to
|
||||
/* Find the default versions for the extension before adding them to
|
||||
the subset list, if their versions are RISCV_UNKNOWN_VERSION.
|
||||
Afterwards, report errors if we can not find their default versions. */
|
||||
|
||||
@ -1389,12 +1373,8 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implicit)
|
||||
riscv_add_subset (rps->subset_list, subset,
|
||||
major_version, minor_version);
|
||||
else
|
||||
riscv_add_implicit_subset (rps->subset_list, subset,
|
||||
major_version, minor_version);
|
||||
riscv_add_subset (rps->subset_list, subset,
|
||||
major_version, minor_version);
|
||||
}
|
||||
|
||||
/* Release subset list. */
|
||||
@ -1420,7 +1400,7 @@ riscv_release_subset_list (riscv_subset_list_t *subset_list)
|
||||
|
||||
Arguments:
|
||||
`rps`: Hooks and status for parsing extensions.
|
||||
`march`: Full ISA string.
|
||||
`arch`: Full ISA string.
|
||||
`p`: Curent parsing position.
|
||||
`major_version`: Parsed major version.
|
||||
`minor_version`: Parsed minor version.
|
||||
@ -1428,7 +1408,7 @@ riscv_release_subset_list (riscv_subset_list_t *subset_list)
|
||||
|
||||
static const char *
|
||||
riscv_parsing_subset_version (riscv_parse_subset_t *rps,
|
||||
const char *march,
|
||||
const char *arch,
|
||||
const char *p,
|
||||
int *major_version,
|
||||
int *minor_version,
|
||||
@ -1458,8 +1438,8 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
|
||||
else
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: expect number after `%dp'"),
|
||||
march, version);
|
||||
(_("%s: expect number after `%dp'"),
|
||||
arch, version);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -1505,12 +1485,12 @@ riscv_supported_std_ext (void)
|
||||
|
||||
Arguments:
|
||||
`rps`: Hooks and status for parsing extensions.
|
||||
`march`: Full ISA string.
|
||||
`arch`: Full ISA string.
|
||||
`p`: Curent parsing position. */
|
||||
|
||||
static const char *
|
||||
riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
const char *march,
|
||||
const char *arch,
|
||||
const char *p)
|
||||
{
|
||||
const char *all_std_exts = riscv_supported_std_ext ();
|
||||
@ -1523,7 +1503,7 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
switch (*p)
|
||||
{
|
||||
case 'i':
|
||||
p = riscv_parsing_subset_version (rps, march, ++p,
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, "i",
|
||||
@ -1532,23 +1512,16 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
p = riscv_parsing_subset_version (rps, march, ++p,
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, "e",
|
||||
major_version,
|
||||
minor_version, false);
|
||||
if (*rps->xlen > 32)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: rv%de is not a valid base ISA"),
|
||||
march, *rps->xlen);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
p = riscv_parsing_subset_version (rps, march, ++p,
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
/* Expand g to imafd. */
|
||||
@ -1570,8 +1543,8 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
|
||||
default:
|
||||
rps->error_handler
|
||||
(_("-march=%s: first ISA extension must be `e', `i' or `g'"),
|
||||
march);
|
||||
(_("%s: first ISA extension must be `e', `i' or `g'"),
|
||||
arch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1597,18 +1570,18 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
{
|
||||
if (riscv_ext_order[(std_ext - 'a')] == 0)
|
||||
rps->error_handler
|
||||
(_("-march=%s: unknown standard and prefixed ISA "
|
||||
"extension `%s'"), march, p);
|
||||
(_("%s: unknown standard ISA extension `%c'"),
|
||||
arch, std_ext);
|
||||
else
|
||||
rps->error_handler
|
||||
(_("-march=%s: standard ISA extension `%c' is not "
|
||||
"in canonical order"), march, std_ext);
|
||||
(_("%s: standard ISA extension `%c' is not "
|
||||
"in canonical order"), arch, std_ext);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std_exts++;
|
||||
subset[0] = std_ext;
|
||||
p = riscv_parsing_subset_version (rps, march, ++p,
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, subset,
|
||||
@ -1626,12 +1599,12 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
||||
|
||||
Arguments:
|
||||
`rps`: Hooks and status for parsing extensions.
|
||||
`march`: Full ISA string.
|
||||
`arch`: Full ISA string.
|
||||
`p`: Curent parsing position. */
|
||||
|
||||
static const char *
|
||||
riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
const char *march,
|
||||
const char *arch,
|
||||
const char *p)
|
||||
{
|
||||
int major_version;
|
||||
@ -1651,8 +1624,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
if (class == RV_ISA_CLASS_UNKNOWN)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: unknown prefix class for the ISA extension `%s'"),
|
||||
march, p);
|
||||
(_("%s: unknown prefix class for the ISA extension `%s'"),
|
||||
arch, p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1664,7 +1637,7 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
;
|
||||
|
||||
end_of_version =
|
||||
riscv_parsing_subset_version (rps, march, q,
|
||||
riscv_parsing_subset_version (rps, arch, q,
|
||||
&major_version,
|
||||
&minor_version, false);
|
||||
*q = '\0';
|
||||
@ -1685,8 +1658,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
&& !riscv_valid_prefixed_ext (subset))
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: unknown prefixed ISA extension `%s'"),
|
||||
march, subset);
|
||||
(_("%s: unknown prefixed ISA extension `%s'"),
|
||||
arch, subset);
|
||||
free (subset);
|
||||
return NULL;
|
||||
}
|
||||
@ -1696,8 +1669,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
if (!strcasecmp (last_name, subset))
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: duplicate prefixed ISA extension `%s'"),
|
||||
march, subset);
|
||||
(_("%s: duplicate prefixed ISA extension `%s'"),
|
||||
arch, subset);
|
||||
free (subset);
|
||||
return NULL;
|
||||
}
|
||||
@ -1706,9 +1679,9 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
if (riscv_compare_subsets (last_name, subset) > 0)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: prefixed ISA extension `%s' is not in expected "
|
||||
(_("%s: prefixed ISA extension `%s' is not in expected "
|
||||
"order. It must come before `%s'"),
|
||||
march, subset, last_name);
|
||||
arch, subset, last_name);
|
||||
free (subset);
|
||||
return NULL;
|
||||
}
|
||||
@ -1722,8 +1695,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||
if (*p != '\0' && *p != '_')
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: prefixed ISA extension must separate with _"),
|
||||
march);
|
||||
(_("%s: prefixed ISA extension must separate with _"),
|
||||
arch);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -1748,6 +1721,39 @@ riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check extensions conflicts. */
|
||||
|
||||
static bool
|
||||
riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
|
||||
{
|
||||
riscv_subset_t *subset = NULL;
|
||||
int xlen = *rps->xlen;
|
||||
bool no_conflict = true;
|
||||
|
||||
if (riscv_lookup_subset (rps->subset_list, "e", &subset)
|
||||
&& xlen > 32)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("rv%d does not support the `e' extension"), xlen);
|
||||
no_conflict = false;
|
||||
}
|
||||
if (riscv_lookup_subset (rps->subset_list, "q", &subset)
|
||||
&& xlen < 64)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("rv%d does not support the `q' extension"), xlen);
|
||||
no_conflict = false;
|
||||
}
|
||||
if (riscv_lookup_subset (rps->subset_list, "e", &subset)
|
||||
&& riscv_lookup_subset (rps->subset_list, "f", &subset))
|
||||
{
|
||||
rps->error_handler
|
||||
(_("rv32e does not support the `f' extension"));
|
||||
no_conflict = false;
|
||||
}
|
||||
return no_conflict;
|
||||
}
|
||||
|
||||
/* Function for parsing ISA string.
|
||||
|
||||
Return Value:
|
||||
@ -1761,16 +1767,14 @@ bool
|
||||
riscv_parse_subset (riscv_parse_subset_t *rps,
|
||||
const char *arch)
|
||||
{
|
||||
riscv_subset_t *subset = NULL;
|
||||
const char *p;
|
||||
bool no_conflict = true;
|
||||
|
||||
for (p = arch; *p != '\0'; p++)
|
||||
{
|
||||
if (ISUPPER (*p))
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: ISA string cannot contain uppercase letters"),
|
||||
(_("%s: ISA string cannot contain uppercase letters"),
|
||||
arch);
|
||||
return false;
|
||||
}
|
||||
@ -1796,7 +1800,7 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
||||
not issue this error when the ISA string is empty. */
|
||||
if (strlen (arch))
|
||||
rps->error_handler (
|
||||
_("-march=%s: ISA string must begin with rv32 or rv64"),
|
||||
_("%s: ISA string must begin with rv32 or rv64"),
|
||||
arch);
|
||||
return false;
|
||||
}
|
||||
@ -1825,23 +1829,7 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
||||
riscv_parse_add_implicit_subsets (rps);
|
||||
|
||||
/* Check the conflicts. */
|
||||
if (riscv_lookup_subset (rps->subset_list, "e", &subset)
|
||||
&& riscv_lookup_subset (rps->subset_list, "f", &subset))
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: rv32e does not support the `f' extension"),
|
||||
arch);
|
||||
no_conflict = false;
|
||||
}
|
||||
if (riscv_lookup_subset (rps->subset_list, "q", &subset)
|
||||
&& *rps->xlen < 64)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("-march=%s: rv32 does not support the `q' extension"),
|
||||
arch);
|
||||
no_conflict = false;
|
||||
}
|
||||
return no_conflict;
|
||||
return riscv_parse_check_conflicts (rps);
|
||||
}
|
||||
|
||||
/* Return the number of digits for the input. */
|
||||
|
@ -1,2 +1,2 @@
|
||||
.*Assembler messages:
|
||||
.*Error: .*rv64e is not a valid base ISA
|
||||
.*Error: rv64 does not support the `e' extension
|
||||
|
@ -1,2 +1,2 @@
|
||||
.*Assembler messages:
|
||||
.*Error: .*unknown standard and prefixed ISA extension `y'
|
||||
.*Error: .*unknown standard ISA extension `y'
|
||||
|
Reference in New Issue
Block a user