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
This commit is contained in:
parent
24609606bd
commit
8f4fe86cd1
@ -1,3 +1,26 @@
|
||||
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.
|
||||
|
@ -3035,10 +3035,6 @@ extern enum mips_code_readable_setting mips_code_readable;
|
||||
#define 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
|
||||
possible. And as on most targets, this means two things:
|
||||
|
||||
|
@ -508,11 +508,9 @@
|
||||
(symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
|
||||
] (const_int 4)))
|
||||
|
||||
;; Attribute describing the processor. This attribute must match exactly
|
||||
;; with the processor enumeration above.
|
||||
(define_attr "cpu"
|
||||
"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")))
|
||||
;; Attribute describing the processor.
|
||||
(define_enum_attr "cpu" "processor"
|
||||
(const (symbol_ref "mips_tune")))
|
||||
|
||||
;; The type of hardware hazard associated with this instruction.
|
||||
;; DELAY means that the next instruction cannot read the result
|
||||
|
@ -6700,9 +6700,46 @@ distances. @xref{Insn Lengths}.
|
||||
The @code{enabled} attribute can be defined to prevent certain
|
||||
alternatives of an insn definition from being used during code
|
||||
generation. @xref{Disable Insn Alternatives}.
|
||||
|
||||
@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
|
||||
@ifset INTERNALS
|
||||
@node Expressions
|
||||
@ -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.
|
||||
|
||||
@findex define_enum
|
||||
@anchor{define_enum}
|
||||
Another way of defining an enumeration is to use @code{define_enum}:
|
||||
|
||||
@smallexample
|
||||
@ -7983,7 +8021,11 @@ This directive implies:
|
||||
])
|
||||
@end smallexample
|
||||
|
||||
@findex define_enum_attr
|
||||
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
|
||||
@ifset INTERNALS
|
||||
@node Iterators
|
||||
|
@ -49,27 +49,33 @@ gen_attr (rtx attr)
|
||||
printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
|
||||
|
||||
/* If numeric attribute, don't need to write an enum. */
|
||||
p = XSTR (attr, 1);
|
||||
if (*p == '\0')
|
||||
printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
|
||||
(is_const ? "void" : "rtx"));
|
||||
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"));
|
||||
else
|
||||
{
|
||||
printf ("enum attr_%s {", XSTR (attr, 0));
|
||||
|
||||
while ((tag = scan_comma_elt (&p)) != 0)
|
||||
p = XSTR (attr, 1);
|
||||
if (*p == '\0')
|
||||
printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
|
||||
(is_const ? "void" : "rtx"));
|
||||
else
|
||||
{
|
||||
write_upcase (XSTR (attr, 0));
|
||||
putchar ('_');
|
||||
while (tag != p)
|
||||
putchar (TOUPPER (*tag++));
|
||||
if (*p == ',')
|
||||
fputs (", ", stdout);
|
||||
}
|
||||
printf ("enum attr_%s {", XSTR (attr, 0));
|
||||
|
||||
fputs ("};\n", stdout);
|
||||
printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
|
||||
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
|
||||
while ((tag = scan_comma_elt (&p)) != 0)
|
||||
{
|
||||
write_upcase (XSTR (attr, 0));
|
||||
putchar ('_');
|
||||
while (tag != p)
|
||||
putchar (TOUPPER (*tag++));
|
||||
if (*p == ',')
|
||||
fputs (", ", stdout);
|
||||
}
|
||||
fputs ("};\n", stdout);
|
||||
|
||||
printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
|
||||
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
|
||||
}
|
||||
}
|
||||
|
||||
/* If `length' attribute, write additional function definitions and define
|
||||
@ -122,7 +128,8 @@ main (int argc, char **argv)
|
||||
if (desc == NULL)
|
||||
break;
|
||||
|
||||
if (GET_CODE (desc) == DEFINE_ATTR)
|
||||
if (GET_CODE (desc) == DEFINE_ATTR
|
||||
|| GET_CODE (desc) == DEFINE_ENUM_ATTR)
|
||||
gen_attr (desc);
|
||||
|
||||
else if (GET_CODE (desc) == DEFINE_DELAY)
|
||||
|
@ -171,6 +171,7 @@ struct attr_value
|
||||
struct attr_desc
|
||||
{
|
||||
char *name; /* Name of attribute. */
|
||||
const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */
|
||||
struct attr_desc *next; /* Next attribute. */
|
||||
struct attr_value *first_value; /* First value of this attribute. */
|
||||
struct attr_value *default_val; /* Default value for this attribute. */
|
||||
@ -1901,11 +1902,13 @@ make_alternative_compare (int mask)
|
||||
computation. If a test condition involves an address, we leave the EQ_ATTR
|
||||
intact because addresses are only valid for the `length' attribute.
|
||||
|
||||
EXP is the EQ_ATTR expression and VALUE is the value of that attribute
|
||||
for the insn corresponding to INSN_CODE and INSN_INDEX. */
|
||||
EXP is the EQ_ATTR expression and ATTR is the attribute to which
|
||||
it refers. VALUE is the value of that attribute for the insn
|
||||
corresponding to INSN_CODE and INSN_INDEX. */
|
||||
|
||||
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 right;
|
||||
@ -1923,16 +1926,12 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
|
||||
|
||||
case SYMBOL_REF:
|
||||
{
|
||||
char *p;
|
||||
char string[256];
|
||||
const char *prefix;
|
||||
char *string, *p;
|
||||
|
||||
gcc_assert (GET_CODE (exp) == EQ_ATTR);
|
||||
gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2
|
||||
<= 256);
|
||||
|
||||
strcpy (string, XSTR (exp, 0));
|
||||
strcat (string, "_");
|
||||
strcat (string, XSTR (exp, 1));
|
||||
prefix = attr->enum_name ? attr->enum_name : attr->name;
|
||||
string = ACONCAT ((prefix, "_", XSTR (exp, 1), NULL));
|
||||
for (p = string; *p; p++)
|
||||
*p = TOUPPER (*p);
|
||||
|
||||
@ -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,
|
||||
insn_code, insn_index);
|
||||
right = insert_right_side (AND, right,
|
||||
evaluate_eq_attr (exp,
|
||||
evaluate_eq_attr (exp, attr,
|
||||
XVECEXP (value, 0,
|
||||
i + 1),
|
||||
insn_code, insn_index),
|
||||
@ -1982,7 +1981,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
|
||||
|
||||
/* Handle the default case. */
|
||||
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);
|
||||
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)
|
||||
if (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);
|
||||
if (attr_rtx_cost(x) < 20)
|
||||
return 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
|
||||
gen_attr (rtx exp, int lineno)
|
||||
{
|
||||
struct enum_type *et;
|
||||
struct enum_value *ev;
|
||||
struct attr_desc *attr;
|
||||
struct attr_value *av;
|
||||
const char *name_ptr;
|
||||
char *p;
|
||||
|
||||
@ -2922,21 +2939,23 @@ gen_attr (rtx exp, int 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;
|
||||
else
|
||||
{
|
||||
name_ptr = XSTR (exp, 1);
|
||||
while ((p = next_comma_elt (&name_ptr)) != NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
add_attr_value (attr, p);
|
||||
}
|
||||
|
||||
if (GET_CODE (XEXP (exp, 2)) == CONST)
|
||||
@ -3319,8 +3338,8 @@ write_test_expr (rtx exp, int flags)
|
||||
/* Now is the time to expand the value of a constant attribute. */
|
||||
if (attr->is_const)
|
||||
{
|
||||
write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
|
||||
-2, -2),
|
||||
write_test_expr (evaluate_eq_attr (exp, attr,
|
||||
attr->default_val->value, -2, -2),
|
||||
flags);
|
||||
}
|
||||
else
|
||||
@ -3612,7 +3631,9 @@ write_attr_get (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->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);
|
||||
else
|
||||
printf ("int\n");
|
||||
@ -3869,7 +3890,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
write_upcase (attr->name);
|
||||
write_upcase (attr->enum_name ? attr->enum_name : attr->name);
|
||||
printf ("_");
|
||||
write_upcase (s);
|
||||
}
|
||||
@ -4133,6 +4154,7 @@ find_attr (const char **name_p, int create)
|
||||
|
||||
attr = oballoc (struct attr_desc);
|
||||
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];
|
||||
@ -4459,6 +4481,7 @@ from the machine description file `md'. */\n\n");
|
||||
break;
|
||||
|
||||
case DEFINE_ATTR:
|
||||
case DEFINE_ENUM_ATTR:
|
||||
gen_attr (desc, lineno);
|
||||
break;
|
||||
|
||||
|
@ -173,6 +173,7 @@ process_rtx (rtx desc, int lineno)
|
||||
break;
|
||||
|
||||
case DEFINE_ATTR:
|
||||
case DEFINE_ENUM_ATTR:
|
||||
queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
|
||||
break;
|
||||
|
||||
|
@ -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:
|
||||
a pointer to the constant definition and INFO. Stop when CALLBACK
|
||||
returns zero. */
|
||||
|
@ -135,5 +135,6 @@ extern const char *scan_comma_elt (const char **);
|
||||
extern void upcase_string (char *);
|
||||
extern void traverse_md_constants (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 *),
|
||||
directive_handler_t);
|
||||
|
@ -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. */
|
||||
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. */
|
||||
DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user