Commit 8f4fe86c by Richard Sandiford Committed by Richard Sandiford

md.texi (define_enum_attr): Document.

gcc/
	* doc/md.texi (define_enum_attr): Document.
	* rtl.def (DEFINE_ENUM_ATTR): New rtx.
	* read-md.h (lookup_enum_type): Declare.
	* read-md.c (lookup_enum_type): New function.
	* genattr.c (gen_attr, main): Handle DEFINE_ENUM_ATTR.
	* genattrtab.c (attr_desc): Add an enum_name field.
	(evaluate_eq_attr): Take the associated attribute as argument.
	Get the enum prefix from the enum_name field, if defined.
	Use ACONCAT rather than a fixed-length buffer.  Update recursive calls.
	(simplify_test_exp): Pass attr to evaluate_eq_attr.
	(add_attr_value): New function, split out from...
	(gen_attr): ...here.  Handle DEFINE_ENUM_ATTR.
	(write_test_expr): Pass attr to evaluate_eq_attr.
	(write_attr_get): Use the enum_name as the enum tag, if defined.
	(write_attr_valueq): Use the enum_name as a prefix, if defined.
	(find_attr): Initialize enum_name.
	(main): Handle DEFINE_ENUM_ATTR.
	* gensupport.c (process_rtx): Likewise.
	* config/mips/mips.h (mips_tune_attr): Delete.
	* config/mips/mips.md (cpu): Use define_attr_enum.

From-SVN: r160581
parent 24609606
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com> 2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
* doc/md.texi (define_enum_attr): Document.
* rtl.def (DEFINE_ENUM_ATTR): New rtx.
* read-md.h (lookup_enum_type): Declare.
* read-md.c (lookup_enum_type): New function.
* genattr.c (gen_attr, main): Handle DEFINE_ENUM_ATTR.
* genattrtab.c (attr_desc): Add an enum_name field.
(evaluate_eq_attr): Take the associated attribute as argument.
Get the enum prefix from the enum_name field, if defined.
Use ACONCAT rather than a fixed-length buffer. Update recursive calls.
(simplify_test_exp): Pass attr to evaluate_eq_attr.
(add_attr_value): New function, split out from...
(gen_attr): ...here. Handle DEFINE_ENUM_ATTR.
(write_test_expr): Pass attr to evaluate_eq_attr.
(write_attr_get): Use the enum_name as the enum tag, if defined.
(write_attr_valueq): Use the enum_name as a prefix, if defined.
(find_attr): Initialize enum_name.
(main): Handle DEFINE_ENUM_ATTR.
* gensupport.c (process_rtx): Likewise.
* config/mips/mips.h (mips_tune_attr): Delete.
* config/mips/mips.md (cpu): Use define_attr_enum.
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
* doc/md.texi (define_c_enum, define_enum): Document. * doc/md.texi (define_c_enum, define_enum): Document.
* read-md.h (md_constant): Add a parent_enum field. * read-md.h (md_constant): Add a parent_enum field.
(enum_value, enum_type): New structures. (enum_value, enum_type): New structures.
......
...@@ -3035,10 +3035,6 @@ extern enum mips_code_readable_setting mips_code_readable; ...@@ -3035,10 +3035,6 @@ extern enum mips_code_readable_setting mips_code_readable;
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
mips_final_prescan_insn (INSN, OPVEC, NOPERANDS) mips_final_prescan_insn (INSN, OPVEC, NOPERANDS)
/* This is necessary to avoid a warning about comparing different enum
types. */
#define mips_tune_attr ((enum attr_cpu) mips_tune)
/* As on most targets, we want the .eh_frame section to be read-only where /* As on most targets, we want the .eh_frame section to be read-only where
possible. And as on most targets, this means two things: possible. And as on most targets, this means two things:
......
...@@ -508,11 +508,9 @@ ...@@ -508,11 +508,9 @@
(symbol_ref "mips_sync_loop_insns (insn, operands) * 4") (symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
] (const_int 4))) ] (const_int 4)))
;; Attribute describing the processor. This attribute must match exactly ;; Attribute describing the processor.
;; with the processor enumeration above. (define_enum_attr "cpu" "processor"
(define_attr "cpu" (const (symbol_ref "mips_tune")))
"r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr"
(const (symbol_ref "mips_tune_attr")))
;; The type of hardware hazard associated with this instruction. ;; The type of hardware hazard associated with this instruction.
;; DELAY means that the next instruction cannot read the result ;; DELAY means that the next instruction cannot read the result
......
...@@ -6700,9 +6700,46 @@ distances. @xref{Insn Lengths}. ...@@ -6700,9 +6700,46 @@ distances. @xref{Insn Lengths}.
The @code{enabled} attribute can be defined to prevent certain The @code{enabled} attribute can be defined to prevent certain
alternatives of an insn definition from being used during code alternatives of an insn definition from being used during code
generation. @xref{Disable Insn Alternatives}. generation. @xref{Disable Insn Alternatives}.
@end table @end table
@findex define_enum_attr
@anchor{define_enum_attr}
Another way of defining an attribute is to use:
@smallexample
(define_enum_attr "@var{attr}" "@var{enum}" @var{default})
@end smallexample
This works in just the same way as @code{define_attr}, except that
the list of values is taken from a separate enumeration called
@var{enum} (@pxref{define_enum}). This form allows you to use
the same list of values for several attributes without having to
repeat the list each time. For example:
@smallexample
(define_enum "processor" [
model_a
model_b
@dots{}
])
(define_enum_attr "arch" "processor"
(const (symbol_ref "target_arch")))
(define_enum_attr "tune" "processor"
(const (symbol_ref "target_tune")))
@end smallexample
defines the same attributes as:
@smallexample
(define_attr "arch" "model_a,model_b,@dots{}"
(const (symbol_ref "target_arch")))
(define_attr "tune" "model_a,model_b,@dots{}"
(const (symbol_ref "target_tune")))
@end smallexample
but without duplicating the processor list. The second example defines two
separate C enums (@code{attr_arch} and @code{attr_tune}) whereas the first
defines a single C enum (@code{processor}).
@end ifset @end ifset
@ifset INTERNALS @ifset INTERNALS
@node Expressions @node Expressions
...@@ -7961,6 +7998,7 @@ it is convenient to define all synchronization-specific enumeration ...@@ -7961,6 +7998,7 @@ it is convenient to define all synchronization-specific enumeration
values in @file{sync.md} rather than in the main @file{.md} file. values in @file{sync.md} rather than in the main @file{.md} file.
@findex define_enum @findex define_enum
@anchor{define_enum}
Another way of defining an enumeration is to use @code{define_enum}: Another way of defining an enumeration is to use @code{define_enum}:
@smallexample @smallexample
...@@ -7983,7 +8021,11 @@ This directive implies: ...@@ -7983,7 +8021,11 @@ This directive implies:
]) ])
@end smallexample @end smallexample
@findex define_enum_attr
where @var{cvaluei} is the capitalized form of @var{valuei}. where @var{cvaluei} is the capitalized form of @var{valuei}.
However, unlike @code{define_c_enum}, the enumerations defined
by @code{define_enum} can be used in attribute specifications
(@pxref{define_enum_attr}).
@end ifset @end ifset
@ifset INTERNALS @ifset INTERNALS
@node Iterators @node Iterators
......
...@@ -49,27 +49,33 @@ gen_attr (rtx attr) ...@@ -49,27 +49,33 @@ gen_attr (rtx attr)
printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
/* If numeric attribute, don't need to write an enum. */ /* If numeric attribute, don't need to write an enum. */
p = XSTR (attr, 1); if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
if (*p == '\0') printf ("extern enum %s get_attr_%s (%s);\n\n",
printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), XSTR (attr, 1), XSTR (attr, 0), (is_const ? "void" : "rtx"));
(is_const ? "void" : "rtx"));
else else
{ {
printf ("enum attr_%s {", XSTR (attr, 0)); p = XSTR (attr, 1);
if (*p == '\0')
while ((tag = scan_comma_elt (&p)) != 0) printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
(is_const ? "void" : "rtx"));
else
{ {
write_upcase (XSTR (attr, 0)); printf ("enum attr_%s {", XSTR (attr, 0));
putchar ('_');
while (tag != p) while ((tag = scan_comma_elt (&p)) != 0)
putchar (TOUPPER (*tag++)); {
if (*p == ',') write_upcase (XSTR (attr, 0));
fputs (", ", stdout); putchar ('_');
} while (tag != p)
putchar (TOUPPER (*tag++));
if (*p == ',')
fputs (", ", stdout);
}
fputs ("};\n", stdout);
fputs ("};\n", stdout); printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
printf ("extern enum attr_%s get_attr_%s (%s);\n\n", XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); }
} }
/* If `length' attribute, write additional function definitions and define /* If `length' attribute, write additional function definitions and define
...@@ -122,7 +128,8 @@ main (int argc, char **argv) ...@@ -122,7 +128,8 @@ main (int argc, char **argv)
if (desc == NULL) if (desc == NULL)
break; break;
if (GET_CODE (desc) == DEFINE_ATTR) if (GET_CODE (desc) == DEFINE_ATTR
|| GET_CODE (desc) == DEFINE_ENUM_ATTR)
gen_attr (desc); gen_attr (desc);
else if (GET_CODE (desc) == DEFINE_DELAY) else if (GET_CODE (desc) == DEFINE_DELAY)
......
...@@ -171,6 +171,7 @@ struct attr_value ...@@ -171,6 +171,7 @@ struct attr_value
struct attr_desc struct attr_desc
{ {
char *name; /* Name of attribute. */ char *name; /* Name of attribute. */
const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */
struct attr_desc *next; /* Next attribute. */ struct attr_desc *next; /* Next attribute. */
struct attr_value *first_value; /* First value of this attribute. */ struct attr_value *first_value; /* First value of this attribute. */
struct attr_value *default_val; /* Default value for this attribute. */ struct attr_value *default_val; /* Default value for this attribute. */
...@@ -1901,11 +1902,13 @@ make_alternative_compare (int mask) ...@@ -1901,11 +1902,13 @@ make_alternative_compare (int mask)
computation. If a test condition involves an address, we leave the EQ_ATTR computation. If a test condition involves an address, we leave the EQ_ATTR
intact because addresses are only valid for the `length' attribute. intact because addresses are only valid for the `length' attribute.
EXP is the EQ_ATTR expression and VALUE is the value of that attribute EXP is the EQ_ATTR expression and ATTR is the attribute to which
for the insn corresponding to INSN_CODE and INSN_INDEX. */ it refers. VALUE is the value of that attribute for the insn
corresponding to INSN_CODE and INSN_INDEX. */
static rtx static rtx
evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index) evaluate_eq_attr (rtx exp, struct attr_desc *attr, rtx value,
int insn_code, int insn_index)
{ {
rtx orexp, andexp; rtx orexp, andexp;
rtx right; rtx right;
...@@ -1923,16 +1926,12 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index) ...@@ -1923,16 +1926,12 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
case SYMBOL_REF: case SYMBOL_REF:
{ {
char *p; const char *prefix;
char string[256]; char *string, *p;
gcc_assert (GET_CODE (exp) == EQ_ATTR); gcc_assert (GET_CODE (exp) == EQ_ATTR);
gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2 prefix = attr->enum_name ? attr->enum_name : attr->name;
<= 256); string = ACONCAT ((prefix, "_", XSTR (exp, 1), NULL));
strcpy (string, XSTR (exp, 0));
strcat (string, "_");
strcat (string, XSTR (exp, 1));
for (p = string; *p; p++) for (p = string; *p; p++)
*p = TOUPPER (*p); *p = TOUPPER (*p);
...@@ -1966,7 +1965,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index) ...@@ -1966,7 +1965,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
right = insert_right_side (AND, andexp, this_cond, right = insert_right_side (AND, andexp, this_cond,
insn_code, insn_index); insn_code, insn_index);
right = insert_right_side (AND, right, right = insert_right_side (AND, right,
evaluate_eq_attr (exp, evaluate_eq_attr (exp, attr,
XVECEXP (value, 0, XVECEXP (value, 0,
i + 1), i + 1),
insn_code, insn_index), insn_code, insn_index),
...@@ -1982,7 +1981,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index) ...@@ -1982,7 +1981,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
/* Handle the default case. */ /* Handle the default case. */
right = insert_right_side (AND, andexp, right = insert_right_side (AND, andexp,
evaluate_eq_attr (exp, XEXP (value, 1), evaluate_eq_attr (exp, attr, XEXP (value, 1),
insn_code, insn_index), insn_code, insn_index),
insn_code, insn_index); insn_code, insn_index);
newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index); newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
...@@ -2732,7 +2731,8 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index) ...@@ -2732,7 +2731,8 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
if (av) if (av)
{ {
got_av: got_av:
x = evaluate_eq_attr (exp, av->value, insn_code, insn_index); x = evaluate_eq_attr (exp, attr, av->value,
insn_code, insn_index);
x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index); x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
if (attr_rtx_cost(x) < 20) if (attr_rtx_cost(x) < 20)
return x; return x;
...@@ -2900,13 +2900,30 @@ clear_struct_flag (rtx x) ...@@ -2900,13 +2900,30 @@ clear_struct_flag (rtx x)
} }
} }
/* Create table entries for DEFINE_ATTR. */ /* Add attribute value NAME to the beginning of ATTR's list. */
static void
add_attr_value (struct attr_desc *attr, const char *name)
{
struct attr_value *av;
av = oballoc (struct attr_value);
av->value = attr_rtx (CONST_STRING, name);
av->next = attr->first_value;
attr->first_value = av;
av->first_insn = NULL;
av->num_insns = 0;
av->has_asm_insn = 0;
}
/* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR. */
static void static void
gen_attr (rtx exp, int lineno) gen_attr (rtx exp, int lineno)
{ {
struct enum_type *et;
struct enum_value *ev;
struct attr_desc *attr; struct attr_desc *attr;
struct attr_value *av;
const char *name_ptr; const char *name_ptr;
char *p; char *p;
...@@ -2922,21 +2939,23 @@ gen_attr (rtx exp, int lineno) ...@@ -2922,21 +2939,23 @@ gen_attr (rtx exp, int lineno)
} }
attr->lineno = lineno; attr->lineno = lineno;
if (*XSTR (exp, 1) == '\0') if (GET_CODE (exp) == DEFINE_ENUM_ATTR)
{
attr->enum_name = XSTR (exp, 1);
et = lookup_enum_type (XSTR (exp, 1));
if (!et || !et->md_p)
error_with_line (lineno, "No define_enum called `%s' defined",
attr->name);
for (ev = et->values; ev; ev = ev->next)
add_attr_value (attr, ev->name);
}
else if (*XSTR (exp, 1) == '\0')
attr->is_numeric = 1; attr->is_numeric = 1;
else else
{ {
name_ptr = XSTR (exp, 1); name_ptr = XSTR (exp, 1);
while ((p = next_comma_elt (&name_ptr)) != NULL) while ((p = next_comma_elt (&name_ptr)) != NULL)
{ add_attr_value (attr, p);
av = oballoc (struct attr_value);
av->value = attr_rtx (CONST_STRING, p);
av->next = attr->first_value;
attr->first_value = av;
av->first_insn = NULL;
av->num_insns = 0;
av->has_asm_insn = 0;
}
} }
if (GET_CODE (XEXP (exp, 2)) == CONST) if (GET_CODE (XEXP (exp, 2)) == CONST)
...@@ -3319,8 +3338,8 @@ write_test_expr (rtx exp, int flags) ...@@ -3319,8 +3338,8 @@ write_test_expr (rtx exp, int flags)
/* Now is the time to expand the value of a constant attribute. */ /* Now is the time to expand the value of a constant attribute. */
if (attr->is_const) if (attr->is_const)
{ {
write_test_expr (evaluate_eq_attr (exp, attr->default_val->value, write_test_expr (evaluate_eq_attr (exp, attr,
-2, -2), attr->default_val->value, -2, -2),
flags); flags);
} }
else else
...@@ -3612,7 +3631,9 @@ write_attr_get (struct attr_desc *attr) ...@@ -3612,7 +3631,9 @@ write_attr_get (struct attr_desc *attr)
/* Write out start of function, then all values with explicit `case' lines, /* Write out start of function, then all values with explicit `case' lines,
then a `default', then the value with the most uses. */ then a `default', then the value with the most uses. */
if (!attr->is_numeric) if (attr->enum_name)
printf ("enum %s\n", attr->enum_name);
else if (!attr->is_numeric)
printf ("enum attr_%s\n", attr->name); printf ("enum attr_%s\n", attr->name);
else else
printf ("int\n"); printf ("int\n");
...@@ -3869,7 +3890,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s) ...@@ -3869,7 +3890,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s)
} }
else else
{ {
write_upcase (attr->name); write_upcase (attr->enum_name ? attr->enum_name : attr->name);
printf ("_"); printf ("_");
write_upcase (s); write_upcase (s);
} }
...@@ -4133,6 +4154,7 @@ find_attr (const char **name_p, int create) ...@@ -4133,6 +4154,7 @@ find_attr (const char **name_p, int create)
attr = oballoc (struct attr_desc); attr = oballoc (struct attr_desc);
attr->name = DEF_ATTR_STRING (name); attr->name = DEF_ATTR_STRING (name);
attr->enum_name = 0;
attr->first_value = attr->default_val = NULL; attr->first_value = attr->default_val = NULL;
attr->is_numeric = attr->is_const = attr->is_special = 0; attr->is_numeric = attr->is_const = attr->is_special = 0;
attr->next = attrs[index]; attr->next = attrs[index];
...@@ -4459,6 +4481,7 @@ from the machine description file `md'. */\n\n"); ...@@ -4459,6 +4481,7 @@ from the machine description file `md'. */\n\n");
break; break;
case DEFINE_ATTR: case DEFINE_ATTR:
case DEFINE_ENUM_ATTR:
gen_attr (desc, lineno); gen_attr (desc, lineno);
break; break;
......
...@@ -173,6 +173,7 @@ process_rtx (rtx desc, int lineno) ...@@ -173,6 +173,7 @@ process_rtx (rtx desc, int lineno)
break; break;
case DEFINE_ATTR: case DEFINE_ATTR:
case DEFINE_ENUM_ATTR:
queue_pattern (desc, &define_attr_tail, read_md_filename, lineno); queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
break; break;
......
...@@ -847,6 +847,14 @@ handle_enum (int lineno, bool md_p) ...@@ -847,6 +847,14 @@ handle_enum (int lineno, bool md_p)
} }
} }
/* Try to find the definition of the given enum. Return null on failure. */
struct enum_type *
lookup_enum_type (const char *name)
{
return (struct enum_type *) htab_find (enum_types, &name);
}
/* For every enum definition, call CALLBACK with two arguments: /* For every enum definition, call CALLBACK with two arguments:
a pointer to the constant definition and INFO. Stop when CALLBACK a pointer to the constant definition and INFO. Stop when CALLBACK
returns zero. */ returns zero. */
......
...@@ -135,5 +135,6 @@ extern const char *scan_comma_elt (const char **); ...@@ -135,5 +135,6 @@ extern const char *scan_comma_elt (const char **);
extern void upcase_string (char *); extern void upcase_string (char *);
extern void traverse_md_constants (htab_trav, void *); extern void traverse_md_constants (htab_trav, void *);
extern void traverse_enum_types (htab_trav, void *); extern void traverse_enum_types (htab_trav, void *);
extern struct enum_type *lookup_enum_type (const char *);
extern bool read_md_files (int, char **, bool (*) (const char *), extern bool read_md_files (int, char **, bool (*) (const char *),
directive_handler_t); directive_handler_t);
...@@ -1198,6 +1198,12 @@ DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", RTX_EXT ...@@ -1198,6 +1198,12 @@ DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", RTX_EXT
3rd operand: expression for the default value of the attribute. */ 3rd operand: expression for the default value of the attribute. */
DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", 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)
/* Marker for the name of an attribute. */ /* Marker for the name of an attribute. */
DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA) DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)
......
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