mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 04:00:07 +08:00
RISC-V: Support to parse the multi-letter prefix in the architecture string.
The original discussion is as follows, https://github.com/riscv/riscv-isa-manual/issues/637 I never considered the prefixes may have multiple letters, like zxm. But the ISA spec has been updated for a long time that I haven't noticed. This patch rewrites the part of architecture parser to support parsing the multi-letter prefixes. Besides, I also improve the parser to report errors in details. One of the most obvious improvement is - Do not parse the prefixed extensions according to the orders in the parse_config. If we do so, then we used to get "unexpected ISA string at end" errors, but the message is a little bit hard to know what is happening. I Remove the confused message, and let riscv_parse_prefixed_ext to report the details. bfd/ * elfxx-riscv.c (riscv_std_z_ext_strtab): Moved forward. (riscv_std_s_ext_strtab): Likewise. (riscv_std_h_ext_strtab): Likewise. (riscv_std_zxm_ext_strtab): Added for the zxm prefix. (enum riscv_prefix_ext_class): Moved forward and renamed from riscv_isa_ext_class. Reorder them according to the parsing order, since the enum values are used to check the orders in the riscv_compare_subsets. (struct riscv_parse_prefix_config): Moved forward and renamed from riscv_parse_config_t. Also removed the ext_valid_p field, the related functions are replaced by riscv_valid_prefixed_ext. (parse_config): Moved forward and updated. The more letters of the prefix string, the more forward it must be defined. Otherwise, we will get the wrong mapping when using strncmp in riscv_get_prefix_class. (riscv_get_prefix_class): Moved forward. Support to parse the multi-letter prefix, like zxm. (riscv_known_prefixed_ext): New function, check if the prefixed extension is supported according to the right riscv_std_*_ext_strtab. (riscv_valid_prefixed_ext): New function, used to replace the riscv_ext_*_valid_p functions. (riscv_init_ext_order): Do not set the values for prefix keywords since they may have multiple letters for now. (riscv_compare_subsets): Set the order values of prefix keywords to negative numbers according to the riscv_prefix_ext_class. (riscv_parse_std_ext): Call riscv_get_prefix_class to see if we have parsed the prefixed extensions. (riscv_parse_prefixed_ext): Updated and removed the parameter config. Report error when the prefix is unknown. (riscv_parse_subset): Do not parse the prefixed extensions according to the orders in the parse_config. Remove the confused message and let riscv_parse_prefixed_ext to report the details. * elfxx-riscv.h (enum riscv_isa_ext_class): Moved to elfxx-riscv.c. (riscv_get_prefix_class): Removed to static. gas/ * testsuite/gas/riscv/march-fail-order-x-std.d: Renamed from march-fail-porder-x-std.d. * testsuite/gas/riscv/march-fail-order-z-std.d: Renamed from march-fail-porder-z-std.d. * testsuite/gas/riscv/march-fail-order-x-z.d: Renamed from march-fail-porder-x-z.d. * testsuite/gas/riscv/march-fail-order-zx-std.l: Added to replace march-fail-porder.l. * testsuite/gas/riscv/march-fail-order-x-z.l: Likewise. * testsuite/gas/riscv/march-fail-order-x.l: Updated. * testsuite/gas/riscv/march-fail-order-z.l: Likewise. * testsuite/gas/riscv/march-fail-single-prefix-h.d: Renamed from march-fail-single-char-h.d. * testsuite/gas/riscv/march-fail-single-prefix-s.d: Renamed from march-fail-single-char-s.d. * testsuite/gas/riscv/march-fail-single-prefix-x.d: Renamed from march-fail-single-char-x.d. * testsuite/gas/riscv/march-fail-single-prefix-z.d: Renamed from march-fail-single-char-z.d. * testsuite/gas/riscv/march-fail-single-prefix-zmx.d: Added. * testsuite/gas/riscv/march-fail-single-prefix.l: Added to replace march-fail-single-prefix.l. * testsuite/gas/riscv/march-fail-unknown-zxm.d: Added. * testsuite/gas/riscv/march-fail-unknown-std.l: Updated. * testsuite/gas/riscv/march-fail-unknown.l: Likewise.
This commit is contained in:
@ -1,3 +1,39 @@
|
|||||||
|
2021-04-12 Nelson Chu <nelson.chu@sifive.com>
|
||||||
|
|
||||||
|
* elfxx-riscv.c (riscv_std_z_ext_strtab): Moved forward.
|
||||||
|
(riscv_std_s_ext_strtab): Likewise.
|
||||||
|
(riscv_std_h_ext_strtab): Likewise.
|
||||||
|
(riscv_std_zxm_ext_strtab): Added for the zxm prefix.
|
||||||
|
(enum riscv_prefix_ext_class): Moved forward and renamed from
|
||||||
|
riscv_isa_ext_class. Reorder them according to the parsing order,
|
||||||
|
since the enum values are used to check the orders in the
|
||||||
|
riscv_compare_subsets.
|
||||||
|
(struct riscv_parse_prefix_config): Moved forward and renamed from
|
||||||
|
riscv_parse_config_t. Also removed the ext_valid_p field, the
|
||||||
|
related functions are replaced by riscv_valid_prefixed_ext.
|
||||||
|
(parse_config): Moved forward and updated. The more letters of the
|
||||||
|
prefix string, the more forward it must be defined. Otherwise, we
|
||||||
|
will get the wrong mapping when using strncmp in riscv_get_prefix_class.
|
||||||
|
(riscv_get_prefix_class): Moved forward. Support to parse the
|
||||||
|
multi-letter prefix, like zxm.
|
||||||
|
(riscv_known_prefixed_ext): New function, check if the prefixed
|
||||||
|
extension is supported according to the right riscv_std_*_ext_strtab.
|
||||||
|
(riscv_valid_prefixed_ext): New function, used to replace the
|
||||||
|
riscv_ext_*_valid_p functions.
|
||||||
|
(riscv_init_ext_order): Do not set the values for prefix keywords
|
||||||
|
since they may have multiple letters for now.
|
||||||
|
(riscv_compare_subsets): Set the order values of prefix keywords
|
||||||
|
to negative numbers according to the riscv_prefix_ext_class.
|
||||||
|
(riscv_parse_std_ext): Call riscv_get_prefix_class to see if we
|
||||||
|
have parsed the prefixed extensions.
|
||||||
|
(riscv_parse_prefixed_ext): Updated and removed the parameter config.
|
||||||
|
Report error when the prefix is unknown.
|
||||||
|
(riscv_parse_subset): Do not parse the prefixed extensions according
|
||||||
|
to the orders in the parse_config. Remove the confused message and
|
||||||
|
let riscv_parse_prefixed_ext to report the details.
|
||||||
|
* elfxx-riscv.h (enum riscv_isa_ext_class): Moved to elfxx-riscv.c.
|
||||||
|
(riscv_get_prefix_class): Removed to static.
|
||||||
|
|
||||||
2021-04-08 Mike Frysinger <vapier@gentoo.org>
|
2021-04-08 Mike Frysinger <vapier@gentoo.org>
|
||||||
|
|
||||||
* configure.ac (ACX_BUGURL): Use https://.
|
* configure.ac (ACX_BUGURL): Use https://.
|
||||||
|
@ -1028,16 +1028,167 @@ riscv_elf_add_sub_reloc (bfd *abfd,
|
|||||||
|
|
||||||
#define RISCV_UNKNOWN_VERSION -1
|
#define RISCV_UNKNOWN_VERSION -1
|
||||||
|
|
||||||
/* Array is used to compare the orders of all extensions quickly.
|
/* Lists of prefixed class extensions that binutils should know about.
|
||||||
|
Whether or not a particular entry is in these lists will dictate if
|
||||||
|
gas/ld will accept its presence in the architecture string.
|
||||||
|
|
||||||
Zero value: Preserved keyword.
|
Please add the extensions to the lists in lower case. However, keep
|
||||||
Negative value: Prefixed keyword (s, h, x, z).
|
these subsets in alphabetical order in these tables is recommended,
|
||||||
Positive value: Standard extension. */
|
although there is no impact on the current implementation. */
|
||||||
|
|
||||||
|
static const char * const riscv_std_z_ext_strtab[] =
|
||||||
|
{
|
||||||
|
"zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const riscv_std_s_ext_strtab[] =
|
||||||
|
{
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const riscv_std_h_ext_strtab[] =
|
||||||
|
{
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const riscv_std_zxm_ext_strtab[] =
|
||||||
|
{
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ISA extension prefixed name class. Must define them in parsing order. */
|
||||||
|
enum riscv_prefix_ext_class
|
||||||
|
{
|
||||||
|
RV_ISA_CLASS_Z = 1,
|
||||||
|
RV_ISA_CLASS_S,
|
||||||
|
RV_ISA_CLASS_H,
|
||||||
|
RV_ISA_CLASS_ZXM,
|
||||||
|
RV_ISA_CLASS_X,
|
||||||
|
RV_ISA_CLASS_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Record the strings of the prefixed extensions, and their corresponding
|
||||||
|
classes. The more letters of the prefix string, the more forward it must
|
||||||
|
be defined. Otherwise, the riscv_get_prefix_class will map it to the
|
||||||
|
wrong classes. */
|
||||||
|
struct riscv_parse_prefix_config
|
||||||
|
{
|
||||||
|
/* Class of the extension. */
|
||||||
|
enum riscv_prefix_ext_class class;
|
||||||
|
|
||||||
|
/* Prefix string for error printing and internal parser usage. */
|
||||||
|
const char *prefix;
|
||||||
|
};
|
||||||
|
static const struct riscv_parse_prefix_config parse_config[] =
|
||||||
|
{
|
||||||
|
{RV_ISA_CLASS_ZXM, "zxm"},
|
||||||
|
{RV_ISA_CLASS_Z, "z"},
|
||||||
|
{RV_ISA_CLASS_S, "s"},
|
||||||
|
{RV_ISA_CLASS_H, "h"},
|
||||||
|
{RV_ISA_CLASS_X, "x"},
|
||||||
|
{RV_ISA_CLASS_UNKNOWN, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get the prefixed name class for the extensions, the class also
|
||||||
|
means the order of the prefixed extensions. */
|
||||||
|
|
||||||
|
static enum riscv_prefix_ext_class
|
||||||
|
riscv_get_prefix_class (const char *arch)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
|
||||||
|
{
|
||||||
|
if (strncmp (arch, parse_config[i].prefix,
|
||||||
|
strlen (parse_config[i].prefix)) == 0)
|
||||||
|
return parse_config[i].class;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return RV_ISA_CLASS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check KNOWN_EXTS to see if the EXT is supported. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
riscv_known_prefixed_ext (const char *ext,
|
||||||
|
const char *const *known_exts)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; known_exts[i]; ++i)
|
||||||
|
if (strcmp (ext, known_exts[i]) == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether the prefixed extension is valid or not. Return
|
||||||
|
true if valid, otehrwise return false. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
riscv_valid_prefixed_ext (const char *ext)
|
||||||
|
{
|
||||||
|
enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext);
|
||||||
|
switch (class)
|
||||||
|
{
|
||||||
|
case RV_ISA_CLASS_Z:
|
||||||
|
return riscv_known_prefixed_ext (ext, riscv_std_z_ext_strtab);
|
||||||
|
case RV_ISA_CLASS_ZXM:
|
||||||
|
return riscv_known_prefixed_ext (ext, riscv_std_zxm_ext_strtab);
|
||||||
|
case RV_ISA_CLASS_S:
|
||||||
|
return riscv_known_prefixed_ext (ext, riscv_std_s_ext_strtab);
|
||||||
|
case RV_ISA_CLASS_H:
|
||||||
|
return riscv_known_prefixed_ext (ext, riscv_std_h_ext_strtab);
|
||||||
|
case RV_ISA_CLASS_X:
|
||||||
|
/* Only the single x is invalid. */
|
||||||
|
if (strcmp (ext, "x") != 0)
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Array is used to compare the orders of standard extensions quickly. */
|
||||||
static int riscv_ext_order[26] = {0};
|
static int riscv_ext_order[26] = {0};
|
||||||
|
|
||||||
|
/* Init the riscv_ext_order array. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
riscv_init_ext_order (void)
|
||||||
|
{
|
||||||
|
static bool inited = false;
|
||||||
|
const char *std_base_exts = "eig";
|
||||||
|
const char *std_remain_exts = riscv_supported_std_ext ();
|
||||||
|
const char *ext;
|
||||||
|
int order;
|
||||||
|
|
||||||
|
if (inited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* The orders of all standard extensions are positive. */
|
||||||
|
order = 1;
|
||||||
|
|
||||||
|
/* Init the standard base extensions first. */
|
||||||
|
for (ext = std_base_exts; *ext; ext++)
|
||||||
|
riscv_ext_order[(*ext - 'a')] = order++;
|
||||||
|
|
||||||
|
/* Init the standard remaining extensions. */
|
||||||
|
for (ext = std_remain_exts; *ext; ext++)
|
||||||
|
riscv_ext_order[(*ext - 'a')] = order++;
|
||||||
|
|
||||||
|
/* Some of the prefixed keyword are not single letter, so we set
|
||||||
|
their prefixed orders in the riscv_compare_subsets directly,
|
||||||
|
not through the riscv_ext_order. */
|
||||||
|
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Similar to the strcmp. It returns an integer less than, equal to,
|
/* Similar to the strcmp. It returns an integer less than, equal to,
|
||||||
or greater than zero if `subset2` is found, respectively, to be less
|
or greater than zero if `subset2` is found, respectively, to be less
|
||||||
than, to match, or be greater than `subset1`. */
|
than, to match, or be greater than `subset1`.
|
||||||
|
|
||||||
|
The order values,
|
||||||
|
Zero: Preserved keywords.
|
||||||
|
Positive number: Standard extensions.
|
||||||
|
Negative number: Prefixed keywords. */
|
||||||
|
|
||||||
int
|
int
|
||||||
riscv_compare_subsets (const char *subset1, const char *subset2)
|
riscv_compare_subsets (const char *subset1, const char *subset2)
|
||||||
@ -1049,10 +1200,19 @@ riscv_compare_subsets (const char *subset1, const char *subset2)
|
|||||||
if (order1 > 0 && order2 > 0)
|
if (order1 > 0 && order2 > 0)
|
||||||
return order1 - order2;
|
return order1 - order2;
|
||||||
|
|
||||||
if (order1 == order2 && order1 < 0)
|
/* Set the prefixed orders to negative numbers. */
|
||||||
|
enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
|
||||||
|
enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
|
||||||
|
|
||||||
|
if (class1 != RV_ISA_CLASS_UNKNOWN)
|
||||||
|
order1 = - (int) class1;
|
||||||
|
if (class2 != RV_ISA_CLASS_UNKNOWN)
|
||||||
|
order2 = - (int) class2;
|
||||||
|
|
||||||
|
if (order1 == order2)
|
||||||
{
|
{
|
||||||
/* Compare the standard addition z extensions. */
|
/* Compare the standard addition z extensions. */
|
||||||
if (*subset1 == 'z')
|
if (class1 == RV_ISA_CLASS_Z)
|
||||||
{
|
{
|
||||||
order1 = riscv_ext_order[(*++subset1 - 'a')];
|
order1 = riscv_ext_order[(*++subset1 - 'a')];
|
||||||
order2 = riscv_ext_order[(*++subset2 - 'a')];
|
order2 = riscv_ext_order[(*++subset2 - 'a')];
|
||||||
@ -1403,7 +1563,9 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
|||||||
|
|
||||||
while (p != NULL && *p != '\0')
|
while (p != NULL && *p != '\0')
|
||||||
{
|
{
|
||||||
if (*p == 'x' || *p == 's' || *p == 'h' || *p == 'z')
|
/* Stop when we parsed the known prefix class. */
|
||||||
|
enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
|
||||||
|
if (class != RV_ISA_CLASS_UNKNOWN)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (*p == '_')
|
if (*p == '_')
|
||||||
@ -1419,10 +1581,10 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
|||||||
|
|
||||||
if (std_ext != *std_exts)
|
if (std_ext != *std_exts)
|
||||||
{
|
{
|
||||||
if (strchr (all_std_exts, std_ext) == NULL)
|
if (riscv_ext_order[(std_ext - 'a')] == 0)
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: unknown standard ISA extension `%c'"),
|
(_("-march=%s: unknown standard and prefixed ISA "
|
||||||
march, std_ext);
|
"extension `%s'"), march, p);
|
||||||
else
|
else
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: standard ISA extension `%c' is not "
|
(_("-march=%s: standard ISA extension `%c' is not "
|
||||||
@ -1443,38 +1605,6 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Classify ARCH into one of riscv_isa_ext_class_t. */
|
|
||||||
|
|
||||||
riscv_isa_ext_class_t
|
|
||||||
riscv_get_prefix_class (const char *arch)
|
|
||||||
{
|
|
||||||
switch (*arch)
|
|
||||||
{
|
|
||||||
case 's': return RV_ISA_CLASS_S;
|
|
||||||
case 'h': return RV_ISA_CLASS_H;
|
|
||||||
case 'x': return RV_ISA_CLASS_X;
|
|
||||||
case 'z': return RV_ISA_CLASS_Z;
|
|
||||||
default: return RV_ISA_CLASS_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Structure describing parameters to use when parsing a particular
|
|
||||||
riscv_isa_ext_class_t. One of these should be provided for each
|
|
||||||
possible class, except RV_ISA_CLASS_UNKNOWN. */
|
|
||||||
typedef struct riscv_parse_config
|
|
||||||
{
|
|
||||||
/* Class of the extension. */
|
|
||||||
riscv_isa_ext_class_t class;
|
|
||||||
|
|
||||||
/* Prefix string for error printing and internal parser usage. */
|
|
||||||
const char *prefix;
|
|
||||||
|
|
||||||
/* Predicate which is used for checking whether this is a "known"
|
|
||||||
extension. For 'x', it always returns true since they are by
|
|
||||||
definition non-standard and cannot be known. */
|
|
||||||
bool (*ext_valid_p) (const char *);
|
|
||||||
} riscv_parse_config_t;
|
|
||||||
|
|
||||||
/* Parsing function for prefixed extensions.
|
/* Parsing function for prefixed extensions.
|
||||||
|
|
||||||
Return Value:
|
Return Value:
|
||||||
@ -1490,13 +1620,12 @@ typedef struct riscv_parse_config
|
|||||||
static const char *
|
static const char *
|
||||||
riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
||||||
const char *march,
|
const char *march,
|
||||||
const char *p,
|
const char *p)
|
||||||
const riscv_parse_config_t *config)
|
|
||||||
{
|
{
|
||||||
int major_version;
|
int major_version;
|
||||||
int minor_version;
|
int minor_version;
|
||||||
const char *last_name;
|
const char *last_name;
|
||||||
riscv_isa_ext_class_t class;
|
enum riscv_prefix_ext_class class;
|
||||||
|
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
@ -1506,12 +1635,14 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assert that the current extension specifier matches our parsing
|
|
||||||
class. */
|
|
||||||
class = riscv_get_prefix_class (p);
|
class = riscv_get_prefix_class (p);
|
||||||
if (class != config->class
|
if (class == RV_ISA_CLASS_UNKNOWN)
|
||||||
|| class == RV_ISA_CLASS_UNKNOWN)
|
{
|
||||||
break;
|
rps->error_handler
|
||||||
|
(_("-march=%s: unknown prefix class for the ISA extension `%s'"),
|
||||||
|
march, p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *subset = xstrdup (p);
|
char *subset = xstrdup (p);
|
||||||
char *q = subset;
|
char *q = subset;
|
||||||
@ -1532,18 +1663,18 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the prefix extension is known.
|
/* Check if the prefix extension is known.
|
||||||
For 'x', anything goes but it cannot simply be 'x'.
|
For 'x', anything goes but it cannot simply be 'x'.
|
||||||
For 's', it must be known from a list and cannot simply be 's'.
|
For 's', it must be known from a list and cannot simply be 's'.
|
||||||
For 'h', it must be known from a list and cannot simply be 'h'.
|
For 'h', it must be known from a list and cannot simply be 'h'.
|
||||||
For 'z', it must be known from a list and cannot simply be 'z'. */
|
For 'z', it must be known from a list and cannot simply be 'z'. */
|
||||||
|
|
||||||
/* Check that the extension name is well-formed. */
|
/* Check that the extension name is well-formed. */
|
||||||
if (!config->ext_valid_p (subset))
|
if (!riscv_valid_prefixed_ext (subset))
|
||||||
{
|
{
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: unknown %s ISA extension `%s'"),
|
(_("-march=%s: unknown prefixed ISA extension `%s'"),
|
||||||
march, config->prefix, subset);
|
march, subset);
|
||||||
free (subset);
|
free (subset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1553,19 +1684,19 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
|||||||
if (!strcasecmp (last_name, subset))
|
if (!strcasecmp (last_name, subset))
|
||||||
{
|
{
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: duplicate %s ISA extension `%s'"),
|
(_("-march=%s: duplicate prefixed ISA extension `%s'"),
|
||||||
march, config->prefix, subset);
|
march, subset);
|
||||||
free (subset);
|
free (subset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the extension is in alphabetical order. */
|
/* Check that the extension is in expected order. */
|
||||||
if (riscv_compare_subsets (last_name, subset) > 0)
|
if (riscv_compare_subsets (last_name, subset) > 0)
|
||||||
{
|
{
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: %s ISA extension `%s' is not in alphabetical "
|
(_("-march=%s: prefixed ISA extension `%s' is not in expected "
|
||||||
"order. It must come before `%s'"),
|
"order. It must come before `%s'"),
|
||||||
march, config->prefix, subset, last_name);
|
march, subset, last_name);
|
||||||
free (subset);
|
free (subset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1579,8 +1710,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
|||||||
if (*p != '\0' && *p != '_')
|
if (*p != '\0' && *p != '_')
|
||||||
{
|
{
|
||||||
rps->error_handler
|
rps->error_handler
|
||||||
(_("-march=%s: %s ISA extension must separate with _"),
|
(_("-march=%s: prefixed ISA extension must separate with _"),
|
||||||
march, config->prefix);
|
march);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1588,132 +1719,6 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lists of prefixed class extensions that binutils should know about.
|
|
||||||
Whether or not a particular entry is in these lists will dictate if
|
|
||||||
gas/ld will accept its presence in the architecture string.
|
|
||||||
|
|
||||||
Please add the extensions to the lists in lower case. However, keep
|
|
||||||
these subsets in alphabetical order in these tables is recommended,
|
|
||||||
although there is no impact on the current implementation. */
|
|
||||||
|
|
||||||
static const char * const riscv_std_z_ext_strtab[] =
|
|
||||||
{
|
|
||||||
"zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const riscv_std_s_ext_strtab[] =
|
|
||||||
{
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char * const riscv_std_h_ext_strtab[] =
|
|
||||||
{
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* For the extension `ext`, search through the list of known extensions
|
|
||||||
`known_exts` for a match, and return TRUE if found. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
riscv_multi_letter_ext_valid_p (const char *ext,
|
|
||||||
const char *const *known_exts)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; known_exts[i]; ++i)
|
|
||||||
if (!strcmp (ext, known_exts[i]))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Predicator function for x-prefixed extensions.
|
|
||||||
Anything goes, except the literal 'x'. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
riscv_ext_x_valid_p (const char *arg)
|
|
||||||
{
|
|
||||||
if (!strcasecmp (arg, "x"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Predicator functions for z-prefixed extensions.
|
|
||||||
Only known z-extensions are permitted. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
riscv_ext_z_valid_p (const char *arg)
|
|
||||||
{
|
|
||||||
return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Predicator function for 's' prefixed extensions.
|
|
||||||
Only known s-extensions are permitted. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
riscv_ext_s_valid_p (const char *arg)
|
|
||||||
{
|
|
||||||
return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Predicator function for 'h' prefixed extensions.
|
|
||||||
Only known h-extensions are permitted. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
riscv_ext_h_valid_p (const char *arg)
|
|
||||||
{
|
|
||||||
return riscv_multi_letter_ext_valid_p (arg, riscv_std_h_ext_strtab);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parsing order of the prefixed extensions that is specified by
|
|
||||||
the ISA spec. */
|
|
||||||
static const riscv_parse_config_t parse_config[] =
|
|
||||||
{
|
|
||||||
{RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
|
|
||||||
{RV_ISA_CLASS_H, "h", riscv_ext_h_valid_p},
|
|
||||||
{RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
|
|
||||||
{RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
|
|
||||||
{RV_ISA_CLASS_UNKNOWN, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Init the riscv_ext_order array. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
riscv_init_ext_order (void)
|
|
||||||
{
|
|
||||||
static bool inited = false;
|
|
||||||
const char *std_base_exts = "eig";
|
|
||||||
const char *std_remain_exts = riscv_supported_std_ext ();
|
|
||||||
const char *ext;
|
|
||||||
unsigned int i;
|
|
||||||
int order;
|
|
||||||
|
|
||||||
if (inited)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* The orders of all standard extensions are positive. */
|
|
||||||
order = 1;
|
|
||||||
|
|
||||||
/* Init the standard base extensions first. */
|
|
||||||
for (ext = std_base_exts; *ext; ext++)
|
|
||||||
riscv_ext_order[(*ext - 'a')] = order++;
|
|
||||||
|
|
||||||
/* Init the standard remaining extensions. */
|
|
||||||
for (ext = std_remain_exts; *ext; ext++)
|
|
||||||
riscv_ext_order[(*ext - 'a')] = order++;
|
|
||||||
|
|
||||||
/* Init the order for prefixed keywords. The orders are negative. */
|
|
||||||
order = -1;
|
|
||||||
for (i = 0; parse_config[i].class != RV_ISA_CLASS_UNKNOWN; i++)
|
|
||||||
{
|
|
||||||
ext = parse_config[i].prefix;
|
|
||||||
riscv_ext_order[(*ext - 'a')] = order--;
|
|
||||||
}
|
|
||||||
|
|
||||||
inited = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the implicit extensions. */
|
/* Add the implicit extensions. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1787,7 +1792,6 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
|||||||
{
|
{
|
||||||
riscv_subset_t *subset = NULL;
|
riscv_subset_t *subset = NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
size_t i;
|
|
||||||
bool no_conflict = true;
|
bool no_conflict = true;
|
||||||
|
|
||||||
for (p = arch; *p != '\0'; p++)
|
for (p = arch; *p != '\0'; p++)
|
||||||
@ -1837,21 +1841,14 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Parse the different classes of extensions in the specified order. */
|
/* Parse the different classes of extensions in the specified order. */
|
||||||
for (i = 0; i < ARRAY_SIZE (parse_config); ++i)
|
while (*p != '\0')
|
||||||
{
|
{
|
||||||
p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
|
p = riscv_parse_prefixed_ext (rps, arch, p);
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p != '\0')
|
|
||||||
{
|
|
||||||
rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
|
|
||||||
arch, p);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally add implicit extensions according to the current
|
/* Finally add implicit extensions according to the current
|
||||||
extensions. */
|
extensions. */
|
||||||
riscv_parse_add_implicit_subsets (rps);
|
riscv_parse_add_implicit_subsets (rps);
|
||||||
|
@ -90,19 +90,6 @@ riscv_arch_str (unsigned, const riscv_subset_list_t *);
|
|||||||
extern size_t
|
extern size_t
|
||||||
riscv_estimate_digit (unsigned);
|
riscv_estimate_digit (unsigned);
|
||||||
|
|
||||||
/* ISA extension prefixed name class. */
|
|
||||||
typedef enum riscv_isa_ext_class
|
|
||||||
{
|
|
||||||
RV_ISA_CLASS_S,
|
|
||||||
RV_ISA_CLASS_H,
|
|
||||||
RV_ISA_CLASS_Z,
|
|
||||||
RV_ISA_CLASS_X,
|
|
||||||
RV_ISA_CLASS_UNKNOWN
|
|
||||||
} riscv_isa_ext_class_t;
|
|
||||||
|
|
||||||
riscv_isa_ext_class_t
|
|
||||||
riscv_get_prefix_class (const char *);
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
riscv_compare_subsets (const char *, const char *);
|
riscv_compare_subsets (const char *, const char *);
|
||||||
|
|
||||||
|
@ -1,3 +1,31 @@
|
|||||||
|
2021-04-12 Nelson Chu <nelson.chu@sifive.com>
|
||||||
|
|
||||||
|
* testsuite/gas/riscv/march-fail-order-x-std.d: Renamed from
|
||||||
|
march-fail-porder-x-std.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-z-std.d: Renamed from
|
||||||
|
march-fail-porder-z-std.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-x-z.d: Renamed from
|
||||||
|
march-fail-porder-x-z.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-zx-std.l: Added to replace
|
||||||
|
march-fail-porder.l.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-x-z.l: Likewise.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-x.l: Updated.
|
||||||
|
* testsuite/gas/riscv/march-fail-order-z.l: Likewise.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix-h.d: Renamed from
|
||||||
|
march-fail-single-char-h.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix-s.d: Renamed from
|
||||||
|
march-fail-single-char-s.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix-x.d: Renamed from
|
||||||
|
march-fail-single-char-x.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix-z.d: Renamed from
|
||||||
|
march-fail-single-char-z.d.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix-zmx.d: Added.
|
||||||
|
* testsuite/gas/riscv/march-fail-single-prefix.l: Added to replace
|
||||||
|
march-fail-single-prefix.l.
|
||||||
|
* testsuite/gas/riscv/march-fail-unknown-zxm.d: Added.
|
||||||
|
* testsuite/gas/riscv/march-fail-unknown-std.l: Updated.
|
||||||
|
* testsuite/gas/riscv/march-fail-unknown.l: Likewise.
|
||||||
|
|
||||||
2021-04-09 Tejas Belagod <tejas.belagod@arm.com>
|
2021-04-09 Tejas Belagod <tejas.belagod@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (warn_unpredictable_ldst): Clean-up diagnostic messages
|
* config/tc-aarch64.c (warn_unpredictable_ldst): Clean-up diagnostic messages
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#as: -march=rv32i_xargle2p0_mafd
|
#as: -march=rv32i_xargle2p0_mafd
|
||||||
#source: empty.s
|
#source: empty.s
|
||||||
#error_output: march-fail-porder.l
|
#error_output: march-fail-order-zx-std.l
|
@ -1,3 +1,3 @@
|
|||||||
#as: -march=rv32i_xargle2p0_zicsr2p0
|
#as: -march=rv32i_xargle2p0_zicsr2p0
|
||||||
#source: empty.s
|
#source: empty.s
|
||||||
#error_output: march-fail-porder.l
|
#error_output: march-fail-order-x-z.l
|
2
gas/testsuite/gas/riscv/march-fail-order-x-z.l
Normal file
2
gas/testsuite/gas/riscv/march-fail-order-x-z.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*Assembler messages:
|
||||||
|
.*Error: .*prefixed ISA extension `zicsr' is not in expected order. It must come before `xargle'
|
@ -1,2 +1,2 @@
|
|||||||
.*Assembler messages:
|
.*Assembler messages:
|
||||||
.*Error: .*x ISA extension `xargle' is not in alphabetical order. It must come before `xbargle'
|
.*Error: .*prefixed ISA extension `xargle' is not in expected order. It must come before `xbargle'
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#as: -march=rv32i_zicsr2p0_mafd
|
#as: -march=rv32i_zicsr2p0_mafd
|
||||||
#source: empty.s
|
#source: empty.s
|
||||||
#error_output: march-fail-porder.l
|
#error_output: march-fail-order-zx-std.l
|
@ -1,2 +1,2 @@
|
|||||||
.*Assembler messages:
|
.*Assembler messages:
|
||||||
.*Error: .*z ISA extension `zicsr' is not in alphabetical order. It must come before `zifencei'
|
.*Error: .*prefixed ISA extension `zicsr' is not in expected order. It must come before `zifencei'
|
||||||
|
2
gas/testsuite/gas/riscv/march-fail-order-zx-std.l
Normal file
2
gas/testsuite/gas/riscv/march-fail-order-zx-std.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*Assembler messages:
|
||||||
|
.*Error: .*unknown prefix class for the ISA extension `mafd'
|
@ -1,2 +0,0 @@
|
|||||||
.*Assembler messages:
|
|
||||||
.*Error: .*unexpected ISA string at end:.*
|
|
@ -1,3 +0,0 @@
|
|||||||
#as: -march=rv32ih
|
|
||||||
#source: empty.s
|
|
||||||
#error_output: march-fail-single-char.l
|
|
@ -1,3 +0,0 @@
|
|||||||
#as: -march=rv32is
|
|
||||||
#source: empty.s
|
|
||||||
#error_output: march-fail-single-char.l
|
|
@ -1,3 +0,0 @@
|
|||||||
#as: -march=rv32ix
|
|
||||||
#source: empty.s
|
|
||||||
#error_output: march-fail-single-char.l
|
|
@ -1,3 +0,0 @@
|
|||||||
#as: -march=rv32iz
|
|
||||||
#source: empty.s
|
|
||||||
#error_output: march-fail-single-char.l
|
|
@ -1,2 +0,0 @@
|
|||||||
.*Assembler messages:
|
|
||||||
.*Error: .*unknown (s|h|z|x) ISA extension `(s|h|z|x)'
|
|
3
gas/testsuite/gas/riscv/march-fail-single-prefix-h.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-single-prefix-h.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32ih
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-single-prefix.l
|
3
gas/testsuite/gas/riscv/march-fail-single-prefix-s.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-single-prefix-s.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32is
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-single-prefix.l
|
3
gas/testsuite/gas/riscv/march-fail-single-prefix-x.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-single-prefix-x.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32ix
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-single-prefix.l
|
3
gas/testsuite/gas/riscv/march-fail-single-prefix-z.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-single-prefix-z.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32iz
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-single-prefix.l
|
3
gas/testsuite/gas/riscv/march-fail-single-prefix-zxm.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-single-prefix-zxm.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32izxm
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-single-prefix.l
|
2
gas/testsuite/gas/riscv/march-fail-single-prefix.l
Normal file
2
gas/testsuite/gas/riscv/march-fail-single-prefix.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.*Assembler messages:
|
||||||
|
.*Error: .*unknown prefixed ISA extension `(s|h|z|x|zxm)'
|
@ -1,2 +1,2 @@
|
|||||||
.*Assembler messages:
|
.*Assembler messages:
|
||||||
.*Error: .*unknown standard ISA extension `[^eimafdqiglcbjtpvn]'
|
.*Error: .*unknown standard and prefixed ISA extension `y'
|
||||||
|
3
gas/testsuite/gas/riscv/march-fail-unknown-zxm.d
Normal file
3
gas/testsuite/gas/riscv/march-fail-unknown-zxm.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#as: -march=rv32izxmfoo2p0
|
||||||
|
#source: empty.s
|
||||||
|
#error_output: march-fail-unknown.l
|
@ -1,2 +1,2 @@
|
|||||||
.*Assembler messages:
|
.*Assembler messages:
|
||||||
.*Error: .*unknown (s|h|z) ISA extension `(s|h|z)foo'
|
.*Error: .*unknown prefixed ISA extension `(s|h|z|zxm)foo'
|
||||||
|
Reference in New Issue
Block a user