summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/config/mips/mips.h4
-rw-r--r--gcc/config/mips/mips.md8
-rw-r--r--gcc/doc/md.texi44
-rw-r--r--gcc/genattr.c43
-rw-r--r--gcc/genattrtab.c83
-rw-r--r--gcc/gensupport.c1
-rw-r--r--gcc/read-md.c8
-rw-r--r--gcc/read-md.h1
-rw-r--r--gcc/rtl.def6
10 files changed, 163 insertions, 58 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f4630c7c410..77453d9ba5e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,28 @@
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.
* read-md.h (md_constant): Add a parent_enum field.
(enum_value, enum_type): New structures.
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 4d791023f14..4026bd73714 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -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:
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 0f287755891..0ad21bd1783 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -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
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 990863acccc..d0aa8646ede 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -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
diff --git a/gcc/genattr.c b/gcc/genattr.c
index 84399b8a677..e4609ca4174 100644
--- a/gcc/genattr.c
+++ b/gcc/genattr.c
@@ -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));
+
+ 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);
- fputs ("};\n", stdout);
- printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
- XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
+ 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)
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index ac5c75e45d0..9fe1c5caa7c 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -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;
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 1389658609c..206e96b7c61 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -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;
diff --git a/gcc/read-md.c b/gcc/read-md.c
index 90707b356d3..9c622912b3a 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -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. */
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 94a5fbbc241..abcca51ac72 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -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);
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 8464d32e7f9..c4a3646afea 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -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)