Commit 10b04d1e by Richard Sandiford Committed by Richard Sandiford

Report ambiguous uses of .md attributes

This patch reports an error if the .md file has an unscoped
attribute that maps to more than one possible value.

2019-07-16  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* read-md.h (md_reader::record_potential_iterator_use): Add a
	file_location parameter.
	* read-rtl.c (attribute_use::loc): New field.
	(map_attr_string): Take a file_location parameter.  Report cases
	in which attributes map to multiple distinct values.
	(apply_attribute_uses): Update call accordingly.
	(md_reader::handle_overloaded_name): Likewise.
	(md_reader::apply_iterator_to_string): Likewise.  Skip empty
	nonnull strings.
	(record_attribute_use): Take a file_location parameter.
	Initialize attribute_use::loc.
	(md_reader::record_potential_iterator_use): Take a file_location
	parameter.  Update call to record_attribute_use.
	(rtx_reader::rtx_alloc_for_name): Update call accordingly.
	(rtx_reader::read_rtx_code): Likewise.
	(rtx_reader::read_rtx_operand): Likewise.  Record a location
	for implicitly-expanded empty strings.

From-SVN: r273511
parent 737eb767
2019-07-16 Richard Sandiford <richard.sandiford@arm.com> 2019-07-16 Richard Sandiford <richard.sandiford@arm.com>
* read-md.h (md_reader::record_potential_iterator_use): Add a
file_location parameter.
* read-rtl.c (attribute_use::loc): New field.
(map_attr_string): Take a file_location parameter. Report cases
in which attributes map to multiple distinct values.
(apply_attribute_uses): Update call accordingly.
(md_reader::handle_overloaded_name): Likewise.
(md_reader::apply_iterator_to_string): Likewise. Skip empty
nonnull strings.
(record_attribute_use): Take a file_location parameter.
Initialize attribute_use::loc.
(md_reader::record_potential_iterator_use): Take a file_location
parameter. Update call to record_attribute_use.
(rtx_reader::rtx_alloc_for_name): Update call accordingly.
(rtx_reader::read_rtx_code): Likewise.
(rtx_reader::read_rtx_operand): Likewise. Record a location
for implicitly-expanded empty strings.
2019-07-16 Richard Sandiford <richard.sandiford@arm.com>
* read-md.h (md_reader::ptr_loc): Moved from read-md.c. * read-md.h (md_reader::ptr_loc): Moved from read-md.c.
Use file_location instead of separate fields. Use file_location instead of separate fields.
(md_reader::set_md_ptr_loc): Take a file_location instead of a (md_reader::set_md_ptr_loc): Take a file_location instead of a
......
...@@ -212,8 +212,8 @@ class md_reader ...@@ -212,8 +212,8 @@ class md_reader
rtx copy_rtx_for_iterators (rtx original); rtx copy_rtx_for_iterators (rtx original);
void read_conditions (); void read_conditions ();
void record_potential_iterator_use (struct iterator_group *group, void record_potential_iterator_use (struct iterator_group *group,
rtx x, unsigned int index, file_location loc, rtx x,
const char *name); unsigned int index, const char *name);
struct mapping *read_mapping (struct iterator_group *group, htab_t table); struct mapping *read_mapping (struct iterator_group *group, htab_t table);
overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *); overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *);
......
...@@ -106,6 +106,9 @@ struct attribute_use { ...@@ -106,6 +106,9 @@ struct attribute_use {
/* The group that describes the use site. */ /* The group that describes the use site. */
struct iterator_group *group; struct iterator_group *group;
/* The location at which the use occurs. */
file_location loc;
/* The name of the attribute, possibly with an "iterator:" prefix. */ /* The name of the attribute, possibly with an "iterator:" prefix. */
const char *value; const char *value;
...@@ -361,10 +364,10 @@ find_subst_iter_by_attr (const char *attr) ...@@ -361,10 +364,10 @@ find_subst_iter_by_attr (const char *attr)
/* Map attribute string P to its current value. Return null if the attribute /* Map attribute string P to its current value. Return null if the attribute
isn't known. If ITERATOR_OUT is nonnull, store the associated iterator isn't known. If ITERATOR_OUT is nonnull, store the associated iterator
there. */ there. Report any errors against location LOC. */
static struct map_value * static struct map_value *
map_attr_string (const char *p, mapping **iterator_out = 0) map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0)
{ {
const char *attr; const char *attr;
struct mapping *iterator; struct mapping *iterator;
...@@ -372,6 +375,8 @@ map_attr_string (const char *p, mapping **iterator_out = 0) ...@@ -372,6 +375,8 @@ map_attr_string (const char *p, mapping **iterator_out = 0)
struct mapping *m; struct mapping *m;
struct map_value *v; struct map_value *v;
int iterator_name_len; int iterator_name_len;
struct map_value *res = NULL;
struct mapping *prev = NULL;
/* Peel off any "iterator:" prefix. Set ATTR to the start of the /* Peel off any "iterator:" prefix. Set ATTR to the start of the
attribute name. */ attribute name. */
...@@ -414,13 +419,22 @@ map_attr_string (const char *p, mapping **iterator_out = 0) ...@@ -414,13 +419,22 @@ map_attr_string (const char *p, mapping **iterator_out = 0)
for (v = m->values; v; v = v->next) for (v = m->values; v; v = v->next)
if (v->number == iterator->current_value->number) if (v->number == iterator->current_value->number)
{ {
if (res && strcmp (v->string, res->string) != 0)
{
error_at (loc, "ambiguous attribute '%s'; could be"
" '%s' (via '%s:%s') or '%s' (via '%s:%s')",
attr, res->string, prev->name, attr,
v->string, iterator->name, attr);
return v;
}
if (iterator_out) if (iterator_out)
*iterator_out = iterator; *iterator_out = iterator;
return v; prev = iterator;
res = v;
} }
} }
} }
return NULL; return res;
} }
/* Apply the current iterator values to STRING. Return the new string /* Apply the current iterator values to STRING. Return the new string
...@@ -432,16 +446,17 @@ md_reader::apply_iterator_to_string (const char *string) ...@@ -432,16 +446,17 @@ md_reader::apply_iterator_to_string (const char *string)
char *base, *copy, *p, *start, *end; char *base, *copy, *p, *start, *end;
struct map_value *v; struct map_value *v;
if (string == 0) if (string == 0 || string[0] == 0)
return string; return string;
file_location loc = get_md_ptr_loc (string)->loc;
base = p = copy = ASTRDUP (string); base = p = copy = ASTRDUP (string);
while ((start = strchr (p, '<')) && (end = strchr (start, '>'))) while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
{ {
p = start + 1; p = start + 1;
*end = 0; *end = 0;
v = map_attr_string (p); v = map_attr_string (loc, p);
*end = '>'; *end = '>';
if (v == 0) if (v == 0)
continue; continue;
...@@ -572,7 +587,7 @@ apply_attribute_uses (void) ...@@ -572,7 +587,7 @@ apply_attribute_uses (void)
FOR_EACH_VEC_ELT (attribute_uses, i, ause) FOR_EACH_VEC_ELT (attribute_uses, i, ause)
{ {
v = map_attr_string (ause->value); v = map_attr_string (ause->loc, ause->value);
if (!v) if (!v)
fatal_with_file_and_line ("unknown iterator value `%s'", ause->value); fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
ause->group->apply_iterator (ause->x, ause->index, ause->group->apply_iterator (ause->x, ause->index,
...@@ -656,6 +671,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators) ...@@ -656,6 +671,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
/* Remove the '@', so that no other code needs to worry about it. */ /* Remove the '@', so that no other code needs to worry about it. */
const char *name = XSTR (original, 0); const char *name = XSTR (original, 0);
file_location loc = get_md_ptr_loc (name)->loc;
copy_md_ptr_loc (name + 1, name); copy_md_ptr_loc (name + 1, name);
name += 1; name += 1;
XSTR (original, 0) = name; XSTR (original, 0) = name;
...@@ -672,7 +688,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators) ...@@ -672,7 +688,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
{ {
*end = 0; *end = 0;
mapping *iterator; mapping *iterator;
if (!map_attr_string (start + 1, &iterator)) if (!map_attr_string (loc, start + 1, &iterator))
fatal_with_file_and_line ("unknown iterator `%s'", start + 1); fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
*end = '>'; *end = '>';
...@@ -1126,24 +1142,25 @@ record_iterator_use (struct mapping *iterator, rtx x, unsigned int index) ...@@ -1126,24 +1142,25 @@ record_iterator_use (struct mapping *iterator, rtx x, unsigned int index)
iterator_uses.safe_push (iuse); iterator_uses.safe_push (iuse);
} }
/* Record that X uses attribute VALUE, which must match a built-in /* Record that X uses attribute VALUE at location LOC, where VALUE must
value from group GROUP. If the use is in an operand of X, INDEX match a built-in value from group GROUP. If the use is in an operand
is the index of that operand, otherwise it is ignored. */ of X, INDEX is the index of that operand, otherwise it is ignored. */
static void static void
record_attribute_use (struct iterator_group *group, rtx x, record_attribute_use (struct iterator_group *group, file_location loc, rtx x,
unsigned int index, const char *value) unsigned int index, const char *value)
{ {
struct attribute_use ause = {group, value, x, index}; struct attribute_use ause = {group, loc, value, x, index};
attribute_uses.safe_push (ause); attribute_uses.safe_push (ause);
} }
/* Interpret NAME as either a built-in value, iterator or attribute /* Interpret NAME as either a built-in value, iterator or attribute
for group GROUP. X and INDEX are the values to pass to GROUP's for group GROUP. X and INDEX are the values to pass to GROUP's
apply_iterator callback. */ apply_iterator callback. LOC is the location of the use. */
void void
md_reader::record_potential_iterator_use (struct iterator_group *group, md_reader::record_potential_iterator_use (struct iterator_group *group,
file_location loc,
rtx x, unsigned int index, rtx x, unsigned int index,
const char *name) const char *name)
{ {
...@@ -1156,7 +1173,7 @@ md_reader::record_potential_iterator_use (struct iterator_group *group, ...@@ -1156,7 +1173,7 @@ md_reader::record_potential_iterator_use (struct iterator_group *group,
/* Copy the attribute string into permanent storage, without the /* Copy the attribute string into permanent storage, without the
angle brackets around it. */ angle brackets around it. */
obstack_grow0 (&m_string_obstack, name + 1, len - 2); obstack_grow0 (&m_string_obstack, name + 1, len - 2);
record_attribute_use (group, x, index, record_attribute_use (group, loc, x, index,
XOBFINISH (&m_string_obstack, char *)); XOBFINISH (&m_string_obstack, char *));
} }
else else
...@@ -1540,7 +1557,8 @@ rtx_reader::rtx_alloc_for_name (const char *name) ...@@ -1540,7 +1557,8 @@ rtx_reader::rtx_alloc_for_name (const char *name)
/* Pick the first possible code for now, and record the attribute /* Pick the first possible code for now, and record the attribute
use for later. */ use for later. */
rtx x = rtx_alloc (check_code_attribute (m)); rtx x = rtx_alloc (check_code_attribute (m));
record_attribute_use (&codes, x, 0, deferred_name); record_attribute_use (&codes, get_current_location (),
x, 0, deferred_name);
return x; return x;
} }
...@@ -1639,8 +1657,8 @@ rtx_reader::read_rtx_code (const char *code_name) ...@@ -1639,8 +1657,8 @@ rtx_reader::read_rtx_code (const char *code_name)
c = read_skip_spaces (); c = read_skip_spaces ();
if (c == ':') if (c == ':')
{ {
read_name (&name); file_location loc = read_name (&name);
record_potential_iterator_use (&modes, return_rtx, 0, name.string); record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string);
} }
else else
unread_char (c); unread_char (c);
...@@ -1862,6 +1880,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) ...@@ -1862,6 +1880,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
|| GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT
|| GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE)) || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE))
{ {
const char *old_stringbuf = stringbuf;
struct obstack *string_obstack = get_string_obstack (); struct obstack *string_obstack = get_string_obstack ();
char line_name[20]; char line_name[20];
const char *read_md_filename = get_filename (); const char *read_md_filename = get_filename ();
...@@ -1875,6 +1894,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) ...@@ -1875,6 +1894,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
sprintf (line_name, ":%d", get_lineno ()); sprintf (line_name, ":%d", get_lineno ());
obstack_grow (string_obstack, line_name, strlen (line_name)+1); obstack_grow (string_obstack, line_name, strlen (line_name)+1);
stringbuf = XOBFINISH (string_obstack, char *); stringbuf = XOBFINISH (string_obstack, char *);
copy_md_ptr_loc (stringbuf, old_stringbuf);
} }
/* Find attr-names in the string. */ /* Find attr-names in the string. */
...@@ -1946,10 +1966,13 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) ...@@ -1946,10 +1966,13 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
case 'i': case 'i':
case 'n': case 'n':
case 'p': case 'p':
/* Can be an iterator or an integer constant. */ {
read_name (&name); /* Can be an iterator or an integer constant. */
record_potential_iterator_use (&ints, return_rtx, idx, name.string); file_location loc = read_name (&name);
break; record_potential_iterator_use (&ints, loc, return_rtx, idx,
name.string);
break;
}
case 'r': case 'r':
read_name (&name); read_name (&name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment