@@ -8070,7 +8070,7 @@ The @code{define_attr} expression is used to define each attribute required
by the target machine. It looks like:
@smallexample
-(define_attr @var{name} @var{list-of-values} @var{default})
+(define_attr @var{name} @var{list-of-values} @var{default} @var{type})
@end smallexample
@var{name} is a string specifying the name of the attribute being
@@ -8095,6 +8095,25 @@ an explicit value for this attribute. @xref{Attr Example}, for more
information on the handling of defaults. @xref{Constant Attributes},
for information on attributes that do not depend on any particular insn.
+@var{type} is an optional string that specifies the type of the attribute.
+The possible values are:
+
+@table @code
+@item code,alternative
+The attribute is a function of the instruction code and the alternative
+number. It does not need need access to a particular rtx instruction
+or to a particular set of operands.
+
+@item insn
+The attribute is a function of an rtx instruction. It can depend on
+things like operand values.
+@end table
+
+If @var{type} is omitted, the default type is @code{insn}.
+@code{insn} attributes may refer to both @code{insn} and
+@code{code,alternative} attributes, but @code{code,alternative} attributes
+may only refer to other @code{code,alternative} attributes.
+
@findex insn-attr.h
For each defined attribute, a number of definitions are written to the
@file{insn-attr.h} file. For cases where an explicit set of values is
@@ -8110,14 +8129,21 @@ elements of the form @samp{@var{upper-name}_@var{upper-value}} where
the attribute name and value are first converted to uppercase.
@item
-A function @samp{get_attr_@var{name}} is defined that is passed an insn and
+For @code{code,alternative} attributes, a function @samp{get_attr_@var{name}}
+is defined that takes an @code{int} instruction code number and an
+@code{int} alternative number and returns the associated attribute value.
+
+@item
+For both @code{code,alternative} and @var{insn} attributes, a function
+@samp{get_attr_@var{name}} is defined that is passed an insn and
returns the attribute value for that insn.
@end itemize
For example, if the following is present in the @file{md} file:
@smallexample
-(define_attr "type" "branch,fp,load,store,arith" @dots{})
+(define_attr "type" "branch,fp,load,store,arith" @dots{}
+ "code,alternative")
@end smallexample
@noindent
@@ -8127,7 +8153,8 @@ the following lines will be written to the file @file{insn-attr.h}.
#define HAVE_ATTR_type 1
enum attr_type @{TYPE_BRANCH, TYPE_FP, TYPE_LOAD,
TYPE_STORE, TYPE_ARITH@};
-extern enum attr_type get_attr_type ();
+extern enum attr_type get_attr_type (int, int);
+extern enum attr_type get_attr_type (rtx_insn *);
@end smallexample
If the attribute takes numeric values, no @code{enum} type will be
@@ -8163,7 +8190,7 @@ attribute is not defined; in that case, it is defined as @samp{0}.
Another way of defining an attribute is to use:
@smallexample
-(define_enum_attr "@var{attr}" "@var{enum}" @var{default})
+(define_enum_attr "@var{attr}" "@var{enum}" @var{default} @var{type})
@end smallexample
This works in just the same way as @code{define_attr}, except that
@@ -31,34 +31,42 @@ along with GCC; see the file COPYING3. If not see
static vec<rtx> const_attrs, reservations;
+/* Declare a get_attr_*-style function for ATTR with the argument
+ types specified in string PROTOTYPE. */
+
+static void
+declare_function (rtx attr, const char *prototype)
+{
+ if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
+ printf ("extern enum %s get_attr_%s (%s);\n",
+ XSTR (attr, 1), XSTR (attr, 0), prototype);
+ else
+ {
+ const char *p = XSTR (attr, 1);
+ if (*p == '\0')
+ printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), prototype);
+ else
+ printf ("extern enum attr_%s get_attr_%s (%s);\n",
+ XSTR (attr, 0), XSTR (attr, 0), prototype);
+ }
+}
+
static void
gen_attr (md_rtx_info *info)
{
- const char *p;
rtx attr = info->def;
- int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
-
- if (is_const)
- const_attrs.safe_push (attr);
+ attr_type type = parse_attr_type (info->loc, attr);
printf ("#define HAVE_ATTR_%s 1\n", XSTR (attr, 0));
- /* If numeric attribute, don't need to write an enum. */
- if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
- printf ("extern enum %s get_attr_%s (%s);\n\n",
- XSTR (attr, 1), XSTR (attr, 0),
- (is_const ? "void" : "rtx_insn *"));
+ if (type == AT_CONST)
+ const_attrs.safe_push (attr);
else
{
- p = XSTR (attr, 1);
- if (*p == '\0')
- printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
- (is_const ? "void" : "rtx_insn *"));
- else
- printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
- XSTR (attr, 0), XSTR (attr, 0),
- (is_const ? "void" : "rtx_insn *"));
+ if (type == AT_CODE_ALT)
+ declare_function (attr, "int, int");
+ declare_function (attr, "rtx_insn *");
}
/* If `length' attribute, write additional function definitions and define
@@ -177,9 +177,12 @@ struct attr_desc
struct attr_value *first_value; /* First value of this attribute. */
struct attr_value *default_val; /* Default value for this attribute. */
file_location loc; /* Where in the .md files it occurs. */
- unsigned is_numeric : 1; /* Values of this attribute are numeric. */
- unsigned is_const : 1; /* Attribute value constant for each run. */
- unsigned is_special : 1; /* Don't call `write_attr_set'. */
+ ENUM_BITFIELD (attr_type) type : 2;
+ /* Type of attribute. */
+ unsigned is_numeric : 1; /* Values of this attribute are numeric. */
+ unsigned is_special : 1; /* Don't call `write_attr_set'. */
+
+ bool is_const () const { return type == AT_CONST; }
};
/* Structure for each DEFINE_DELAY. */
@@ -772,9 +775,10 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
" attribute `%s'", XSTR (exp, 0), attr->name);
}
- if (attr->is_const && ! attr2->is_const)
- fatal_at (loc, "constant attribute `%s' cannot test non-constant"
- " attribute `%s'", attr->name, attr2->name);
+ if (attr->type < attr2->type)
+ fatal_at (loc, "%s attribute `%s' cannot test %s attribute `%s'",
+ get_attr_type_name (attr->type), attr->name,
+ get_attr_type_name (attr2->type), attr2->name);
/* Copy this just to make it permanent,
so expressions using it can be permanent too. */
@@ -783,7 +787,7 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
/* 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 (attr2->is_const)
+ if (attr2->is_const ())
ATTR_IND_SIMPLIFIED_P (exp) = 1;
if (attr2->is_numeric)
@@ -859,10 +863,10 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
break;
case MATCH_OPERAND:
- if (attr->is_const)
- fatal_at (loc, "invalid operator `%s' in definition of constant"
+ if (attr->type < AT_INSN)
+ fatal_at (loc, "invalid operator `%s' in definition of %s"
" attribute `%s'", GET_RTX_NAME (GET_CODE (exp)),
- attr->name);
+ get_attr_type_name (attr->type), attr->name);
/* These cases can't be simplified. */
ATTR_IND_SIMPLIFIED_P (exp) = 1;
break;
@@ -880,7 +884,7 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr)
break;
case SYMBOL_REF:
- if (attr->is_const)
+ if (attr->is_const ())
{
/* These cases are valid for constant attributes, but can't be
simplified. */
@@ -1017,10 +1021,11 @@ check_attr_value (file_location loc, rtx exp, struct attr_desc *attr)
if (attr2 == NULL)
error_at (loc, "unknown attribute `%s' in ATTR",
XSTR (exp, 0));
- else if (attr->is_const && ! attr2->is_const)
- error_at (attr->loc,
- "constant attribute `%s' cannot refer to non-constant"
- " attribute `%s'", attr->name, attr2->name);
+ else if (attr->type < attr2->type)
+ error_at (loc,
+ "%s attribute `%s' cannot refer to %s attribute `%s'",
+ get_attr_type_name (attr->type), attr->name,
+ get_attr_type_name (attr2->type), attr2->name);
else if (attr->is_numeric != attr2->is_numeric)
error_at (loc,
"numeric attribute mismatch calling `%s' from `%s'",
@@ -1199,7 +1204,7 @@ make_canonical (file_location loc, struct attr_desc *attr, rtx exp)
break;
case SYMBOL_REF:
- if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
+ if (!attr->is_const () || ATTR_IND_SIMPLIFIED_P (exp))
break;
/* The SYMBOL_REF is constant for a given run, so mark it as unchanging.
This makes the COND something that won't be considered an arbitrary
@@ -1425,7 +1430,7 @@ fill_attr (struct attr_desc *attr)
/* Don't fill constant attributes. The value is independent of
any particular insn. */
- if (attr->is_const)
+ if (attr->is_const ())
return;
for (id = defs; id; id = id->next)
@@ -1557,7 +1562,7 @@ make_length_attrs (void)
if (! length_attr->is_numeric)
fatal_at (length_attr->loc, "length attribute must be numeric");
- length_attr->is_const = 0;
+ length_attr->type = AT_INSN;
length_attr->is_special = 1;
/* Make each new attribute, in turn. */
@@ -2889,7 +2894,7 @@ get_attr_order (struct attr_desc ***ret)
j = 0;
for (i = 0; i < num; i++)
- if (all[i]->is_const)
+ if (all[i]->is_const ())
handled[i] = 1, sorted[j++] = all[i];
/* We have only few attributes hence we can live with the inner
@@ -2917,7 +2922,7 @@ get_attr_order (struct attr_desc ***ret)
}
if (k == num)
{
- /* Nothing in I depended on anything intersting, so
+ /* Nothing in I depended on anything interesting, so
it's done. */
handled[i] = 1;
sorted[j++] = all[i];
@@ -2935,7 +2940,7 @@ get_attr_order (struct attr_desc ***ret)
fprintf (stderr, "%s depends on: ", attr->name);
for (i = 0; i < MAX_ATTRS_INDEX; ++i)
for (attr2 = attrs[i]; attr2; attr2 = attr2->next)
- if (!attr2->is_const)
+ if (!attr2->is_const ())
for (av = attr->first_value; av; av = av->next)
if (av->num_insns != 0)
if (tests_attr_p (av->value, attr2))
@@ -3152,6 +3157,8 @@ gen_attr (md_rtx_info *info)
}
attr->loc = info->loc;
+ attr->type = parse_attr_type (info->loc, def);
+
if (GET_CODE (def) == DEFINE_ENUM_ATTR)
{
attr->enum_name = XSTR (def, 1);
@@ -3172,9 +3179,8 @@ gen_attr (md_rtx_info *info)
add_attr_value (attr, p);
}
- if (GET_CODE (XEXP (def, 2)) == CONST)
+ if (attr->type == AT_CONST)
{
- attr->is_const = 1;
if (attr->is_numeric)
error_at (info->loc,
"constant attributes may not take numeric values");
@@ -3389,7 +3395,7 @@ find_attrs_to_cache (rtx exp, bool create)
return;
attr = find_attr (&name, 0);
gcc_assert (attr);
- if (attr->is_const)
+ if (attr->type != AT_INSN)
return;
if (cached_attr_count == 32)
return;
@@ -3688,13 +3694,17 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags)
gcc_assert (attr);
/* Now is the time to expand the value of a constant attribute. */
- if (attr->is_const)
+ if (attr->type == AT_CONST)
+ write_test_expr (outf,
+ evaluate_eq_attr (exp, attr,
+ attr->default_val->value,
+ -2, -2),
+ attrs_cached, 0);
+ else if (attr->type == AT_CODE_ALT)
{
- write_test_expr (outf,
- evaluate_eq_attr (exp, attr,
- attr->default_val->value,
- -2, -2),
- attrs_cached, 0);
+ fprintf (outf, "get_attr_%s (icode, which_alternative)", attr->name);
+ fprintf (outf, " == ");
+ write_attr_valueq (outf, attr, XSTR (exp, 1));
}
else
{
@@ -3932,6 +3942,7 @@ walk_attr_value (rtx exp)
int i, j;
const char *fmt;
RTX_CODE code;
+ attr_desc *attr;
if (exp == NULL)
return;
@@ -3957,6 +3968,9 @@ walk_attr_value (rtx exp)
break;
case EQ_ATTR:
+ attr = find_attr (&XSTR (exp, 0), 0);
+ if (attr->type == AT_CODE_ALT)
+ must_constrain = 1;
if (XSTR (exp, 0) == alternative_name)
must_extract = must_constrain = 1;
else if (strcmp_check (XSTR (exp, 0), length_str) == 0)
@@ -3995,6 +4009,19 @@ walk_attr_value (rtx exp)
}
}
+/* Write the return type of ATTR's function to OUTF. */
+
+static void
+write_attr_return_type (FILE *outf, struct attr_desc *attr)
+{
+ if (attr->enum_name)
+ fprintf (outf, "enum %s", attr->enum_name);
+ else if (!attr->is_numeric)
+ fprintf (outf, "enum attr_%s", attr->name);
+ else
+ fprintf (outf, "int");
+}
+
/* Write out a function to obtain the attribute for a given INSN. */
static void
@@ -4009,39 +4036,30 @@ write_attr_get (FILE *outf, struct attr_desc *attr)
/* Write out start of function, then all values with explicit `case' lines,
then a `default', then the value with the most uses. */
- if (attr->enum_name)
- fprintf (outf, "enum %s\n", attr->enum_name);
- else if (!attr->is_numeric)
- fprintf (outf, "enum attr_%s\n", attr->name);
+ write_attr_return_type (outf, attr);
+
+ if (attr->type == AT_CONST)
+ gcc_unreachable ();
+ else if (attr->type == AT_CODE_ALT)
+ fprintf (outf, "\nget_attr_%s (int icode,"
+ " int which_alternative ATTRIBUTE_UNUSED)\n",
+ attr->name);
+ else if (attr->name[0] == '*')
+ /* If the attribute name starts with a star, the remainder is the name of
+ the subroutine to use, instead of `get_attr_...'. */
+ fprintf (outf, "\n%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
else
- fprintf (outf, "int\n");
-
- /* If the attribute name starts with a star, the remainder is the name of
- the subroutine to use, instead of `get_attr_...'. */
- if (attr->name[0] == '*')
- fprintf (outf, "%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
- else if (attr->is_const == 0)
- fprintf (outf, "get_attr_%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n", attr->name);
- else
- {
- fprintf (outf, "get_attr_%s (void)\n", attr->name);
- fprintf (outf, "{\n");
-
- for (av = attr->first_value; av; av = av->next)
- if (av->num_insns == 1)
- write_attr_set (outf, attr, 2, av->value, "return", ";",
- true_rtx, av->first_insn->def->insn_code,
- av->first_insn->def->insn_index, 0);
- else if (av->num_insns != 0)
- write_attr_set (outf, attr, 2, av->value, "return", ";",
- true_rtx, -2, 0, 0);
-
- fprintf (outf, "}\n\n");
- return;
- }
+ fprintf (outf, "\nget_attr_%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n",
+ attr->name);
fprintf (outf, "{\n");
+ if (attr->type == AT_CODE_ALT)
+ fprintf (outf, "#define recog_data _Pragma ("
+ "\"GCC error \\\"recog_data cannot be used"
+ " in %s attributes\\\"\") recog_data\n",
+ get_attr_type_name (attr->type));
+
/* Find attributes that are worth caching in the conditions. */
cached_attr_count = 0;
attrs_seen_more_than_once = 0;
@@ -4059,13 +4077,9 @@ write_attr_get (FILE *outf, struct attr_desc *attr)
if (i != j)
cached_attrs[j] = name;
cached_attr = find_attr (&name, 0);
- gcc_assert (cached_attr && cached_attr->is_const == 0);
- if (cached_attr->enum_name)
- fprintf (outf, " enum %s", cached_attr->enum_name);
- else if (!cached_attr->is_numeric)
- fprintf (outf, " enum attr_%s", cached_attr->name);
- else
- fprintf (outf, " int");
+ gcc_assert (cached_attr && cached_attr->type == AT_INSN);
+ fprintf (outf, " ");
+ write_attr_return_type (outf, cached_attr);
fprintf (outf, " cached_%s ATTRIBUTE_UNUSED;\n", name);
j++;
}
@@ -4073,7 +4087,9 @@ write_attr_get (FILE *outf, struct attr_desc *attr)
if (cached_attr_count)
fprintf (outf, "\n");
- fprintf (outf, " switch (recog_memoized (insn))\n");
+ if (attr->type == AT_INSN)
+ fprintf (outf, " int icode = recog_memoized (insn);\n");
+ fprintf (outf, " switch (icode)\n");
fprintf (outf, " {\n");
for (av = attr->first_value; av; av = av->next)
@@ -4081,8 +4097,22 @@ write_attr_get (FILE *outf, struct attr_desc *attr)
write_attr_case (outf, attr, av, 1, "return", ";", 4, true_rtx);
write_attr_case (outf, attr, common_av, 0, "return", ";", 4, true_rtx);
- fprintf (outf, " }\n}\n\n");
+ fprintf (outf, " }\n");
+ if (attr->type == AT_CODE_ALT)
+ fprintf (outf, "#undef recog_data\n");
+ fprintf (outf, "}\n\n");
cached_attr_count = 0;
+ if (attr->type == AT_CODE_ALT)
+ {
+ write_attr_return_type (outf, attr);
+ fprintf (outf, "\nget_attr_%s (rtx_insn *insn)\n", attr->name);
+ fprintf (outf, "{\n");
+ fprintf (outf, " int which_alternative = "
+ "extract_constrain_insn_cached (insn);\n");
+ fprintf (outf, " return get_attr_%s (INSN_CODE (insn),"
+ " which_alternative);\n", attr->name);
+ fprintf (outf, "}\n\n");
+ }
}
/* Given an AND tree of known true terms (because we are inside an `if' with
@@ -4254,7 +4284,7 @@ write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av,
if (av->num_insns == 0)
return;
- if (av->has_asm_insn)
+ if (attr->type == AT_INSN && av->has_asm_insn)
{
write_indent (outf, indent);
fprintf (outf, "case -1:\n");
@@ -4279,19 +4309,22 @@ write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av,
walk_attr_value (av->value);
int code_indent = indent + 2;
- if (must_constrain)
- {
- code_indent += 2;
- write_indent (outf, indent + 2);
- fprintf (outf, "{\n");
- write_indent (outf, code_indent);
- fprintf (outf, "int which_alternative ATTRIBUTE_UNUSED = "
- "extract_constrain_insn_cached (insn);\n");
- }
- else if (must_extract)
+ if (attr->type == AT_INSN)
{
- write_indent (outf, code_indent);
- fprintf (outf, "extract_insn_cached (insn);\n");
+ if (must_constrain)
+ {
+ code_indent += 2;
+ write_indent (outf, indent + 2);
+ fprintf (outf, "{\n");
+ write_indent (outf, code_indent);
+ fprintf (outf, "int which_alternative ATTRIBUTE_UNUSED = "
+ "extract_constrain_insn_cached (insn);\n");
+ }
+ else if (must_extract)
+ {
+ write_indent (outf, code_indent);
+ fprintf (outf, "extract_insn_cached (insn);\n");
+ }
}
attrs_to_cache = 0;
@@ -4360,15 +4393,17 @@ write_attr_value (FILE *outf, struct attr_desc *attr, rtx value)
case ATTR:
{
struct attr_desc *attr2 = find_attr (&XSTR (value, 0), 0);
- if (attr->enum_name)
- fprintf (outf, "(enum %s)", attr->enum_name);
- else if (!attr->is_numeric)
- fprintf (outf, "(enum attr_%s)", attr->name);
- else if (!attr2->is_numeric)
- fprintf (outf, "(int)");
-
- fprintf (outf, "get_attr_%s (%s)", attr2->name,
- (attr2->is_const ? "" : "insn"));
+ fprintf (outf, "(");
+ write_attr_return_type (outf, attr);
+ fprintf (outf, ")");
+
+ fprintf (outf, "get_attr_%s", attr2->name);
+ if (attr->type == AT_CONST)
+ gcc_unreachable ();
+ else if (attr->type == AT_CODE_ALT)
+ fprintf (outf, " (icode, which_alternative)\n");
+ else
+ fprintf (outf, " (insn)\n");
}
break;
@@ -4623,11 +4658,10 @@ find_attr (const char **name_p, int create)
return NULL;
attr = oballoc (struct attr_desc);
+ memset (attr, 0, sizeof (*attr));
attr->name = DEF_ATTR_STRING (name);
- attr->enum_name = 0;
- attr->first_value = attr->default_val = NULL;
- attr->is_numeric = attr->is_const = attr->is_special = 0;
attr->next = attrs[index];
+ attr->type = AT_INSN;
attrs[index] = attr;
*name_p = attr->name;
@@ -4646,7 +4680,7 @@ make_internal_attr (const char *name, rtx value, int special)
gcc_assert (!attr->default_val);
attr->is_numeric = 1;
- attr->is_const = 0;
+ attr->type = AT_INSN;
attr->is_special = (special & ATTR_SPECIAL) != 0;
attr->default_val = get_attr_value (file_location ("<internal>", 0),
value, attr, -2);
@@ -4770,6 +4804,7 @@ gen_insn_reserv (md_rtx_info *info)
memset (&attr, 0, sizeof (attr));
attr.name = DEF_ATTR_STRING (XSTR (def, 0));
attr.loc = info->loc;
+ attr.type = AT_INSN;
decl->name = DEF_ATTR_STRING (XSTR (def, 0));
decl->default_latency = XINT (def, 1);
@@ -4904,7 +4939,7 @@ find_tune_attr (rtx exp)
attr = find_attr (&XSTR (exp, 0), 0);
gcc_assert (attr);
- if (attr->is_const && !attr->is_special)
+ if (attr->is_const () && !attr->is_special)
{
struct insn_reserv *decl;
@@ -4942,7 +4977,7 @@ make_automaton_attrs (void)
struct attr_value *val;
bool first = true;
- gcc_assert (tune_attr->is_const
+ gcc_assert (tune_attr->is_const ()
&& !tune_attr->is_special
&& !tune_attr->is_numeric);
@@ -5335,7 +5370,7 @@ main (int argc, char **argv)
outf = attr_file;
#undef IS_ATTR_GROUP
- if (! attr->is_special && ! attr->is_const)
+ if (! attr->is_special && !attr->is_const ())
write_attr_get (outf, attr);
}
@@ -434,10 +434,10 @@ remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
*queue = elem->next;
}
-/* Build a define_attr for an binary attribute with name NAME and
- possible values "yes" and "no", and queue it. */
+/* Build a define_attr for a binary attribute with name NAME, type TYPE,
+ and possible values "yes" and "no", then queue it. */
static void
-add_define_attr (const char *name)
+add_define_attr (const char *name, const char *type)
{
struct queue_elem *e = XNEW (struct queue_elem);
rtx t1 = rtx_alloc (DEFINE_ATTR);
@@ -445,6 +445,7 @@ add_define_attr (const char *name)
XSTR (t1, 1) = "no,yes";
XEXP (t1, 2) = rtx_alloc (CONST_STRING);
XSTR (XEXP (t1, 2), 0) = "yes";
+ XSTR (t1, 3) = type;
e->data = t1;
e->loc = file_location ("built-in", -1);
e->next = define_attr_queue;
@@ -1372,15 +1373,21 @@ alter_attrs_for_insn (rtx insn)
struct queue_elem *elem;
global_changes_made = true;
- add_define_attr ("ce_enabled");
- add_define_attr ("nonce_enabled");
for (elem = define_attr_queue; elem ; elem = elem->next)
if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
{
+ add_define_attr ("ce_enabled", XSTR (elem->data, 3));
+ add_define_attr ("nonce_enabled", XSTR (elem->data, 3));
XEXP (elem->data, 2)
= modify_attr_enabled_ce (XEXP (elem->data, 2));
+ break;
}
+ if (!elem)
+ {
+ add_define_attr ("ce_enabled", "code,alternative");
+ add_define_attr ("nonce_enabled", "code,alternative");
+ }
}
if (enabled_idx == -1)
return;
@@ -3061,3 +3068,44 @@ needs_barrier_p (rtx x)
&& GET_CODE (SET_DEST (x)) == PC
&& GET_CODE (SET_SRC (x)) == LABEL_REF);
}
+
+/* Parse the attribute type for DEFINE_ATTR or DEFINE_ENUM_ATTR definition
+ DEF, which was found at location LOC. */
+
+attr_type
+parse_attr_type (file_location loc, rtx def)
+{
+ const char *type = XSTR (def, 3);
+ if (GET_CODE (XEXP (def, 2)) == CONST)
+ {
+ if (type[0])
+ error_at (loc, "constant attributes cannot have type `%s'", type);
+ return AT_CONST;
+ }
+
+ if (type[0] == 0 || strcmp (type, "insn") == 0)
+ return AT_INSN;
+
+ if (strcmp (type, "code,alternative") == 0)
+ return AT_CODE_ALT;
+
+ error_at (loc, "unknown attribute type `%s'", type);
+ return AT_INSN;
+}
+
+/* Return an English description of TYPE, for error messages. */
+
+const char *
+get_attr_type_name (attr_type type)
+{
+ switch (type)
+ {
+ case AT_CONST:
+ return "constant";
+ case AT_CODE_ALT:
+ return "code-and-alternative";
+ case AT_INSN:
+ return "instruction";
+ }
+ gcc_unreachable ();
+}
@@ -25,6 +25,24 @@ along with GCC; see the file COPYING3. If not see
struct obstack;
extern struct obstack *rtl_obstack;
+/* Classifies the type of a DEFINE_ATTR or DEFINE_ENUM_ATTR.
+ The enum is in increasing order of generality, so that attributes
+ with a higher type can refer to attributes with a lower type, but not
+ vice versa. */
+enum attr_type {
+ /* The attribute depends only on global state; it is not a property
+ of a specific instruction. These attributes have traditionally
+ been called "constant" and are associated with a (const ...) rtx. */
+ AT_CONST,
+
+ /* The attribute depends on an instruction code and alternative number. */
+ AT_CODE_ALT,
+
+ /* The attribute depends on an rtx instruction, and may examine the
+ operands of that instruction. */
+ AT_INSN
+};
+
/* Information about an .md define_* rtx. */
struct md_rtx_info {
/* The rtx itself. */
@@ -135,5 +153,7 @@ extern void compute_test_codes (rtx, file_location, char *);
extern file_location get_file_location (rtx);
extern const char *get_emit_function (rtx);
extern bool needs_barrier_p (rtx);
+attr_type parse_attr_type (file_location, rtx);
+const char *get_attr_type_name (attr_type);
#endif /* GCC_GENSUPPORT_H */
@@ -944,6 +944,7 @@ add_define_attr_for_define_subst (const char *attr_name, vec<rtx> *queue)
XSTR (return_rtx, 0) = xstrdup (attr_name);
XSTR (return_rtx, 1) = xstrdup ("no,yes");
XEXP (return_rtx, 2) = const_str;
+ XSTR (return_rtx, 3) = "code,alternative";
queue->safe_push (return_rtx);
}
@@ -1246,14 +1246,16 @@ DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", RTX_EXT
/* Definition of an insn attribute.
1st operand: name of the attribute
2nd operand: comma-separated list of possible attribute values
- 3rd operand: expression for the default value of the attribute. */
-DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", RTX_EXTRA)
+ 3rd operand: expression for the default value of the attribute.
+ 4th operand: optional type. */
+DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sses", RTX_EXTRA)
/* Definition of an insn attribute that uses an existing enumerated type.
1st operand: name of the attribute
2nd operand: the name of the enumerated type
- 3rd operand: expression for the default value of the attribute. */
-DEF_RTL_EXPR(DEFINE_ENUM_ATTR, "define_enum_attr", "sse", RTX_EXTRA)
+ 3rd operand: expression for the default value of the attribute.
+ 4th operand: optional type. */
+DEF_RTL_EXPR(DEFINE_ENUM_ATTR, "define_enum_attr", "sses", RTX_EXTRA)
/* Marker for the name of an attribute. */
DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)