re PR other/29442 (insn-attrtab has grown too large)
authorSteven Bosscher <steven@gcc.gnu.org>
Fri, 4 May 2012 20:04:47 +0000 (20:04 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Fri, 4 May 2012 20:04:47 +0000 (20:04 +0000)
PR other/29442
* read-md.c (fprint_md_ptr_loc, fprint_c_condition): New functions.
(print_md_ptr_loc, print_c_condition): Use them.
* read-md.h (fprint_md_ptr_loc, fprint_c_condition): New prototypes.
* genattrtab.c (attr_file_name, dfa_file_name, latency_file_name,
attr_file, dfa_file, latency_file): New global variables.
(write_attr_valueq, write_attr_set, write_attr_case, write_attr_value,
write_upcase, write_indent, write_length_unit_log, write_test_expr,
write_attr_get, write_insn_cases, write_eligible_delay,
write_const_num_delay_slots): Accept FILE pointer and toss it around.
Update all callers.
(write_header, open_outfile, handle_arg): New funcions.
(make_automaton_attrs): Write prototypes as extern to the output
files.
(main): Use init_rtx_reader_args_cb with handle_arg to take 3 file
names from the command line.  Open the output files and write out
internal functions for DFA functions to dfa_file_name, insn latency
functions to latency_file_name, and everything else to attr_file.
* Makefile.in (OBJS): Add insn-dfatab.o and insn-latencytab.o.
(BACKEND): Build libbackend first.
(MOSTLYCLEANFILES): Add insn-dfatab.c and insn-latencytab.c.
(.PRECIOUS): Likewise.
(insn-dfatab.o): New rule.
(insn-latencytab.o): New rule.
(simple_rtl_generated_c): Do not include insn-attrtab.c.
(s-attrtab): New rule.

From-SVN: r187181

gcc/ChangeLog
gcc/Makefile.in
gcc/genattrtab.c
gcc/read-md.c
gcc/read-md.h

index e04dbfb..8dafc82 100644 (file)
@@ -1,5 +1,34 @@
 2012-05-04  Steven Bosscher  <steven@gcc.gnu.org>
 
+       PR other/29442
+       * read-md.c (fprint_md_ptr_loc, fprint_c_condition): New functions.
+       (print_md_ptr_loc, print_c_condition): Use them.
+       * read-md.h (fprint_md_ptr_loc, fprint_c_condition): New prototypes.
+       * genattrtab.c (attr_file_name, dfa_file_name, latency_file_name,
+       attr_file, dfa_file, latency_file): New global variables.
+       (write_attr_valueq, write_attr_set, write_attr_case, write_attr_value,
+       write_upcase, write_indent, write_length_unit_log, write_test_expr,
+       write_attr_get, write_insn_cases, write_eligible_delay,
+       write_const_num_delay_slots): Accept FILE pointer and toss it around.
+       Update all callers.
+       (write_header, open_outfile, handle_arg): New funcions.
+       (make_automaton_attrs): Write prototypes as extern to the output
+       files.
+       (main): Use init_rtx_reader_args_cb with handle_arg to take 3 file
+       names from the command line.  Open the output files and write out
+       internal functions for DFA functions to dfa_file_name, insn latency
+       functions to latency_file_name, and everything else to attr_file.
+       * Makefile.in (OBJS): Add insn-dfatab.o and insn-latencytab.o.
+       (BACKEND): Build libbackend first.
+       (MOSTLYCLEANFILES): Add insn-dfatab.c and insn-latencytab.c.
+       (.PRECIOUS): Likewise.
+       (insn-dfatab.o): New rule.
+       (insn-latencytab.o): New rule.
+       (simple_rtl_generated_c): Do not include insn-attrtab.c.
+       (s-attrtab): New rule.
+
+2012-05-04  Steven Bosscher  <steven@gcc.gnu.org>
+
        * rtl.def (ATTR_FLAG): Remove probability indicating flags.
        * genattr.c (main): Remove ATTR_FLAG_likely, ATTR_FLAG_unlikely,
        ATTR_FLAG_very_likely, and ATTR_FLAG_very_unlikely.
index d35d110..ec27f88 100644 (file)
@@ -1143,8 +1143,10 @@ C_OBJS = c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
 OBJS = \
        insn-attrtab.o \
        insn-automata.o \
+       insn-dfatab.o \
        insn-emit.o \
        insn-extract.o \
+       insn-latencytab.o \
        insn-modes.o \
        insn-opinit.o \
        insn-output.o \
@@ -1469,13 +1471,13 @@ ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
 # compilation or not.
 ALL_HOST_OBJS = $(ALL_HOST_FRONTEND_OBJS) $(ALL_HOST_BACKEND_OBJS)
 
-BACKEND = main.o @TREEBROWSER@ libbackend.a libcommon-target.a libcommon.a \
+BACKEND = libbackend.a main.o @TREEBROWSER@ libcommon-target.a libcommon.a \
        $(CPPLIB) $(LIBDECNUMBER)
 
 MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
  insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
- insn-attr.h insn-attr-common.h insn-attrtab.c insn-opinit.c \
- insn-preds.c insn-constants.h \
+ insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
+ insn-latencytab.c insn-opinit.c insn-preds.c insn-constants.h \
  tm-preds.h tm-constrs.h checksum-options \
  tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
@@ -3460,7 +3462,8 @@ $(common_out_object_file): $(common_out_file) $(CONFIG_H) $(SYSTEM_H) \
 
 .PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
   insn-emit.c insn-recog.c insn-extract.c insn-output.c insn-peep.c \
-  insn-attr.h insn-attr-common.h insn-attrtab.c insn-preds.c
+  insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
+  insn-latencytab.c insn-preds.c
 
 # Dependencies for the md file.  The first time through, we just assume
 # the md file itself and the generated dependency file (in order to get
@@ -3479,7 +3482,11 @@ insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h      \
   insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
 insn-automata.o : insn-automata.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
   $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H)                   \
-  insn-config.h toplev.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H) $(EMIT_RTL_H)
+  insn-config.h toplev.h $(DIAGNOSTIC_CORE_H) $(RECOG_H)               \
+  $(TM_P_H) $(FLAGS_H) $(EMIT_RTL_H)
+insn-dfatab.o : insn-dfatab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h      \
+  $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H)                   \
+  insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
 insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)  \
   $(RTL_H) $(TM_P_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H)               \
   dfp.h $(FLAGS_H) output.h insn-config.h hard-reg-set.h $(RECOG_H)    \
@@ -3488,6 +3495,9 @@ insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)     \
 insn-enums.o : insn-enums.c $(CONFIG_H) $(SYSTEM_H) insn-constants.h
 insn-extract.o : insn-extract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h    \
   $(TM_H) $(RTL_H) $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H)
+insn-latencytab.o : insn-latencytab.c $(CONFIG_H) $(SYSTEM_H)          \
+  coretypes.h $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H)       \
+  insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
 insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h        $(TM_H) \
   $(MACHMODE_H)
 insn-opinit.o : insn-opinit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h      \
@@ -3520,7 +3530,7 @@ insn-recog.o : insn-recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h           \
 simple_rtl_generated_h = insn-attr.h insn-attr-common.h insn-codes.h \
                          insn-config.h insn-flags.h
 
-simple_rtl_generated_c = insn-attrtab.c insn-automata.c insn-emit.c \
+simple_rtl_generated_c = insn-automata.c insn-emit.c \
                          insn-extract.c insn-opinit.c insn-output.c \
                          insn-peep.c insn-recog.c
 
@@ -3557,6 +3567,17 @@ s-check : build/gencheck$(build_exeext)
        $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
        $(STAMP) s-check
 
+# genattrtab produces three files: tmp-{attrtab.c,dfatab.c,latencytab.c}
+insn-attrtab.c insn-dfatab.c insn-latencytab.c: s-attrtab ; @true
+s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
+  insn-conditions.md
+       $(RUN_GEN) build/genattrtab$(build_exeext) $(md_file) insn-conditions.md \
+               -Atmp-attrtab.c -Dtmp-dfatab.c -Ltmp-latencytab.c
+       $(SHELL) $(srcdir)/../move-if-change tmp-attrtab.c    insn-attrtab.c
+       $(SHELL) $(srcdir)/../move-if-change tmp-dfatab.c     insn-dfatab.c
+       $(SHELL) $(srcdir)/../move-if-change tmp-latencytab.c insn-latencytab.c
+       $(STAMP) s-attrtab
+
 # gencondmd doesn't use the standard naming convention.
 build/gencondmd.c: s-conditions; @true
 s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
index bfbe3e8..60aa59c 100644 (file)
@@ -275,16 +275,17 @@ static rtx copy_rtx_unchanging       (rtx);
 static bool attr_alt_subset_p      (rtx, rtx);
 static bool attr_alt_subset_of_compl_p (rtx, rtx);
 static void clear_struct_flag      (rtx);
-static void write_attr_valueq     (struct attr_desc *, const char *);
+static void write_attr_valueq     (FILE *, struct attr_desc *, const char *);
 static struct attr_value *find_most_used  (struct attr_desc *);
-static void write_attr_set        (struct attr_desc *, int, rtx,
+static void write_attr_set        (FILE *, struct attr_desc *, int, rtx,
                                    const char *, const char *, rtx,
                                    int, int, unsigned int);
-static void write_attr_case       (struct attr_desc *, struct attr_value *,
+static void write_attr_case       (FILE *, struct attr_desc *,
+                                   struct attr_value *,
                                    int, const char *, const char *, int, rtx);
-static void write_attr_value      (struct attr_desc *, rtx);
-static void write_upcase          (const char *);
-static void write_indent          (int);
+static void write_attr_value      (FILE *, struct attr_desc *, rtx);
+static void write_upcase          (FILE *, const char *);
+static void write_indent          (FILE *, int);
 static rtx identity_fn            (rtx);
 static rtx zero_fn                (rtx);
 static rtx one_fn                 (rtx);
@@ -294,6 +295,23 @@ static rtx min_fn             (rtx);
 #define oballoc(T) XOBNEW (hash_obstack, T)
 #define oballocvec(T, N) XOBNEWVEC (hash_obstack, T, (N))
 
+/* This gen* file is unique, in that it writes out multiple files.
+
+   Before GCC 4.8, insn-attrtab.c was written out containing many large
+   functions and tables.  This made insn-attrtab.c _the_ bottle-neck in
+   a parallel build, and even made it impossible to build GCC on machines
+   with relatively small RAM space (PR other/29442).  Therefore, the
+   atrribute functions/tables are now written out to three separate
+   files: all "*insn_default_latency" functions go to LATENCY_FILE_NAME,
+   all "*internal_dfa_insn_code" functions go to DFA_FILE_NAME, and the
+   rest goes to ATTR_FILE_NAME.  */
+
+static const char *attr_file_name = NULL;
+static const char *dfa_file_name = NULL;
+static const char *latency_file_name = NULL;
+
+static FILE *attr_file, *dfa_file, *latency_file;
+
 /* Hash table for sharing RTL and strings.  */
 
 /* Each hash table slot is a bucket containing a chain of these structures.
@@ -1610,7 +1628,7 @@ min_fn (rtx exp)
 }
 
 static void
-write_length_unit_log (void)
+write_length_unit_log (FILE *outf)
 {
   struct attr_desc *length_attr = find_attr (&length_str, 0);
   struct attr_value *av;
@@ -1633,7 +1651,7 @@ write_length_unit_log (void)
       for (length_unit_log = 0; length_or & 1; length_or >>= 1)
        length_unit_log++;
     }
-  printf ("EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
+  fprintf (outf, "EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
 }
 
 /* Take a COND expression and see if any of the conditions in it can be
@@ -3247,7 +3265,7 @@ find_attrs_to_cache (rtx exp, bool create)
     }
 }
 
-/* Given a piece of RTX, print a C expression to test its truth value.
+/* Given a piece of RTX, print a C expression to test its truth value to OUTF.
    We use AND and IOR both for logical and bit-wise operations, so
    interpret them as logical unless they are inside a comparison expression.  */
 
@@ -3265,7 +3283,7 @@ find_attrs_to_cache (rtx exp, bool create)
 #define FLG_OUTSIDE_AND                8
 
 static unsigned int
-write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
+write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags)
 {
   int comparison_operator = 0;
   RTX_CODE code;
@@ -3274,14 +3292,14 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
   /* In order not to worry about operator precedence, surround our part of
      the expression with parentheses.  */
 
-  printf ("(");
+  fprintf (outf, "(");
   code = GET_CODE (exp);
   switch (code)
     {
     /* Binary operators.  */
     case GEU: case GTU:
     case LEU: case LTU:
-      printf ("(unsigned) ");
+      fprintf (outf, "(unsigned) ");
       /* Fall through.  */
 
     case EQ: case NE:
@@ -3295,7 +3313,7 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
       if ((code != AND && code != IOR) || (flags & FLG_BITWISE))
        {
          flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND);
-         write_test_expr (XEXP (exp, 0), attrs_cached,
+         write_test_expr (outf, XEXP (exp, 0), attrs_cached,
                           flags | comparison_operator);
        }
       else
@@ -3307,78 +3325,78 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
              || (GET_CODE (XEXP (exp, 0)) == NOT
                  && GET_CODE (XEXP (XEXP (exp, 0), 0)) == EQ_ATTR))
            attrs_cached
-             = write_test_expr (XEXP (exp, 0), attrs_cached, flags);
+             = write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
          else
-           write_test_expr (XEXP (exp, 0), attrs_cached, flags);
+           write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
        }
       switch (code)
        {
        case EQ:
-         printf (" == ");
+         fprintf (outf, " == ");
          break;
        case NE:
-         printf (" != ");
+         fprintf (outf, " != ");
          break;
        case GE:
-         printf (" >= ");
+         fprintf (outf, " >= ");
          break;
        case GT:
-         printf (" > ");
+         fprintf (outf, " > ");
          break;
        case GEU:
-         printf (" >= (unsigned) ");
+         fprintf (outf, " >= (unsigned) ");
          break;
        case GTU:
-         printf (" > (unsigned) ");
+         fprintf (outf, " > (unsigned) ");
          break;
        case LE:
-         printf (" <= ");
+         fprintf (outf, " <= ");
          break;
        case LT:
-         printf (" < ");
+         fprintf (outf, " < ");
          break;
        case LEU:
-         printf (" <= (unsigned) ");
+         fprintf (outf, " <= (unsigned) ");
          break;
        case LTU:
-         printf (" < (unsigned) ");
+         fprintf (outf, " < (unsigned) ");
          break;
        case PLUS:
-         printf (" + ");
+         fprintf (outf, " + ");
          break;
        case MINUS:
-         printf (" - ");
+         fprintf (outf, " - ");
          break;
        case MULT:
-         printf (" * ");
+         fprintf (outf, " * ");
          break;
        case DIV:
-         printf (" / ");
+         fprintf (outf, " / ");
          break;
        case MOD:
-         printf (" %% ");
+         fprintf (outf, " %% ");
          break;
        case AND:
          if (flags & FLG_BITWISE)
-           printf (" & ");
+           fprintf (outf, " & ");
          else
-           printf (" && ");
+           fprintf (outf, " && ");
          break;
        case IOR:
          if (flags & FLG_BITWISE)
-           printf (" | ");
+           fprintf (outf, " | ");
          else
-           printf (" || ");
+           fprintf (outf, " || ");
          break;
        case XOR:
-         printf (" ^ ");
+         fprintf (outf, " ^ ");
          break;
        case ASHIFT:
-         printf (" << ");
+         fprintf (outf, " << ");
          break;
        case LSHIFTRT:
        case ASHIFTRT:
-         printf (" >> ");
+         fprintf (outf, " >> ");
          break;
        default:
          gcc_unreachable ();
@@ -3409,9 +3427,9 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
              || (GET_CODE (XEXP (exp, 1)) == NOT
                  && GET_CODE (XEXP (XEXP (exp, 1), 0)) == EQ_ATTR)))
        attrs_cached
-         = write_test_expr (XEXP (exp, 1), attrs_cached, flags);
+         = write_test_expr (outf, XEXP (exp, 1), attrs_cached, flags);
       else
-       write_test_expr (XEXP (exp, 1), attrs_cached,
+       write_test_expr (outf, XEXP (exp, 1), attrs_cached,
                         flags | comparison_operator);
       break;
 
@@ -3421,12 +3439,14 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
        {
          if (XSTR (XEXP (exp, 0), 0) == alternative_name)
            {
-             printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
+             fprintf (outf, "which_alternative != %s",
+                      XSTR (XEXP (exp, 0), 1));
              break;
            }
 
-         printf ("! ");
-         attrs_cached = write_test_expr (XEXP (exp, 0), attrs_cached, flags);
+         fprintf (outf, "! ");
+         attrs_cached =
+           write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
          break;
        }
 
@@ -3438,22 +3458,22 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
        {
        case NOT:
          if (flags & FLG_BITWISE)
-           printf ("~ ");
+           fprintf (outf, "~ ");
          else
-           printf ("! ");
+           fprintf (outf, "! ");
          break;
        case ABS:
-         printf ("abs ");
+         fprintf (outf, "abs ");
          break;
        case NEG:
-         printf ("-");
+         fprintf (outf, "-");
          break;
        default:
          gcc_unreachable ();
        }
 
       flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND);
-      write_test_expr (XEXP (exp, 0), attrs_cached, flags);
+      write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
       break;
 
     case EQ_ATTR_ALT:
@@ -3491,13 +3511,13 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
              if (!(set & 1))
                bit++;
 
-             printf ("which_alternative %s= %d",
-                     XINT (exp, 1) ? "!" : "=", bit);
+             fprintf (outf, "which_alternative %s= %d",
+                      XINT (exp, 1) ? "!" : "=", bit);
            }
          else
            {
-             printf ("%s((1 << which_alternative) & %#x)",
-                     XINT (exp, 1) ? "!" : "", set);
+             fprintf (outf, "%s((1 << which_alternative) & %#x)",
+                      XINT (exp, 1) ? "!" : "", set);
            }
        }
       break;
@@ -3511,7 +3531,7 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
 
       if (XSTR (exp, 0) == alternative_name)
        {
-         printf ("which_alternative == %s", XSTR (exp, 1));
+         fprintf (outf, "which_alternative == %s", XSTR (exp, 1));
          break;
        }
 
@@ -3521,8 +3541,10 @@ write_test_expr (rtx exp, unsigned int attrs_cached, 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,
-                                            attr->default_val->value, -2, -2),
+         write_test_expr (outf,
+                          evaluate_eq_attr (exp, attr,
+                                            attr->default_val->value,
+                                            -2, -2),
                           attrs_cached, 0);
        }
       else
@@ -3532,10 +3554,10 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
            if (attr->name == cached_attrs[i])
              break;
          if (i < cached_attr_count && (attrs_cached & (1U << i)) != 0)
-           printf ("cached_%s", attr->name);
+           fprintf (outf, "cached_%s", attr->name);
          else if (i < cached_attr_count && (attrs_to_cache & (1U << i)) != 0)
            {
-             printf ("(cached_%s = get_attr_%s (insn))",
+             fprintf (outf, "(cached_%s = get_attr_%s (insn))",
                      attr->name, attr->name);
              if (flags & FLG_AFTER)
                attrs_cached_after |= (1U << i);
@@ -3544,9 +3566,9 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
              attrs_cached |= (1U << i);
            }
          else
-           printf ("get_attr_%s (insn)", attr->name);
-         printf (" == ");
-         write_attr_valueq (attr, XSTR (exp, 1));
+           fprintf (outf, "get_attr_%s (insn)", attr->name);
+         fprintf (outf, " == ");
+         write_attr_valueq (outf, attr, XSTR (exp, 1));
        }
       break;
 
@@ -3554,7 +3576,7 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
     case ATTR_FLAG:
       if (flags & FLG_BITWISE)
        fatal ("ATTR_FLAG not valid inside comparison");
-      printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
+      fprintf (outf, "(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
       break;
 
     /* See if an operand matches a predicate.  */
@@ -3566,34 +3588,35 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
          if (GET_MODE (exp) == VOIDmode)
            fatal ("null MATCH_OPERAND specified as test");
          else
-           printf ("GET_MODE (operands[%d]) == %smode",
-                   XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
+           fprintf (outf, "GET_MODE (operands[%d]) == %smode",
+                    XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
        }
       else
-       printf ("%s (operands[%d], %smode)",
-               XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
+       fprintf (outf, "%s (operands[%d], %smode)",
+                XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
       break;
 
     /* Constant integer.  */
     case CONST_INT:
-      printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0));
+      fprintf (outf, HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0));
       break;
 
     case MATCH_TEST:
-      print_c_condition (XSTR (exp, 0));
+      fprint_c_condition (outf, XSTR (exp, 0));
       if (flags & FLG_BITWISE)
-       printf (" != 0");
+       fprintf (outf, " != 0");
       break;
 
     /* A random C expression.  */
     case SYMBOL_REF:
-      print_c_condition (XSTR (exp, 0));
+      fprint_c_condition (outf, XSTR (exp, 0));
       break;
 
     /* The address of the branch target.  */
     case MATCH_DUP:
-      printf ("INSN_ADDRESSES_SET_P () ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])) : 0",
-             XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
+      fprintf (outf,
+              "INSN_ADDRESSES_SET_P () ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])) : 0",
+              XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
       break;
 
     case PC:
@@ -3602,19 +3625,19 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
         address of the next insn for forward branches, and both with
         adjustments that account for the worst-case possible stretching of
         intervening alignments between this insn and its destination.  */
-      printf ("insn_current_reference_address (insn)");
+      fprintf (outf, "insn_current_reference_address (insn)");
       break;
 
     case CONST_STRING:
-      printf ("%s", XSTR (exp, 0));
+      fprintf (outf, "%s", XSTR (exp, 0));
       break;
 
     case IF_THEN_ELSE:
-      write_test_expr (XEXP (exp, 0), attrs_cached, 0);
-      printf (" ? ");
-      write_test_expr (XEXP (exp, 1), attrs_cached, FLG_BITWISE);
-      printf (" : ");
-      write_test_expr (XEXP (exp, 2), attrs_cached, FLG_BITWISE);
+      write_test_expr (outf, XEXP (exp, 0), attrs_cached, 0);
+      fprintf (outf, " ? ");
+      write_test_expr (outf, XEXP (exp, 1), attrs_cached, FLG_BITWISE);
+      fprintf (outf, " : ");
+      write_test_expr (outf, XEXP (exp, 2), attrs_cached, FLG_BITWISE);
       break;
 
     default:
@@ -3622,7 +3645,7 @@ write_test_expr (rtx exp, unsigned int attrs_cached, int flags)
             GET_RTX_NAME (code));
     }
 
-  printf (")");
+  fprintf (outf, ")");
   return attrs_cached;
 }
 
@@ -3826,7 +3849,7 @@ walk_attr_value (rtx exp)
 /* Write out a function to obtain the attribute for a given INSN.  */
 
 static void
-write_attr_get (struct attr_desc *attr)
+write_attr_get (FILE *outf, struct attr_desc *attr)
 {
   struct attr_value *av, *common_av;
   int i, j;
@@ -3838,37 +3861,37 @@ 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->enum_name)
-    printf ("enum %s\n", attr->enum_name);
+    fprintf (outf, "enum %s\n", attr->enum_name);
   else if (!attr->is_numeric)
-    printf ("enum attr_%s\n", attr->name);
+    fprintf (outf, "enum attr_%s\n", attr->name);
   else
-    printf ("int\n");
+    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] == '*')
-    printf ("%s (rtx insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
+    fprintf (outf, "%s (rtx insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
   else if (attr->is_const == 0)
-    printf ("get_attr_%s (rtx insn ATTRIBUTE_UNUSED)\n", attr->name);
+    fprintf (outf, "get_attr_%s (rtx insn ATTRIBUTE_UNUSED)\n", attr->name);
   else
     {
-      printf ("get_attr_%s (void)\n", attr->name);
-      printf ("{\n");
+      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 (attr, 2, av->value, "return", ";",
+         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 (attr, 2, av->value, "return", ";",
+         write_attr_set (outf, attr, 2, av->value, "return", ";",
                          true_rtx, -2, 0, 0);
 
-      printf ("}\n\n");
+      fprintf (outf, "}\n\n");
       return;
     }
 
-  printf ("{\n");
+  fprintf (outf, "{\n");
 
   /* Find attributes that are worth caching in the conditions.  */
   cached_attr_count = 0;
@@ -3889,27 +3912,27 @@ write_attr_get (struct attr_desc *attr)
        cached_attr = find_attr (&name, 0);
        gcc_assert (cached_attr && cached_attr->is_const == 0);
        if (cached_attr->enum_name)
-         printf ("  enum %s", cached_attr->enum_name);
+         fprintf (outf, "  enum %s", cached_attr->enum_name);
        else if (!cached_attr->is_numeric)
-         printf ("  enum attr_%s", cached_attr->name);
+         fprintf (outf, "  enum attr_%s", cached_attr->name);
        else
-         printf ("  int");
-       printf (" cached_%s ATTRIBUTE_UNUSED;\n", name);
+         fprintf (outf, "  int");
+       fprintf (outf, " cached_%s ATTRIBUTE_UNUSED;\n", name);
        j++;
       }
   cached_attr_count = j;
   if (cached_attr_count)
-    printf ("\n");
+    fprintf (outf, "\n");
 
-  printf ("  switch (recog_memoized (insn))\n");
-  printf ("    {\n");
+  fprintf (outf, "  switch (recog_memoized (insn))\n");
+  fprintf (outf, "    {\n");
 
   for (av = attr->first_value; av; av = av->next)
     if (av != common_av)
-      write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
+      write_attr_case (outf, attr, av, 1, "return", ";", 4, true_rtx);
 
-  write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
-  printf ("    }\n}\n\n");
+  write_attr_case (outf, attr, common_av, 0, "return", ";", 4, true_rtx);
+  fprintf (outf, "    }\n}\n\n");
   cached_attr_count = 0;
 }
 
@@ -3947,7 +3970,7 @@ eliminate_known_true (rtx known_true, rtx exp, int insn_code, int insn_index)
    and ";").  */
 
 static void
-write_attr_set (struct attr_desc *attr, int indent, rtx value,
+write_attr_set (FILE *outf, struct attr_desc *attr, int indent, rtx value,
                const char *prefix, const char *suffix, rtx known_true,
                int insn_code, int insn_index, unsigned int attrs_cached)
 {
@@ -4002,49 +4025,49 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value,
 
          attrs_cached_inside = attrs_cached;
          attrs_cached_after = attrs_cached;
-         write_indent (indent);
-         printf ("%sif ", first_if ? "" : "else ");
+         write_indent (outf, indent);
+         fprintf (outf, "%sif ", first_if ? "" : "else ");
          first_if = 0;
-         write_test_expr (testexp, attrs_cached,
+         write_test_expr (outf, testexp, attrs_cached,
                           (FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND));
          attrs_cached = attrs_cached_after;
-         printf ("\n");
-         write_indent (indent + 2);
-         printf ("{\n");
+         fprintf (outf, "\n");
+         write_indent (outf, indent + 2);
+         fprintf (outf, "{\n");
 
-         write_attr_set (attr, indent + 4,
+         write_attr_set (outf, attr, indent + 4,
                          XVECEXP (value, 0, i + 1), prefix, suffix,
                          inner_true, insn_code, insn_index,
                          attrs_cached_inside);
-         write_indent (indent + 2);
-         printf ("}\n");
+         write_indent (outf, indent + 2);
+         fprintf (outf, "}\n");
          our_known_true = newexp;
        }
 
       if (! first_if)
        {
-         write_indent (indent);
-         printf ("else\n");
-         write_indent (indent + 2);
-         printf ("{\n");
+         write_indent (outf, indent);
+         fprintf (outf, "else\n");
+         write_indent (outf, indent + 2);
+         fprintf (outf, "{\n");
        }
 
-      write_attr_set (attr, first_if ? indent : indent + 4, default_val,
+      write_attr_set (outf, attr, first_if ? indent : indent + 4, default_val,
                      prefix, suffix, our_known_true, insn_code, insn_index,
                      attrs_cached);
 
       if (! first_if)
        {
-         write_indent (indent + 2);
-         printf ("}\n");
+         write_indent (outf, indent + 2);
+         fprintf (outf, "}\n");
        }
     }
   else
     {
-      write_indent (indent);
-      printf ("%s ", prefix);
-      write_attr_value (attr, value);
-      printf ("%s\n", suffix);
+      write_indent (outf, indent);
+      fprintf (outf, "%s ", prefix);
+      write_attr_value (outf, attr, value);
+      fprintf (outf, "%s\n", suffix);
     }
 }
 
@@ -4052,25 +4075,25 @@ write_attr_set (struct attr_desc *attr, int indent, rtx value,
    INDENT is the amount of indentation to write before each case.  */
 
 static void
-write_insn_cases (struct insn_ent *ie, int indent)
+write_insn_cases (FILE *outf, struct insn_ent *ie, int indent)
 {
   for (; ie != 0; ie = ie->next)
     if (ie->def->insn_code != -1)
       {
-       write_indent (indent);
+       write_indent (outf, indent);
        if (GET_CODE (ie->def->def) == DEFINE_PEEPHOLE)
-         printf ("case %d:  /* define_peephole, line %d */\n",
-                 ie->def->insn_code, ie->def->lineno);
+         fprintf (outf, "case %d:  /* define_peephole, line %d */\n",
+                  ie->def->insn_code, ie->def->lineno);
        else
-         printf ("case %d:  /* %s */\n",
-                 ie->def->insn_code, XSTR (ie->def->def, 0));
+         fprintf (outf, "case %d:  /* %s */\n",
+                  ie->def->insn_code, XSTR (ie->def->def, 0));
       }
 }
 
 /* Write out the computation for one attribute value.  */
 
 static void
-write_attr_case (struct attr_desc *attr, struct attr_value *av,
+write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av,
                 int write_case_lines, const char *prefix, const char *suffix,
                 int indent, rtx known_true)
 {
@@ -4079,22 +4102,22 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av,
 
   if (av->has_asm_insn)
     {
-      write_indent (indent);
-      printf ("case -1:\n");
-      write_indent (indent + 2);
-      printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
-      write_indent (indent + 2);
-      printf ("    && asm_noperands (PATTERN (insn)) < 0)\n");
-      write_indent (indent + 2);
-      printf ("  fatal_insn_not_found (insn);\n");
+      write_indent (outf, indent);
+      fprintf (outf, "case -1:\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "    && asm_noperands (PATTERN (insn)) < 0)\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "  fatal_insn_not_found (insn);\n");
     }
 
   if (write_case_lines)
-    write_insn_cases (av->first_insn, indent);
+    write_insn_cases (outf, av->first_insn, indent);
   else
     {
-      write_indent (indent);
-      printf ("default:\n");
+      write_indent (outf, indent);
+      fprintf (outf, "default:\n");
     }
 
   /* See what we have to do to output this value.  */
@@ -4103,85 +4126,85 @@ write_attr_case (struct attr_desc *attr, struct attr_value *av,
 
   if (must_constrain)
     {
-      write_indent (indent + 2);
-      printf ("extract_constrain_insn_cached (insn);\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "extract_constrain_insn_cached (insn);\n");
     }
   else if (must_extract)
     {
-      write_indent (indent + 2);
-      printf ("extract_insn_cached (insn);\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "extract_insn_cached (insn);\n");
     }
 
   attrs_to_cache = 0;
   if (av->num_insns == 1)
-    write_attr_set (attr, indent + 2, av->value, prefix, suffix,
+    write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
                    known_true, av->first_insn->def->insn_code,
                    av->first_insn->def->insn_index, 0);
   else
-    write_attr_set (attr, indent + 2, av->value, prefix, suffix,
+    write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
                    known_true, -2, 0, 0);
 
   if (strncmp (prefix, "return", 6))
     {
-      write_indent (indent + 2);
-      printf ("break;\n");
+      write_indent (outf, indent + 2);
+      fprintf (outf, "break;\n");
     }
-  printf ("\n");
+  fprintf (outf, "\n");
 }
 
 /* Utilities to write in various forms.  */
 
 static void
-write_attr_valueq (struct attr_desc *attr, const char *s)
+write_attr_valueq (FILE *outf, struct attr_desc *attr, const char *s)
 {
   if (attr->is_numeric)
     {
       int num = atoi (s);
 
-      printf ("%d", num);
+      fprintf (outf, "%d", num);
 
       if (num > 9 || num < 0)
-       printf (" /* %#x */", num);
+       fprintf (outf, " /* %#x */", num);
     }
   else
     {
-      write_upcase (attr->enum_name ? attr->enum_name : attr->name);
-      printf ("_");
-      write_upcase (s);
+      write_upcase (outf, attr->enum_name ? attr->enum_name : attr->name);
+      fprintf (outf, "_");
+      write_upcase (outf, s);
     }
 }
 
 static void
-write_attr_value (struct attr_desc *attr, rtx value)
+write_attr_value (FILE *outf, struct attr_desc *attr, rtx value)
 {
   int op;
 
   switch (GET_CODE (value))
     {
     case CONST_STRING:
-      write_attr_valueq (attr, XSTR (value, 0));
+      write_attr_valueq (outf, attr, XSTR (value, 0));
       break;
 
     case CONST_INT:
-      printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (value));
+      fprintf (outf, HOST_WIDE_INT_PRINT_DEC, INTVAL (value));
       break;
 
     case SYMBOL_REF:
-      print_c_condition (XSTR (value, 0));
+      fprint_c_condition (outf, XSTR (value, 0));
       break;
 
     case ATTR:
       {
        struct attr_desc *attr2 = find_attr (&XSTR (value, 0), 0);
        if (attr->enum_name)
-         printf ("(enum %s)", attr->enum_name);
+         fprintf (outf, "(enum %s)", attr->enum_name);
        else if (!attr->is_numeric)
-         printf ("(enum attr_%s)", attr->name);
+         fprintf (outf, "(enum attr_%s)", attr->name);
        else if (!attr2->is_numeric)
-         printf ("(int)");
+         fprintf (outf, "(int)");
 
-       printf ("get_attr_%s (%s)", attr2->name,
-               (attr2->is_const ? "" : "insn"));
+       fprintf (outf, "get_attr_%s (%s)", attr2->name,
+                (attr2->is_const ? "" : "insn"));
       }
       break;
 
@@ -4202,11 +4225,11 @@ write_attr_value (struct attr_desc *attr, rtx value)
       goto do_operator;
 
     do_operator:
-      write_attr_value (attr, XEXP (value, 0));
-      putchar (' ');
-      putchar (op);
-      putchar (' ');
-      write_attr_value (attr, XEXP (value, 1));
+      write_attr_value (outf, attr, XEXP (value, 0));
+      fputc (' ', outf);
+      fputc (op,  outf);
+      fputc (' ', outf);
+      write_attr_value (outf, attr, XEXP (value, 1));
       break;
 
     default:
@@ -4215,24 +4238,24 @@ write_attr_value (struct attr_desc *attr, rtx value)
 }
 
 static void
-write_upcase (const char *str)
+write_upcase (FILE *outf, const char *str)
 {
   while (*str)
     {
       /* The argument of TOUPPER should not have side effects.  */
-      putchar (TOUPPER(*str));
+      fputc (TOUPPER(*str), outf);
       str++;
     }
 }
 
 static void
-write_indent (int indent)
+write_indent (FILE *outf, int indent)
 {
   for (; indent > 8; indent -= 8)
-    printf ("\t");
+    fprintf (outf, "\t");
 
   for (; indent; indent--)
-    printf (" ");
+    fprintf (outf, " ");
 }
 
 /* Write a subroutine that is given an insn that requires a delay slot, a
@@ -4248,7 +4271,7 @@ write_indent (int indent)
    or "annul_false").  */
 
 static void
-write_eligible_delay (const char *kind)
+write_eligible_delay (FILE *outf, const char *kind)
 {
   struct delay_desc *delay;
   int max_slots;
@@ -4268,19 +4291,20 @@ write_eligible_delay (const char *kind)
 
   /* Write function prelude.  */
 
-  printf ("int\n");
-  printf ("eligible_for_%s (rtx delay_insn ATTRIBUTE_UNUSED, int slot, rtx candidate_insn, int flags ATTRIBUTE_UNUSED)\n",
-         kind);
-  printf ("{\n");
-  printf ("  rtx insn;\n");
-  printf ("\n");
-  printf ("  gcc_assert (slot < %d);\n", max_slots);
-  printf ("\n");
+  fprintf (outf, "int\n");
+  fprintf (outf, "eligible_for_%s (rtx delay_insn ATTRIBUTE_UNUSED, int slot, \n"
+                "                 rtx candidate_insn, int flags ATTRIBUTE_UNUSED)\n",
+          kind);
+  fprintf (outf, "{\n");
+  fprintf (outf, "  rtx insn;\n");
+  fprintf (outf, "\n");
+  fprintf (outf, "  gcc_assert (slot < %d);\n", max_slots);
+  fprintf (outf, "\n");
   /* Allow dbr_schedule to pass labels, etc.  This can happen if try_split
      converts a compound instruction into a loop.  */
-  printf ("  if (!INSN_P (candidate_insn))\n");
-  printf ("    return 0;\n");
-  printf ("\n");
+  fprintf (outf, "  if (!INSN_P (candidate_insn))\n");
+  fprintf (outf, "    return 0;\n");
+  fprintf (outf, "\n");
 
   /* If more than one delay type, find out which type the delay insn is.  */
 
@@ -4290,28 +4314,28 @@ write_eligible_delay (const char *kind)
       gcc_assert (attr);
       common_av = find_most_used (attr);
 
-      printf ("  insn = delay_insn;\n");
-      printf ("  switch (recog_memoized (insn))\n");
-      printf ("    {\n");
+      fprintf (outf, "  insn = delay_insn;\n");
+      fprintf (outf, "  switch (recog_memoized (insn))\n");
+      fprintf (outf, "    {\n");
 
       sprintf (str, " * %d;\n      break;", max_slots);
       for (av = attr->first_value; av; av = av->next)
        if (av != common_av)
-         write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
+         write_attr_case (outf, attr, av, 1, "slot +=", str, 4, true_rtx);
 
-      write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
-      printf ("    }\n\n");
+      write_attr_case (outf, attr, common_av, 0, "slot +=", str, 4, true_rtx);
+      fprintf (outf, "    }\n\n");
 
       /* Ensure matched.  Otherwise, shouldn't have been called.  */
-      printf ("  gcc_assert (slot >= %d);\n\n", max_slots);
+      fprintf (outf, "  gcc_assert (slot >= %d);\n\n", max_slots);
     }
 
   /* If just one type of delay slot, write simple switch.  */
   if (num_delays == 1 && max_slots == 1)
     {
-      printf ("  insn = candidate_insn;\n");
-      printf ("  switch (recog_memoized (insn))\n");
-      printf ("    {\n");
+      fprintf (outf, "  insn = candidate_insn;\n");
+      fprintf (outf, "  switch (recog_memoized (insn))\n");
+      fprintf (outf, "    {\n");
 
       attr = find_attr (&delay_1_0_str, 0);
       gcc_assert (attr);
@@ -4319,27 +4343,27 @@ write_eligible_delay (const char *kind)
 
       for (av = attr->first_value; av; av = av->next)
        if (av != common_av)
-         write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
+         write_attr_case (outf, attr, av, 1, "return", ";", 4, true_rtx);
 
-      write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
-      printf ("    }\n");
+      write_attr_case (outf, attr, common_av, 0, "return", ";", 4, true_rtx);
+      fprintf (outf, "    }\n");
     }
 
   else
     {
       /* Write a nested CASE.  The first indicates which condition we need to
         test, and the inner CASE tests the condition.  */
-      printf ("  insn = candidate_insn;\n");
-      printf ("  switch (slot)\n");
-      printf ("    {\n");
+      fprintf (outf, "  insn = candidate_insn;\n");
+      fprintf (outf, "  switch (slot)\n");
+      fprintf (outf, "    {\n");
 
       for (delay = delays; delay; delay = delay->next)
        for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
          {
-           printf ("    case %d:\n",
-                   (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
-           printf ("      switch (recog_memoized (insn))\n");
-           printf ("\t{\n");
+           fprintf (outf, "    case %d:\n",
+                    (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
+           fprintf (outf, "      switch (recog_memoized (insn))\n");
+           fprintf (outf, "\t{\n");
 
            sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
            pstr = str;
@@ -4349,18 +4373,18 @@ write_eligible_delay (const char *kind)
 
            for (av = attr->first_value; av; av = av->next)
              if (av != common_av)
-               write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
+               write_attr_case (outf, attr, av, 1, "return", ";", 8, true_rtx);
 
-           write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
-           printf ("      }\n");
+           write_attr_case (outf, attr, common_av, 0, "return", ";", 8, true_rtx);
+           fprintf (outf, "      }\n");
          }
 
-      printf ("    default:\n");
-      printf ("      gcc_unreachable ();\n");
-      printf ("    }\n");
+      fprintf (outf, "    default:\n");
+      fprintf (outf, "      gcc_unreachable ();\n");
+      fprintf (outf, "    }\n");
     }
 
-  printf ("}\n\n");
+  fprintf (outf, "}\n\n");
 }
 
 /* This page contains miscellaneous utility routines.  */
@@ -4499,29 +4523,29 @@ copy_rtx_unchanging (rtx orig)
    number of delay slots is not a function of the length of the insn.  */
 
 static void
-write_const_num_delay_slots (void)
+write_const_num_delay_slots (FILE *outf)
 {
   struct attr_desc *attr = find_attr (&num_delay_slots_str, 0);
   struct attr_value *av;
 
   if (attr)
     {
-      printf ("int\nconst_num_delay_slots (rtx insn)\n");
-      printf ("{\n");
-      printf ("  switch (recog_memoized (insn))\n");
-      printf ("    {\n");
+      fprintf (outf, "int\nconst_num_delay_slots (rtx insn)\n");
+      fprintf (outf, "{\n");
+      fprintf (outf, "  switch (recog_memoized (insn))\n");
+      fprintf (outf, "    {\n");
 
       for (av = attr->first_value; av; av = av->next)
        {
          length_used = 0;
          walk_attr_value (av->value);
          if (length_used)
-           write_insn_cases (av->first_insn, 4);
+           write_insn_cases (outf, av->first_insn, 4);
        }
 
-      printf ("    default:\n");
-      printf ("      return 1;\n");
-      printf ("    }\n}\n\n");
+      fprintf (outf, "    default:\n");
+      fprintf (outf, "      return 1;\n");
+      fprintf (outf, "    }\n}\n\n");
     }
 }
 \f
@@ -4697,7 +4721,10 @@ find_tune_attr (rtx exp)
     }
 }
 
-/* Create all of the attributes that describe automaton properties.  */
+/* Create all of the attributes that describe automaton properties.
+   Write the DFA and latency function prototypes to  the files that
+   need to have them, and write the init_sched_attrs().  */
+
 static void
 make_automaton_attrs (void)
 {
@@ -4719,23 +4746,49 @@ make_automaton_attrs (void)
       gcc_assert (tune_attr->is_const
                  && !tune_attr->is_special
                  && !tune_attr->is_numeric);
+
+      /* Write the prototypes for all DFA functions.  */
+      for (val = tune_attr->first_value; val; val = val->next)
+       {
+         if (val == tune_attr->default_val)
+           continue;
+         gcc_assert (GET_CODE (val->value) == CONST_STRING);
+         fprintf (dfa_file,
+                  "extern int internal_dfa_insn_code_%s (rtx);\n",
+                  XSTR (val->value, 0));
+       }
+      fprintf (dfa_file, "\n");
+
+      /* Write the prototypes for all latency functions.  */
       for (val = tune_attr->first_value; val; val = val->next)
        {
          if (val == tune_attr->default_val)
            continue;
          gcc_assert (GET_CODE (val->value) == CONST_STRING);
-         printf ("static int internal_dfa_insn_code_%s (rtx);\n"
-                 "static int insn_default_latency_%s (rtx);\n",
-                 XSTR (val->value, 0), XSTR (val->value, 0));
+         fprintf (latency_file,
+                  "extern int insn_default_latency_%s (rtx);\n",
+                  XSTR (val->value, 0));
        }
+      fprintf (latency_file, "\n");
 
-      printf ("\n");
-      printf ("int (*internal_dfa_insn_code) (rtx);\n");
-      printf ("int (*insn_default_latency) (rtx);\n");
-      printf ("\n");
-      printf ("void\n");
-      printf ("init_sched_attrs (void)\n");
-      printf ("{\n");
+      /* Write the prototypes for all automaton functions.  */
+      for (val = tune_attr->first_value; val; val = val->next)
+       {
+         if (val == tune_attr->default_val)
+           continue;
+         gcc_assert (GET_CODE (val->value) == CONST_STRING);
+         fprintf (attr_file,
+                  "extern int internal_dfa_insn_code_%s (rtx);\n"
+                  "extern int insn_default_latency_%s (rtx);\n",
+                  XSTR (val->value, 0), XSTR (val->value, 0));
+       }
+      fprintf (attr_file, "\n");
+      fprintf (attr_file, "int (*internal_dfa_insn_code) (rtx);\n");
+      fprintf (attr_file, "int (*insn_default_latency) (rtx);\n");
+      fprintf (attr_file, "\n");
+      fprintf (attr_file, "void\n");
+      fprintf (attr_file, "init_sched_attrs (void)\n");
+      fprintf (attr_file, "{\n");
 
       for (val = tune_attr->first_value; val; val = val->next)
        {
@@ -4804,27 +4857,27 @@ make_automaton_attrs (void)
 
          if (first)
            {
-             printf ("  if (");
+             fprintf (attr_file, "  if (");
              first = false;
            }
          else
-           printf ("  else if (");
-         write_test_expr (test, 0, 0);
-         printf (")\n");
-         printf ("    {\n");
-         printf ("      internal_dfa_insn_code\n");
-         printf ("        = internal_dfa_insn_code_%s;\n",
-                 XSTR (val->value, 0));
-         printf ("      insn_default_latency\n");
-         printf ("        = insn_default_latency_%s;\n",
-                 XSTR (val->value, 0));
-         printf ("    }\n");
+           fprintf (attr_file, "  else if (");
+         write_test_expr (attr_file, test, 0, 0);
+         fprintf (attr_file, ")\n");
+         fprintf (attr_file, "    {\n");
+         fprintf (attr_file, "      internal_dfa_insn_code\n");
+         fprintf (attr_file, "        = internal_dfa_insn_code_%s;\n",
+                  XSTR (val->value, 0));
+         fprintf (attr_file, "      insn_default_latency\n");
+         fprintf (attr_file, "        = insn_default_latency_%s;\n",
+                  XSTR (val->value, 0));
+         fprintf (attr_file, "    }\n");
        }
 
-      printf ("  else\n");
-      printf ("    gcc_unreachable ();\n");
-      printf ("}\n");
-      printf ("\n");
+      fprintf (attr_file, "  else\n");
+      fprintf (attr_file, "    gcc_unreachable ();\n");
+      fprintf (attr_file, "}\n");
+      fprintf (attr_file, "\n");
 
       XDELETEVEC (condexps);
     }
@@ -4874,7 +4927,62 @@ make_automaton_attrs (void)
          }
     }
 
-  make_internal_attr ("*bypass_p",               byps_exp, ATTR_NONE);
+  make_internal_attr ("*bypass_p", byps_exp, ATTR_NONE);
+}
+
+static void
+write_header (FILE *outf)
+{
+  fprintf (outf, "/* Generated automatically by the program `genattrtab'\n"
+                "   from the machine description file `md'.  */\n\n");
+
+  fprintf (outf, "#include \"config.h\"\n");
+  fprintf (outf, "#include \"system.h\"\n");
+  fprintf (outf, "#include \"coretypes.h\"\n");
+  fprintf (outf, "#include \"tm.h\"\n");
+  fprintf (outf, "#include \"rtl.h\"\n");
+  fprintf (outf, "#include \"insn-attr.h\"\n");
+  fprintf (outf, "#include \"tm_p.h\"\n");
+  fprintf (outf, "#include \"insn-config.h\"\n");
+  fprintf (outf, "#include \"recog.h\"\n");
+  fprintf (outf, "#include \"regs.h\"\n");
+  fprintf (outf, "#include \"real.h\"\n");
+  fprintf (outf, "#include \"output.h\"\n");
+  fprintf (outf, "#include \"toplev.h\"\n");
+  fprintf (outf, "#include \"flags.h\"\n");
+  fprintf (outf, "#include \"function.h\"\n");
+  fprintf (outf, "\n");
+  fprintf (outf, "#define operands recog_data.operand\n\n");
+}
+
+static FILE *
+open_outfile (const char *file_name)
+{
+  FILE *outf;
+  outf = fopen (file_name, "w");
+  if (! outf)
+    fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
+  write_header (outf);
+  return outf;
+}
+
+static bool
+handle_arg (const char *arg)
+{
+  switch (arg[1])
+    {
+    case 'A':
+      attr_file_name = &arg[2];
+      return true;
+    case 'D':
+      dfa_file_name = &arg[2];
+      return true;
+    case 'L':
+      latency_file_name = &arg[2];
+      return true;
+    default:
+      return false;
+    }
 }
 
 int
@@ -4888,8 +4996,12 @@ main (int argc, char **argv)
 
   progname = "genattrtab";
 
-  if (!init_rtx_reader_args (argc, argv))
-    return (FATAL_EXIT_CODE);
+  if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
+    return FATAL_EXIT_CODE;
+
+  attr_file = open_outfile (attr_file_name);
+  dfa_file = open_outfile (dfa_file_name);
+  latency_file = open_outfile (latency_file_name);
 
   obstack_init (hash_obstack);
   obstack_init (temp_obstack);
@@ -4908,9 +5020,6 @@ main (int argc, char **argv)
   delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");
   num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");
 
-  printf ("/* Generated automatically by the program `genattrtab'\n\
-from the machine description file `md'.  */\n\n");
-
   /* Read the machine description.  */
 
   while (1)
@@ -4970,23 +5079,6 @@ from the machine description file `md'.  */\n\n");
   if (num_delays)
     expand_delays ();
 
-  printf ("#include \"config.h\"\n");
-  printf ("#include \"system.h\"\n");
-  printf ("#include \"coretypes.h\"\n");
-  printf ("#include \"tm.h\"\n");
-  printf ("#include \"rtl.h\"\n");
-  printf ("#include \"insn-attr.h\"\n");
-  printf ("#include \"tm_p.h\"\n");
-  printf ("#include \"insn-config.h\"\n");
-  printf ("#include \"recog.h\"\n");
-  printf ("#include \"regs.h\"\n");
-  printf ("#include \"output.h\"\n");
-  printf ("#include \"diagnostic-core.h\"\n");
-  printf ("#include \"flags.h\"\n");
-  printf ("#include \"function.h\"\n");
-  printf ("\n");
-  printf ("#define operands recog_data.operand\n\n");
-
   /* Make `insn_alternatives'.  */
   insn_alternatives = oballocvec (int, insn_code_number);
   for (id = defs; id; id = id->next)
@@ -5031,8 +5123,19 @@ from the machine description file `md'.  */\n\n");
   for (i = 0; i < MAX_ATTRS_INDEX; i++)
     for (attr = attrs[i]; attr; attr = attr->next)
       {
+        FILE *outf;
+
+#define IS_ATTR_GROUP(X) (!strncmp(attr->name,X,strlen(X)))
+       if (IS_ATTR_GROUP ("*internal_dfa_insn_code"))
+         outf = dfa_file;
+       else if (IS_ATTR_GROUP ("*insn_default_latency"))
+         outf = latency_file;  
+       else
+         outf = attr_file;
+#undef IS_ATTR_GROUP
+
        if (! attr->is_special && ! attr->is_const)
-         write_attr_get (attr);
+         write_attr_get (outf, attr);
       }
 
   /* Write out delay eligibility information, if DEFINE_DELAY present.
@@ -5040,18 +5143,25 @@ from the machine description file `md'.  */\n\n");
      below.)  */
   if (num_delays)
     {
-      write_eligible_delay ("delay");
+      write_eligible_delay (attr_file, "delay");
       if (have_annul_true)
-       write_eligible_delay ("annul_true");
+       write_eligible_delay (attr_file, "annul_true");
       if (have_annul_false)
-       write_eligible_delay ("annul_false");
+       write_eligible_delay (attr_file, "annul_false");
     }
 
   /* Write out constant delay slot info.  */
-  write_const_num_delay_slots ();
+  write_const_num_delay_slots (attr_file);
 
-  write_length_unit_log ();
+  write_length_unit_log (attr_file);
 
-  fflush (stdout);
-  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
+  if (fclose (attr_file) != 0)
+    fatal ("cannot close file %s: %s", attr_file_name, xstrerror (errno));
+  if (fclose (dfa_file) != 0)
+    fatal ("cannot close file %s: %s", dfa_file_name, xstrerror (errno));
+  if (fclose (latency_file) != 0)
+    fatal ("cannot close file %s: %s", latency_file_name, xstrerror (errno));
+
+  return SUCCESS_EXIT_CODE;
 }
+
index 4f1933f..e5534d7 100644 (file)
@@ -167,14 +167,21 @@ copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
 }
 
 /* If PTR is associated with a known file position, print a #line
-   directive for it.  */
+   directive for it to OUTF.  */
 
 void
-print_md_ptr_loc (const void *ptr)
+fprint_md_ptr_loc (FILE *outf, const void *ptr)
 {
   const struct ptr_loc *loc = get_md_ptr_loc (ptr);
   if (loc != 0)
-    printf ("#line %d \"%s\"\n", loc->lineno, loc->filename);
+    fprintf (outf, "#line %d \"%s\"\n", loc->lineno, loc->filename);
+}
+
+/* Special fprint_md_ptr_loc for writing to STDOUT.  */
+void
+print_md_ptr_loc (const void *ptr)
+{
+  fprint_md_ptr_loc (stdout, ptr);
 }
 
 /* Return a condition that satisfies both COND1 and COND2.  Either string
@@ -204,31 +211,39 @@ join_c_conditions (const char *cond1, const char *cond2)
   return result;
 }
 
-/* Print condition COND, wrapped in brackets.  If COND was created by
-   join_c_conditions, recursively invoke this function for the original
+/* Print condition COND to OUTF, wrapped in brackets.  If COND was created
+   by join_c_conditions, recursively invoke this function for the original
    conditions and join the result with "&&".  Otherwise print a #line
    directive for COND if its original file position is known.  */
 
 void
-print_c_condition (const char *cond)
+fprint_c_condition (FILE *outf, const char *cond)
 {
   const char **halves = (const char **) htab_find (joined_conditions, &cond);
   if (halves != 0)
     {
-      printf ("(");
-      print_c_condition (halves[1]);
-      printf (" && ");
-      print_c_condition (halves[2]);
-      printf (")");
+      fprintf (outf, "(");
+      fprint_c_condition (outf, halves[1]);
+      fprintf (outf, " && ");
+      fprint_c_condition (outf, halves[2]);
+      fprintf (outf, ")");
     }
   else
     {
-      putc ('\n', stdout);
-      print_md_ptr_loc (cond);
-      printf ("(%s)", cond);
+      fputc ('\n', outf);
+      fprint_md_ptr_loc (outf, cond);
+      fprintf (outf, "(%s)", cond);
     }
 }
 
+/* Special fprint_c_condition for writing to STDOUT.  */
+
+void
+print_c_condition (const char *cond)
+{
+  fprint_c_condition (stdout, cond);
+}
+
 /* A vfprintf-like function for reporting an error against line LINENO
    of the current MD file.  */
 
index abcca51..43dfc44 100644 (file)
@@ -118,8 +118,10 @@ extern hashval_t leading_string_hash (const void *);
 extern int leading_string_eq_p (const void *, const void *);
 extern void copy_md_ptr_loc (const void *, const void *);
 extern void print_md_ptr_loc (const void *);
+extern void fprint_md_ptr_loc (FILE *, const void *);
 extern const char *join_c_conditions (const char *, const char *);
 extern void print_c_condition (const char *);
+extern void fprint_c_condition (FILE *, const char *);
 extern void message_with_line (int, const char *, ...) ATTRIBUTE_PRINTF_2;
 extern void error_with_line (int, const char *, ...) ATTRIBUTE_PRINTF_2;
 extern void fatal_with_file_and_line (const char *, ...)