RISC-V: Handle implied extension in canonical ordering.
- ISA spec has specify the order between multi-letter extensions, implied extension also need to follow store in canonical ordering, so most easy way is we keep that in-order during insertion. gcc/ChangeLog: * common/config/riscv/riscv-common.c (single_letter_subset_rank): New. (multi_letter_subset_rank): Ditto. (subset_cmp): Ditto. (riscv_subset_list::add): Insert subext in canonical ordering. (riscv_subset_list::parse_std_ext): Move handle_implied_ext to ... (riscv_subset_list::parse): ... here.
This commit is contained in:
parent
d87ee7f1c9
commit
6a5bb4705f
|
@ -145,6 +145,129 @@ riscv_subset_list::~riscv_subset_list ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the rank for single-letter subsets, lower value meaning higher
|
||||||
|
priority. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
single_letter_subset_rank (char ext)
|
||||||
|
{
|
||||||
|
int rank;
|
||||||
|
|
||||||
|
switch (ext)
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
return 0;
|
||||||
|
case 'e':
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *all_ext = riscv_supported_std_ext ();
|
||||||
|
const char *ext_pos = strchr (all_ext, ext);
|
||||||
|
if (ext_pos == NULL)
|
||||||
|
/* If got an unknown extension letter, then give it an alphabetical
|
||||||
|
order, but after all known standard extension. */
|
||||||
|
rank = strlen (all_ext) + ext - 'a';
|
||||||
|
else
|
||||||
|
rank = (int)(ext_pos - all_ext) + 2 /* e and i has higher rank. */;
|
||||||
|
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the rank for multi-letter subsets, lower value meaning higher
|
||||||
|
priority. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
multi_letter_subset_rank (const std::string &subset)
|
||||||
|
{
|
||||||
|
gcc_assert (subset.length () >= 2);
|
||||||
|
int high_order = -1;
|
||||||
|
int low_order = 0;
|
||||||
|
/* The order between multi-char extensions: s -> h -> z -> x. */
|
||||||
|
char multiletter_class = subset[0];
|
||||||
|
switch (multiletter_class)
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
high_order = 0;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
high_order = 1;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
gcc_assert (subset.length () > 2);
|
||||||
|
high_order = 2;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
high_order = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gcc_unreachable ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiletter_class == 'z')
|
||||||
|
/* Order for z extension on spec: If multiple "Z" extensions are named, they
|
||||||
|
should be ordered first by category, then alphabetically within a
|
||||||
|
category - for example, "Zicsr_Zifencei_Zam". */
|
||||||
|
low_order = single_letter_subset_rank (subset[1]);
|
||||||
|
else
|
||||||
|
low_order = 0;
|
||||||
|
|
||||||
|
return (high_order << 8) + low_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subset compare
|
||||||
|
|
||||||
|
Returns an integral value indicating the relationship between the subsets:
|
||||||
|
Return value indicates
|
||||||
|
-1 B has higher order than A.
|
||||||
|
0 A and B are same subset.
|
||||||
|
1 A has higher order than B.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
subset_cmp (const std::string &a, const std::string &b)
|
||||||
|
{
|
||||||
|
if (a == b)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t a_len = a.length ();
|
||||||
|
size_t b_len = b.length ();
|
||||||
|
|
||||||
|
/* Single-letter extension always get higher order than
|
||||||
|
multi-letter extension. */
|
||||||
|
if (a_len == 1 && b_len != 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (a_len != 1 && b_len == 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (a_len == 1 && b_len == 1)
|
||||||
|
{
|
||||||
|
int rank_a = single_letter_subset_rank (a[0]);
|
||||||
|
int rank_b = single_letter_subset_rank (b[0]);
|
||||||
|
|
||||||
|
if (rank_a < rank_b)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int rank_a = multi_letter_subset_rank(a);
|
||||||
|
int rank_b = multi_letter_subset_rank(b);
|
||||||
|
|
||||||
|
/* Using alphabetical/lexicographical order if they have same rank. */
|
||||||
|
if (rank_a == rank_b)
|
||||||
|
/* The return value of strcmp has opposite meaning. */
|
||||||
|
return -strcmp (a.c_str (), b.c_str ());
|
||||||
|
else
|
||||||
|
return (rank_a < rank_b) ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add new subset to list. */
|
/* Add new subset to list. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -152,6 +275,7 @@ riscv_subset_list::add (const char *subset, int major_version,
|
||||||
int minor_version, bool explicit_version_p)
|
int minor_version, bool explicit_version_p)
|
||||||
{
|
{
|
||||||
riscv_subset_t *s = new riscv_subset_t ();
|
riscv_subset_t *s = new riscv_subset_t ();
|
||||||
|
riscv_subset_t *itr;
|
||||||
|
|
||||||
if (m_head == NULL)
|
if (m_head == NULL)
|
||||||
m_head = s;
|
m_head = s;
|
||||||
|
@ -162,9 +286,45 @@ riscv_subset_list::add (const char *subset, int major_version,
|
||||||
s->explicit_version_p = explicit_version_p;
|
s->explicit_version_p = explicit_version_p;
|
||||||
s->next = NULL;
|
s->next = NULL;
|
||||||
|
|
||||||
if (m_tail != NULL)
|
if (m_tail == NULL)
|
||||||
m_tail->next = s;
|
{
|
||||||
|
m_tail = s;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* e, i or g should be first subext, never come here. */
|
||||||
|
gcc_assert (subset[0] != 'e'
|
||||||
|
&& subset[0] != 'i'
|
||||||
|
&& subset[0] != 'g');
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
{
|
||||||
|
gcc_assert (m_head->next == NULL);
|
||||||
|
m_head->next = s;
|
||||||
|
m_tail = s;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_assert (m_head->next != NULL);
|
||||||
|
|
||||||
|
/* Subset list must in canonical order, but implied subset won't
|
||||||
|
add in canonical order. */
|
||||||
|
for (itr = m_head; itr->next != NULL; itr = itr->next)
|
||||||
|
{
|
||||||
|
riscv_subset_t *next = itr->next;
|
||||||
|
int cmp = subset_cmp (s->name, next->name);
|
||||||
|
gcc_assert (cmp != 0);
|
||||||
|
|
||||||
|
if (cmp > 0)
|
||||||
|
{
|
||||||
|
s->next = next;
|
||||||
|
itr->next = s;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert at tail of the list. */
|
||||||
|
itr->next = s;
|
||||||
m_tail = s;
|
m_tail = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,9 +601,6 @@ riscv_subset_list::parse_std_ext (const char *p)
|
||||||
|
|
||||||
subset[0] = std_ext;
|
subset[0] = std_ext;
|
||||||
|
|
||||||
handle_implied_ext (subset, major_version,
|
|
||||||
minor_version, explicit_version_p);
|
|
||||||
|
|
||||||
add (subset, major_version, minor_version, explicit_version_p);
|
add (subset, major_version, minor_version, explicit_version_p);
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
@ -553,6 +710,7 @@ riscv_subset_list *
|
||||||
riscv_subset_list::parse (const char *arch, location_t loc)
|
riscv_subset_list::parse (const char *arch, location_t loc)
|
||||||
{
|
{
|
||||||
riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
|
riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
|
||||||
|
riscv_subset_t *itr;
|
||||||
const char *p = arch;
|
const char *p = arch;
|
||||||
if (strncmp (p, "rv32", 4) == 0)
|
if (strncmp (p, "rv32", 4) == 0)
|
||||||
{
|
{
|
||||||
|
@ -608,6 +766,15 @@ riscv_subset_list::parse (const char *arch, location_t loc)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
|
||||||
|
{
|
||||||
|
subset_list->handle_implied_ext (
|
||||||
|
itr->name.c_str (),
|
||||||
|
itr->major_version,
|
||||||
|
itr->minor_version,
|
||||||
|
itr->explicit_version_p);
|
||||||
|
}
|
||||||
|
|
||||||
return subset_list;
|
return subset_list;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
Loading…
Reference in New Issue