gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jun 2010 20:24:17 +0000 (20:24 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jun 2010 20:24:17 +0000 (20:24 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@160581 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/doc/md.texi
gcc/genattr.c
gcc/genattrtab.c
gcc/gensupport.c
gcc/read-md.c
gcc/read-md.h
gcc/rtl.def

index f4630c7..77453d9 100644 (file)
@@ -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.
index 4d79102..4026bd7 100644 (file)
@@ -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:
 
index 0f28775..0ad21bd 100644 (file)
          (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
index 990863a..d0aa864 100644 (file)
@@ -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
index 84399b8..e4609ca 100644 (file)
@@ -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)
index ac5c75e..9fe1c5c 100644 (file)
@@ -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;
 
index 1389658..206e96b 100644 (file)
@@ -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;
 
index 90707b3..9c62291 100644 (file)
@@ -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.  */
index 94a5fbb..abcca51 100644 (file)
@@ -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);
index 8464d32..c4a3646 100644 (file)
@@ -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)