Improve error reporting from genattrtab.c
The errors reported by check_attr_value weren't very helpful because they always used the location of the define(_enum)_attr, even if the error was in a define_insn. Also, the errors reported by check_attr_test didn't say which attribute was faulty. Although not technically a bug fix, it was really useful in writing the patch for PR68432. Tested on a variety of targets. gcc/ * genattrtab.c (check_attr_test): Take an attr_desc instead of an is_const flag. Put the file_location argument first. Update recursive calls. Improve error messages. (check_attr_value): Take a file location and use it instead of attr->loc. Improve error messages. Update calls to check_attr_test. (check_defs): Update call to check_attr_value. (make_canonical): Likewise. (gen_attr): Likewise. (main): Likewise. (gen_insn_reserv): Update call to check_attr_test. From-SVN: r231103
This commit is contained in:
parent
c178abcc58
commit
481445220b
2 changed files with 88 additions and 68 deletions
|
@ -1,3 +1,17 @@
|
|||
2015-12-01 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* genattrtab.c (check_attr_test): Take an attr_desc instead of
|
||||
an is_const flag. Put the file_location argument first.
|
||||
Update recursive calls. Improve error messages.
|
||||
(check_attr_value): Take a file location and use it instead
|
||||
of attr->loc. Improve error messages. Update calls to
|
||||
check_attr_test.
|
||||
(check_defs): Update call to check_attr_value.
|
||||
(make_canonical): Likewise.
|
||||
(gen_attr): Likewise.
|
||||
(main): Likewise.
|
||||
(gen_insn_reserv): Update call to check_attr_test.
|
||||
|
||||
2015-12-01 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
|
||||
|
||||
* config/aarch64/aarch64.c (aarch64_builtin_reciprocal): Fix typo.
|
||||
|
|
142
gcc/genattrtab.c
142
gcc/genattrtab.c
|
@ -729,9 +729,8 @@ attr_copy_rtx (rtx orig)
|
|||
return copy;
|
||||
}
|
||||
|
||||
/* Given a test expression for an attribute, ensure it is validly formed.
|
||||
IS_CONST indicates whether the expression is constant for each compiler
|
||||
run (a constant expression may not test any particular insn).
|
||||
/* Given a test expression EXP for attribute ATTR, ensure it is validly
|
||||
formed. LOC is the location of the .md construct that contains EXP.
|
||||
|
||||
Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..))
|
||||
and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")). Do the latter
|
||||
|
@ -744,9 +743,8 @@ attr_copy_rtx (rtx orig)
|
|||
Return the new expression, if any. */
|
||||
|
||||
static rtx
|
||||
check_attr_test (rtx exp, int is_const, file_location loc)
|
||||
check_attr_test (file_location loc, rtx exp, attr_desc *attr)
|
||||
{
|
||||
struct attr_desc *attr;
|
||||
struct attr_value *av;
|
||||
const char *name_ptr, *p;
|
||||
rtx orexp, newexp;
|
||||
|
@ -756,26 +754,27 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
case EQ_ATTR:
|
||||
/* Handle negation test. */
|
||||
if (XSTR (exp, 1)[0] == '!')
|
||||
return check_attr_test (attr_rtx (NOT,
|
||||
return check_attr_test (loc,
|
||||
attr_rtx (NOT,
|
||||
attr_eq (XSTR (exp, 0),
|
||||
&XSTR (exp, 1)[1])),
|
||||
is_const, loc);
|
||||
attr);
|
||||
|
||||
else if (n_comma_elts (XSTR (exp, 1)) == 1)
|
||||
{
|
||||
attr = find_attr (&XSTR (exp, 0), 0);
|
||||
if (attr == NULL)
|
||||
attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
|
||||
if (attr2 == NULL)
|
||||
{
|
||||
if (! strcmp (XSTR (exp, 0), "alternative"))
|
||||
return mk_attr_alt (((uint64_t) 1) << atoi (XSTR (exp, 1)));
|
||||
else
|
||||
fatal_at (loc, "unknown attribute `%s' in EQ_ATTR",
|
||||
XSTR (exp, 0));
|
||||
fatal_at (loc, "unknown attribute `%s' in definition of"
|
||||
" attribute `%s'", XSTR (exp, 0), attr->name);
|
||||
}
|
||||
|
||||
if (is_const && ! attr->is_const)
|
||||
fatal_at (loc, "constant expression uses insn attribute `%s'"
|
||||
" in EQ_ATTR", XSTR (exp, 0));
|
||||
if (attr->is_const && ! attr2->is_const)
|
||||
fatal_at (loc, "constant attribute `%s' cannot test non-constant"
|
||||
" attribute `%s'", attr->name, attr2->name);
|
||||
|
||||
/* Copy this just to make it permanent,
|
||||
so expressions using it can be permanent too. */
|
||||
|
@ -784,26 +783,26 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
/* It shouldn't be possible to simplify the value given to a
|
||||
constant attribute, so don't expand this until it's time to
|
||||
write the test expression. */
|
||||
if (attr->is_const)
|
||||
if (attr2->is_const)
|
||||
ATTR_IND_SIMPLIFIED_P (exp) = 1;
|
||||
|
||||
if (attr->is_numeric)
|
||||
if (attr2->is_numeric)
|
||||
{
|
||||
for (p = XSTR (exp, 1); *p; p++)
|
||||
if (! ISDIGIT (*p))
|
||||
fatal_at (loc, "attribute `%s' takes only numeric values",
|
||||
XSTR (exp, 0));
|
||||
attr2->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (av = attr->first_value; av; av = av->next)
|
||||
for (av = attr2->first_value; av; av = av->next)
|
||||
if (GET_CODE (av->value) == CONST_STRING
|
||||
&& ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
|
||||
break;
|
||||
|
||||
if (av == NULL)
|
||||
fatal_at (loc, "unknown value `%s' for `%s' attribute",
|
||||
XSTR (exp, 1), XSTR (exp, 0));
|
||||
fatal_at (loc, "unknown value `%s' for attribute `%s'",
|
||||
XSTR (exp, 1), attr2->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -829,7 +828,7 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
|
||||
}
|
||||
|
||||
return check_attr_test (orexp, is_const, loc);
|
||||
return check_attr_test (loc, orexp, attr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -846,12 +845,12 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
|
||||
case IOR:
|
||||
case AND:
|
||||
XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, loc);
|
||||
XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const, loc);
|
||||
XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
|
||||
XEXP (exp, 1) = check_attr_test (loc, XEXP (exp, 1), attr);
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, loc);
|
||||
XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
|
||||
break;
|
||||
|
||||
case MATCH_TEST:
|
||||
|
@ -860,9 +859,10 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
break;
|
||||
|
||||
case MATCH_OPERAND:
|
||||
if (is_const)
|
||||
fatal_at (loc, "RTL operator \"%s\" not valid in constant attribute"
|
||||
" test", GET_RTX_NAME (GET_CODE (exp)));
|
||||
if (attr->is_const)
|
||||
fatal_at (loc, "invalid operator `%s' in definition of constant"
|
||||
" attribute `%s'", GET_RTX_NAME (GET_CODE (exp)),
|
||||
attr->name);
|
||||
/* These cases can't be simplified. */
|
||||
ATTR_IND_SIMPLIFIED_P (exp) = 1;
|
||||
break;
|
||||
|
@ -880,7 +880,7 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
break;
|
||||
|
||||
case SYMBOL_REF:
|
||||
if (is_const)
|
||||
if (attr->is_const)
|
||||
{
|
||||
/* These cases are valid for constant attributes, but can't be
|
||||
simplified. */
|
||||
|
@ -889,21 +889,21 @@ check_attr_test (rtx exp, int is_const, file_location loc)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
fatal_at (loc, "RTL operator \"%s\" not valid in attribute test",
|
||||
GET_RTX_NAME (GET_CODE (exp)));
|
||||
fatal_at (loc, "invalid operator `%s' in definition of attribute"
|
||||
" `%s'", GET_RTX_NAME (GET_CODE (exp)), attr->name);
|
||||
}
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Given an expression, ensure that it is validly formed and that all named
|
||||
attribute values are valid for the given attribute. Issue a fatal error
|
||||
if not.
|
||||
/* Given an expression EXP, ensure that it is validly formed and that
|
||||
all named attribute values are valid for ATTR. Issue an error if not.
|
||||
LOC is the location of the .md construct that contains EXP.
|
||||
|
||||
Return a perhaps modified replacement expression for the value. */
|
||||
|
||||
static rtx
|
||||
check_attr_value (rtx exp, struct attr_desc *attr)
|
||||
check_attr_value (file_location loc, rtx exp, struct attr_desc *attr)
|
||||
{
|
||||
struct attr_value *av;
|
||||
const char *p;
|
||||
|
@ -914,16 +914,16 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
case CONST_INT:
|
||||
if (!attr->is_numeric)
|
||||
{
|
||||
error_at (attr->loc,
|
||||
"CONST_INT not valid for non-numeric attribute %s",
|
||||
error_at (loc,
|
||||
"CONST_INT not valid for non-numeric attribute `%s'",
|
||||
attr->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (INTVAL (exp) < 0)
|
||||
{
|
||||
error_at (attr->loc,
|
||||
"negative numeric value specified for attribute %s",
|
||||
error_at (loc,
|
||||
"negative numeric value specified for attribute `%s'",
|
||||
attr->name);
|
||||
break;
|
||||
}
|
||||
|
@ -939,9 +939,9 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
for (; *p; p++)
|
||||
if (! ISDIGIT (*p))
|
||||
{
|
||||
error_at (attr->loc,
|
||||
"non-numeric value for numeric attribute %s",
|
||||
attr->name);
|
||||
error_at (loc,
|
||||
"non-numeric value specified for numeric"
|
||||
" attribute `%s'", attr->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -953,15 +953,14 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
break;
|
||||
|
||||
if (av == NULL)
|
||||
error_at (attr->loc, "unknown value `%s' for `%s' attribute",
|
||||
error_at (loc, "unknown value `%s' for attribute `%s'",
|
||||
XSTR (exp, 0), attr->name);
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), attr->is_const,
|
||||
attr->loc);
|
||||
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
|
||||
XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
|
||||
XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
|
||||
XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
|
||||
XEXP (exp, 2) = check_attr_value (loc, XEXP (exp, 2), attr);
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
|
@ -971,16 +970,17 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
case MOD:
|
||||
if (!attr->is_numeric)
|
||||
{
|
||||
error_at (attr->loc, "invalid operation `%s' for non-numeric"
|
||||
" attribute value", GET_RTX_NAME (GET_CODE (exp)));
|
||||
error_at (loc, "invalid operation `%s' for non-numeric"
|
||||
" attribute `%s'", GET_RTX_NAME (GET_CODE (exp)),
|
||||
attr->name);
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case IOR:
|
||||
case AND:
|
||||
XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
|
||||
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
|
||||
XEXP (exp, 0) = check_attr_value (loc, XEXP (exp, 0), attr);
|
||||
XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
|
||||
break;
|
||||
|
||||
case FFS:
|
||||
|
@ -989,41 +989,42 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
case POPCOUNT:
|
||||
case PARITY:
|
||||
case BSWAP:
|
||||
XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
|
||||
XEXP (exp, 0) = check_attr_value (loc, XEXP (exp, 0), attr);
|
||||
break;
|
||||
|
||||
case COND:
|
||||
if (XVECLEN (exp, 0) % 2 != 0)
|
||||
{
|
||||
error_at (attr->loc, "first operand of COND must have even length");
|
||||
error_at (loc, "first operand of COND must have even length");
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
{
|
||||
XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
|
||||
attr->is_const, attr->loc);
|
||||
XVECEXP (exp, 0, i) = check_attr_test (attr->loc,
|
||||
XVECEXP (exp, 0, i),
|
||||
attr);
|
||||
XVECEXP (exp, 0, i + 1)
|
||||
= check_attr_value (XVECEXP (exp, 0, i + 1), attr);
|
||||
= check_attr_value (loc, XVECEXP (exp, 0, i + 1), attr);
|
||||
}
|
||||
|
||||
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
|
||||
XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
|
||||
break;
|
||||
|
||||
case ATTR:
|
||||
{
|
||||
struct attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
|
||||
if (attr2 == NULL)
|
||||
error_at (attr->loc, "unknown attribute `%s' in ATTR",
|
||||
error_at (loc, "unknown attribute `%s' in ATTR",
|
||||
XSTR (exp, 0));
|
||||
else if (attr->is_const && ! attr2->is_const)
|
||||
error_at (attr->loc,
|
||||
"non-constant attribute `%s' referenced from `%s'",
|
||||
XSTR (exp, 0), attr->name);
|
||||
"constant attribute `%s' cannot refer to non-constant"
|
||||
" attribute `%s'", attr->name, attr2->name);
|
||||
else if (attr->is_numeric != attr2->is_numeric)
|
||||
error_at (attr->loc,
|
||||
error_at (loc,
|
||||
"numeric attribute mismatch calling `%s' from `%s'",
|
||||
XSTR (exp, 0), attr->name);
|
||||
attr2->name, attr->name);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1034,8 +1035,8 @@ check_attr_value (rtx exp, struct attr_desc *attr)
|
|||
return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
|
||||
|
||||
default:
|
||||
error_at (attr->loc, "invalid operation `%s' for attribute value",
|
||||
GET_RTX_NAME (GET_CODE (exp)));
|
||||
error_at (loc, "invalid operator `%s' in definition of attribute `%s'",
|
||||
GET_RTX_NAME (GET_CODE (exp)), attr->name);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1163,7 +1164,7 @@ check_defs (void)
|
|||
}
|
||||
|
||||
XVECEXP (id->def, id->vec_idx, i) = value;
|
||||
XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
|
||||
XEXP (value, 1) = check_attr_value (id->loc, XEXP (value, 1), attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1204,7 +1205,7 @@ make_canonical (file_location loc, struct attr_desc *attr, rtx exp)
|
|||
This makes the COND something that won't be considered an arbitrary
|
||||
expression by walk_attr_value. */
|
||||
ATTR_IND_SIMPLIFIED_P (exp) = 1;
|
||||
exp = check_attr_value (exp, attr);
|
||||
exp = check_attr_value (loc, exp, attr);
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
|
@ -3186,7 +3187,7 @@ gen_attr (md_rtx_info *info)
|
|||
error_at (info->loc, "`length' attribute must take numeric values");
|
||||
|
||||
/* Set up the default value. */
|
||||
XEXP (def, 2) = check_attr_value (XEXP (def, 2), attr);
|
||||
XEXP (def, 2) = check_attr_value (info->loc, XEXP (def, 2), attr);
|
||||
attr->default_val = get_attr_value (info->loc, XEXP (def, 2), attr, -2);
|
||||
}
|
||||
|
||||
|
@ -4755,9 +4756,14 @@ gen_insn_reserv (md_rtx_info *info)
|
|||
struct insn_reserv *decl = oballoc (struct insn_reserv);
|
||||
rtx def = info->def;
|
||||
|
||||
struct attr_desc attr;
|
||||
memset (&attr, 0, sizeof (attr));
|
||||
attr.name = DEF_ATTR_STRING (XSTR (def, 0));
|
||||
attr.loc = info->loc;
|
||||
|
||||
decl->name = DEF_ATTR_STRING (XSTR (def, 0));
|
||||
decl->default_latency = XINT (def, 1);
|
||||
decl->condexp = check_attr_test (XEXP (def, 2), 0, info->loc);
|
||||
decl->condexp = check_attr_test (info->loc, XEXP (def, 2), &attr);
|
||||
decl->insn_num = n_insn_reservs;
|
||||
decl->bypassed = false;
|
||||
decl->next = 0;
|
||||
|
@ -5287,7 +5293,7 @@ main (int argc, char **argv)
|
|||
for (i = 0; i < MAX_ATTRS_INDEX; i++)
|
||||
for (attr = attrs[i]; attr; attr = attr->next)
|
||||
attr->default_val->value
|
||||
= check_attr_value (attr->default_val->value, attr);
|
||||
= check_attr_value (attr->loc, attr->default_val->value, attr);
|
||||
|
||||
if (have_error)
|
||||
return FATAL_EXIT_CODE;
|
||||
|
|
Loading…
Add table
Reference in a new issue