示例#1
0
int
main (int argc, char **argv)
{
  int dummy1, dummy2;
  rtx desc;

  progname = "genconstants";

  if (argc <= 1)
    fatal ("no input file name");

  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
    return (FATAL_EXIT_CODE);

  /* Scan and discard the entire file.  This has the side effect
     of loading up the constants table that we wish to scan.  */
  do
    desc = read_md_rtx (&dummy1, &dummy2);
  while (desc);

  puts ("/* Generated automatically by the program `genconstants'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_CONSTANTS_H");
  puts ("#define GCC_INSN_CONSTANTS_H\n");

  traverse_md_constants (print_md_constant, stdout);

  puts ("\n#endif /* GCC_INSN_CONSTANTS_H */");

  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
}
示例#2
0
文件: genmddump.c 项目: AHelper/gcc
int
main (int argc, char **argv)
{
  rtx desc;
  int pattern_lineno;
  int code; /* not used */
  progname = "genmddump";

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  /* Read the machine description.  */
  while (1)
    {
      desc = read_md_rtx (&pattern_lineno, &code);
      if (desc == NULL)
	break;
      printf (";; %s: %d\n", read_md_filename, pattern_lineno);
      print_inline_rtx (stdout, desc, 0);
      printf ("\n\n");
    }

  fflush (stdout);
  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}
示例#3
0
int
main (int argc, char **argv)
{
  rtx desc;
  bool have_delay = false;
  bool have_sched = false;

  progname = "genattr-common";

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  puts ("/* Generated automatically by the program `genattr-common'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_ATTR_COMMON_H");
  puts ("#define GCC_INSN_ATTR_COMMON_H\n");

  /* Read the machine description.  */

  while (1)
    {
      int line_no, insn_code_number;

      desc = read_md_rtx (&line_no, &insn_code_number);
      if (desc == NULL)
	break;

      if (GET_CODE (desc) == DEFINE_ATTR)
	gen_attr (desc);

      if (GET_CODE (desc) == DEFINE_DELAY)
        {
	  if (!have_delay)
	    {
	      printf ("#define DELAY_SLOTS\n");
	      have_delay = true;
	    }
	}
      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
	{
	  if (!have_sched)
	    {
	      printf ("#define INSN_SCHEDULING\n");
	      have_sched = true;
	    }
	}
    }
  puts ("\n#endif /* GCC_INSN_ATTR_COMMON_H */");

  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
}
示例#4
0
int
main (int argc, char **argv)
{
  rtx desc;
  int pattern_lineno; /* not used */
  int code;

  progname = "genconditions";

  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
    return (FATAL_EXIT_CODE);

  condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL);

  /* Read the machine description.  */

  while (1)
    {
      desc = read_md_rtx (&pattern_lineno, &code);
      if (desc == NULL)
	break;

      /* N.B. define_insn_and_split, define_cond_exec are handled
	 entirely within read_md_rtx; we never see them.  */
      switch (GET_CODE (desc))
	{
	default:
	  break;

	case DEFINE_INSN:
	case DEFINE_EXPAND:
	  add_condition (XSTR (desc, 2));
	  /* except.h needs to know whether there is an eh_return
	     pattern in the machine description.  */
	  if (!strcmp (XSTR (desc, 0), "eh_return"))
	    saw_eh_return = 1;
	  break;

	case DEFINE_SPLIT:
	case DEFINE_PEEPHOLE:
	case DEFINE_PEEPHOLE2:
	  add_condition (XSTR (desc, 1));
	  break;
	}
    }

  write_header ();
  write_conditions ();

  fflush (stdout);
  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}
示例#5
0
int
main (int argc, char **argv)
{
  rtx desc;
  rtx dummy;
  rtx *insns;
  rtx *insn_ptr;

  progname = "genflags";
  obstack_init (&obstack);

  /* We need to see all the possibilities.  Elided insns may have
     direct calls to their generators in C code.  */
  insn_elision = 0;

  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
    return (FATAL_EXIT_CODE);

  puts ("/* Generated automatically by the program `genflags'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_FLAGS_H");
  puts ("#define GCC_INSN_FLAGS_H\n");

  /* Read the machine description.  */

  while (1)
    {
      int line_no, insn_code_number = 0;

      desc = read_md_rtx (&line_no, &insn_code_number);
      if (desc == NULL)
	break;
      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
	gen_insn (desc);
    }

  /* Print out the prototypes now.  */
  dummy = (rtx) 0;
  obstack_grow (&obstack, &dummy, sizeof (rtx));
  insns = (rtx *) obstack_finish (&obstack);

  for (insn_ptr = insns; *insn_ptr; insn_ptr++)
    gen_proto (*insn_ptr);

  puts("\n#endif /* GCC_INSN_FLAGS_H */");

  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
}
示例#6
0
int
main (int argc, char **argv)
{
  bool have_delay = false;
  bool have_sched = false;

  progname = "genattr-common";

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  puts ("/* Generated automatically by the program `genattr-common'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_ATTR_COMMON_H");
  puts ("#define GCC_INSN_ATTR_COMMON_H\n");

  /* Read the machine description.  */

  md_rtx_info info;
  while (read_md_rtx (&info))
    switch (GET_CODE (info.def))
      {
      case DEFINE_ATTR:
	gen_attr (&info);
	break;

      case DEFINE_DELAY:
	have_delay = true;
	break;

      case DEFINE_INSN_RESERVATION:
	if (!have_sched)
	  {
	    printf ("#define INSN_SCHEDULING\n");
	    have_sched = true;
	  }
	break;

      default:
	break;
      }

	    printf ("#define DELAY_SLOTS %d\n", have_delay);
  puts ("\n#endif /* GCC_INSN_ATTR_COMMON_H */");

  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
}
示例#7
0
文件: gencodes.c 项目: wqren/pymc-1
int
main (int argc, char **argv)
{
  rtx desc;

/* BEGIN GCC-XML MODIFICATIONS ($Date: 2007-10-31 15:07:06 $) */
  gccxml_fix_printf();
/* END GCC-XML MODIFICATIONS ($Date: 2007-10-31 15:07:06 $) */

  progname = "gencodes";

  /* We need to see all the possibilities.  Elided insns may have
     direct references to CODE_FOR_xxx in C code.  */
  insn_elision = 0;

  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
    return (FATAL_EXIT_CODE);

  puts ("\
/* Generated automatically by the program `gencodes'\n\
   from the machine description file `md'.  */\n\
\n\
#ifndef GCC_INSN_CODES_H\n\
#define GCC_INSN_CODES_H\n\
\n\
enum insn_code {");

  /* Read the machine description.  */

  while (1)
    {
      int line_no;
      int insn_code_number;

      desc = read_md_rtx (&line_no, &insn_code_number);
      if (desc == NULL)
        break;

      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
        gen_insn (desc, insn_code_number);
    }

  puts ("  CODE_FOR_nothing\n\
};\n\
示例#8
0
文件: genmddump.c 项目: 0day-ci/gcc
int
main (int argc, char **argv)
{
  progname = "genmddump";

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  /* Read the machine description.  */
  md_rtx_info info;
  while (read_md_rtx (&info))
    {
      printf (";; %s: %d\n", info.loc.filename, info.loc.lineno);
      print_inline_rtx (stdout, info.def, 0);
      printf ("\n\n");
    }

  fflush (stdout);
  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
}
示例#9
0
int
main (int argc, char **argv)
{
  rtx desc;

  progname = "gencodes";

  /* We need to see all the possibilities.  Elided insns may have
     direct references to CODE_FOR_xxx in C code.  */
  insn_elision = 0;

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  puts ("\
/* Generated automatically by the program `gencodes'\n\
   from the machine description file `md'.  */\n\
\n\
#ifndef GCC_INSN_CODES_H\n\
#define GCC_INSN_CODES_H\n\
\n\
enum insn_code {\n\
  CODE_FOR_nothing = 0,\n");

  /* Read the machine description.  */

  while (1)
    {
      int line_no;
      int insn_code_number;

      desc = read_md_rtx (&line_no, &insn_code_number);
      if (desc == NULL)
	break;

      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
	gen_insn (desc, insn_code_number);
    }

  puts ("  LAST_INSN_CODE\n\
};\n\
示例#10
0
int
main (int argc, char **argv)
{
    FILE *h_file, *s_file;
    unsigned int i, j, n, last_kind[5];
    pattern *p;

    progname = "genopinit";

    if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
        fatal ("genopinit range assumptions invalid");

    if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
        return (FATAL_EXIT_CODE);

    h_file = open_outfile (header_file_name);
    s_file = open_outfile (source_file_name);

    /* Read the machine description.  */
    while (1)
    {
        int line_no, insn_code_number = 0;
        rtx desc = read_md_rtx (&line_no, &insn_code_number);
        if (desc == NULL)
            break;
        if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
            gen_insn (desc);
    }

    /* Sort the collected patterns.  */
    qsort (patterns.address (), patterns.length (),
           sizeof (pattern), pattern_cmp);

    /* Now that we've handled the "extra" patterns, eliminate them from
       the optabs array.  That way they don't get in the way below.  */
    n = ARRAY_SIZE (optabs);
    for (i = 0; i < n; )
        if (optabs[i].base == NULL)
            optabs[i] = optabs[--n];
        else
            ++i;

    /* Sort the (real) optabs.  Better than forcing the optabs.def file to
       remain sorted by kind.  We also scrogged any real ordering with the
       purging of the X patterns above.  */
    qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);

    /* Emit the optab enumeration for the header file.  */
    fprintf (h_file, "enum optab_tag {\n");
    for (i = j = 0; i < n; ++i)
    {
        optabs[i].op = i;
        fprintf (h_file, "  %s,\n", optabs[i].name);
        if (optabs[i].kind != j)
            last_kind[j++] = i - 1;
    }
    fprintf (h_file, "  FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
    fprintf (h_file, "  LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
    fprintf (h_file, "  LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
    fprintf (h_file, "  FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
    fprintf (h_file, "  LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
    fprintf (h_file, "  LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
    fprintf (h_file, "};\n\n");

    fprintf (h_file, "#define NUM_OPTABS          %u\n", n);
    fprintf (h_file, "#define NUM_CONVLIB_OPTABS  %u\n",
             last_kind[1] - last_kind[0]);
    fprintf (h_file, "#define NUM_NORMLIB_OPTABS  %u\n",
             last_kind[3] - last_kind[2]);
    fprintf (h_file, "#define NUM_OPTAB_PATTERNS  %u\n",
             (unsigned) patterns.length ());

    fprintf (s_file,
             "#include \"config.h\"\n"
             "#include \"system.h\"\n"
             "#include \"coretypes.h\"\n"
             "#include \"tm.h\"\n"
             "#include \"rtl.h\"\n"
             "#include \"tm_p.h\"\n"
             "#include \"flags.h\"\n"
             "#include \"insn-config.h\"\n"
             "#include \"expr.h\"\n"
             "#include \"optabs.h\"\n"
             "\n"
             "struct optab_pat {\n"
             "  unsigned scode;\n"
             "  enum insn_code icode;\n"
             "};\n\n");

    fprintf (s_file,
             "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
    for (i = 0; patterns.iterate (i, &p); ++i)
        fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
    fprintf (s_file, "};\n\n");

    fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
    fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
    for (i = 0; patterns.iterate (i, &p); ++i)
        fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
    fprintf (s_file, "}\n\n");

    /* Perform a binary search on a pre-encoded optab+mode*2.  */
    /* ??? Perhaps even better to generate a minimal perfect hash.
       Using gperf directly is awkward since it's so geared to working
       with strings.  Plus we have no visibility into the ordering of
       the hash entries, which complicates the pat_enable array.  */
    fprintf (s_file,
             "static int\n"
             "lookup_handler (unsigned scode)\n"
             "{\n"
             "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
             "  while (h > l)\n"
             "    {\n"
             "      m = (h + l) / 2;\n"
             "      if (scode == pats[m].scode)\n"
             "        return m;\n"
             "      else if (scode < pats[m].scode)\n"
             "        h = m;\n"
             "      else\n"
             "        l = m + 1;\n"
             "    }\n"
             "  return -1;\n"
             "}\n\n");

    fprintf (s_file,
             "enum insn_code\n"
             "raw_optab_handler (unsigned scode)\n"
             "{\n"
             "  int i = lookup_handler (scode);\n"
             "  return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
             "          ? pats[i].icode : CODE_FOR_nothing);\n"
             "}\n\n");

    fprintf (s_file,
             "bool\n"
             "swap_optab_enable (optab op, enum machine_mode m, bool set)\n"
             "{\n"
             "  unsigned scode = (op << 16) | m;\n"
             "  int i = lookup_handler (scode);\n"
             "  if (i >= 0)\n"
             "    {\n"
             "      bool ret = this_fn_optabs->pat_enable[i];\n"
             "      this_fn_optabs->pat_enable[i] = set;\n"
             "      return ret;\n"
             "    }\n"
             "  else\n"
             "    {\n"
             "      gcc_assert (!set);\n"
             "      return false;\n"
             "    }\n"
             "}\n\n");

    /* C++ (even G++) does not support (non-trivial) designated initializers.
       To work around that, generate these arrays programatically rather than
       by our traditional multiple inclusion of def files.  */

    fprintf (s_file,
             "const struct convert_optab_libcall_d "
             "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
    for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
        fprintf (s_file, "  { %s, %s },\n", optabs[i].base, optabs[i].libcall);
    fprintf (s_file, "};\n\n");

    fprintf (s_file,
             "const struct optab_libcall_d "
             "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
    for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
        fprintf (s_file, "  { %s, %s, %s },\n",
                 optabs[i].suffix, optabs[i].base, optabs[i].libcall);
    fprintf (s_file, "};\n\n");

    fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
    for (i = 0; i < n; ++i)
        fprintf (s_file, "  %s,\n", rtx_upname[optabs[i].fcode]);
    fprintf (s_file, "};\n\n");

    qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);

    fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
    for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
        continue;
    for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
    {
        if (j < n && optabs[j].rcode == i)
            fprintf (s_file, "  %s,\n", optabs[j++].name);
        else
            fprintf (s_file, "  unknown_optab,\n");
    }
    fprintf (s_file, "};\n\n");

    return (fclose (h_file) == 0 && fclose (s_file) == 0
            ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
}
示例#11
0
int
main (int argc, const char **argv)
{
  progname = "genconfig";

  if (!init_rtx_reader_args (argc, argv))
    return (FATAL_EXIT_CODE);

  puts ("/* Generated automatically by the program `genconfig'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_CONFIG_H");
  puts ("#define GCC_INSN_CONFIG_H\n");

  /* Allow at least 30 operands for the sake of asm constructs.  */
  /* ??? We *really* ought to reorganize things such that there
     is no fixed upper bound.  */
  max_recog_operands = 29;  /* We will add 1 later.  */
  max_dup_operands = 1;

  /* Read the machine description.  */

  md_rtx_info info;
  while (read_md_rtx (&info))
    switch (GET_CODE (info.def))
      {
      case DEFINE_INSN:
	gen_insn (&info);
	break;

      case DEFINE_EXPAND:
	gen_expand (&info);
	break;

      case DEFINE_SPLIT:
	gen_split (&info);
	break;

      case DEFINE_PEEPHOLE2:
	have_peephole2_flag = 1;
	gen_peephole2 (&info);
	break;

      case DEFINE_PEEPHOLE:
	have_peephole_flag = 1;
	gen_peephole (&info);
	break;

      default:
	break;
      }

  printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
  printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);

  /* This is conditionally defined, in case the user writes code which emits
     more splits than we can readily see (and knows s/he does it).  */
  printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
  printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
  printf ("#endif\n");

  if (have_cc0_flag)
    {
      printf ("#define HAVE_cc0 1\n");
      printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
    }
  else
    {
      /* We output CC0_P this way to make sure that X is declared
	 somewhere.  */
      printf ("#define HAVE_cc0 0\n");
      printf ("#define CC0_P(X) ((X) ? 0 : 0)\n");
    }

  if (have_cmove_flag)
    printf ("#define HAVE_conditional_move 1\n");
  else
    printf ("#define HAVE_conditional_move 0\n");

  if (have_cond_exec_flag)
    printf ("#define HAVE_conditional_execution 1\n");
  else
    printf ("#define HAVE_conditional_execution 0\n");

  if (have_lo_sum_flag)
    printf ("#define HAVE_lo_sum 1\n");
  else
    printf ("#define HAVE_lo_sum 0\n");

  if (have_rotate_flag)
    printf ("#define HAVE_rotate 1\n");

  if (have_rotatert_flag)
    printf ("#define HAVE_rotatert 1\n");

  if (have_peephole_flag)
    printf ("#define HAVE_peephole 1\n");
  else
    printf ("#define HAVE_peephole 0\n");

  if (have_peephole2_flag)
    {
      printf ("#define HAVE_peephole2 1\n");
      printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
    }
  else
    {
      printf ("#define HAVE_peephole2 0\n");
      printf ("#define MAX_INSNS_PER_PEEP2 0\n");
    }

  puts ("\n#endif /* GCC_INSN_CONFIG_H */");

  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
}
示例#12
0
文件: genopinit.c 项目: 0day-ci/gcc
int
main (int argc, char **argv)
{
  FILE *h_file, *s_file;
  unsigned int i, j, n, last_kind[5];
  optab_pattern *p;

  progname = "genopinit";

  if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
    fatal ("genopinit range assumptions invalid");

  if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
    return (FATAL_EXIT_CODE);

  h_file = open_outfile (header_file_name);
  s_file = open_outfile (source_file_name);

  /* Read the machine description.  */
  md_rtx_info info;
  while (read_md_rtx (&info))
    switch (GET_CODE (info.def))
      {
      case DEFINE_INSN:
      case DEFINE_EXPAND:
	gen_insn (&info);
	break;

      default:
	break;
      }

  /* Sort the collected patterns.  */
  patterns.qsort (pattern_cmp);

  /* Now that we've handled the "extra" patterns, eliminate them from
     the optabs array.  That way they don't get in the way below.  */
  n = num_optabs;
  for (i = 0; i < n; )
    if (optabs[i].base == NULL)
      optabs[i] = optabs[--n];
    else
      ++i;

  /* Sort the (real) optabs.  Better than forcing the optabs.def file to
     remain sorted by kind.  We also scrogged any real ordering with the
     purging of the X patterns above.  */
  qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);

  fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
  fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");

  /* Emit the optab enumeration for the header file.  */
  fprintf (h_file, "enum optab_tag {\n");
  for (i = j = 0; i < n; ++i)
    {
      optabs[i].op = i;
      fprintf (h_file, "  %s,\n", optabs[i].name);
      if (optabs[i].kind != j)
	last_kind[j++] = i - 1;
    }
  fprintf (h_file, "  FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
  fprintf (h_file, "  LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
  fprintf (h_file, "  LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
  fprintf (h_file, "  FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
  fprintf (h_file, "  LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
  fprintf (h_file, "  LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
  fprintf (h_file, "};\n\n");

  fprintf (h_file, "#define NUM_OPTABS          %u\n", n);
  fprintf (h_file, "#define NUM_CONVLIB_OPTABS  %u\n",
	   last_kind[1] - last_kind[0]);
  fprintf (h_file, "#define NUM_NORMLIB_OPTABS  %u\n",
	   last_kind[3] - last_kind[2]);
  fprintf (h_file, "#define NUM_OPTAB_PATTERNS  %u\n",
	   (unsigned) patterns.length ());

  fprintf (h_file, 
	   "typedef enum optab_tag optab;\n"
	   "typedef enum optab_tag convert_optab;\n"
	   "typedef enum optab_tag direct_optab;\n"
	   "\n"
	   "struct optab_libcall_d\n"
	   "{\n"
	   "  char libcall_suffix;\n"
	   "  const char *libcall_basename;\n"
	   "  void (*libcall_gen) (optab, const char *name,\n"
	   "		       char suffix, machine_mode);\n"
	   "};\n"
	   "\n"
	   "struct convert_optab_libcall_d\n"
	   "{\n"
	   "  const char *libcall_basename;\n"
	   "  void (*libcall_gen) (convert_optab, const char *name,\n"
	   "		       machine_mode, machine_mode);\n"
	   "};\n"
	   "\n"
	   "/* Given an enum insn_code, access the function to construct\n"
	   "   the body of that kind of insn.  */\n"
	   "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
	   "\n"
	   "#ifdef NUM_RTX_CODE\n"
	   "/* Contains the optab used for each rtx code, and vice-versa.  */\n"
	   "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
	   "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
	   "\n"
	   "static inline optab\n"
	   "code_to_optab (enum rtx_code code)\n"
	   "{\n"
	   "  return code_to_optab_[code];\n"
	   "}\n"
	   "\n"
	   "static inline enum rtx_code\n"
	   "optab_to_code (optab op)\n"
	   "{\n"
	   "  return optab_to_code_[op];\n"
	   "}\n"
	   "#endif\n"
	   "\n"
	   "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
	   "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
	   "\n"
	   "/* Returns the active icode for the given (encoded) optab.  */\n"
	   "extern enum insn_code raw_optab_handler (unsigned);\n"
	   "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
	   "\n"
	   "/* Target-dependent globals.  */\n"
	   "struct target_optabs {\n"
	   "  /* Patterns that are used by optabs that are enabled for this target.  */\n"
	   "  bool pat_enable[NUM_OPTAB_PATTERNS];\n"
	   "};\n"
	   "extern void init_all_optabs (struct target_optabs *);\n"
	   "\n"
	   "extern struct target_optabs default_target_optabs;\n"
	   "extern struct target_optabs *this_fn_optabs;\n"
	   "#if SWITCHABLE_TARGET\n"
	   "extern struct target_optabs *this_target_optabs;\n"
	   "#else\n"
	   "#define this_target_optabs (&default_target_optabs)\n"
	   "#endif\n");

  fprintf (s_file,
	   "#include \"config.h\"\n"
	   "#include \"system.h\"\n"
	   "#include \"coretypes.h\"\n"
	   "#include \"backend.h\"\n"
	   "#include \"predict.h\"\n"
	   "#include \"tree.h\"\n"
	   "#include \"rtl.h\"\n"
	   "#include \"alias.h\"\n"
	   "#include \"varasm.h\"\n"
	   "#include \"stor-layout.h\"\n"
	   "#include \"calls.h\"\n"
	   "#include \"tm_p.h\"\n"
	   "#include \"flags.h\"\n"
	   "#include \"insn-config.h\"\n"
	   "#include \"expmed.h\"\n"
	   "#include \"dojump.h\"\n"
	   "#include \"explow.h\"\n"
	   "#include \"emit-rtl.h\"\n"
	   "#include \"stmt.h\"\n"
	   "#include \"expr.h\"\n"
	   "#include \"insn-codes.h\"\n"
	   "#include \"optabs.h\"\n"
	   "\n"
	   "struct optab_pat {\n"
	   "  unsigned scode;\n"
	   "  enum insn_code icode;\n"
	   "};\n\n");

  fprintf (s_file,
	   "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
  for (i = 0; patterns.iterate (i, &p); ++i)
    fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
  fprintf (s_file, "};\n\n");

  fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
  fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
  for (i = 0; patterns.iterate (i, &p); ++i)
    fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
  fprintf (s_file, "}\n\n");

  /* Perform a binary search on a pre-encoded optab+mode*2.  */
  /* ??? Perhaps even better to generate a minimal perfect hash.
     Using gperf directly is awkward since it's so geared to working
     with strings.  Plus we have no visibility into the ordering of
     the hash entries, which complicates the pat_enable array.  */
  fprintf (s_file,
	   "static int\n"
	   "lookup_handler (unsigned scode)\n"
	   "{\n"
	   "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
	   "  while (h > l)\n"
	   "    {\n"
	   "      m = (h + l) / 2;\n"
	   "      if (scode == pats[m].scode)\n"
	   "        return m;\n"
	   "      else if (scode < pats[m].scode)\n"
	   "        h = m;\n"
	   "      else\n"
	   "        l = m + 1;\n"
	   "    }\n"
	   "  return -1;\n"
	   "}\n\n");

  fprintf (s_file,
	   "enum insn_code\n"
	   "raw_optab_handler (unsigned scode)\n"
	   "{\n"
	   "  int i = lookup_handler (scode);\n"
	   "  return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
	   "          ? pats[i].icode : CODE_FOR_nothing);\n"
	   "}\n\n");

  fprintf (s_file,
	   "bool\n"
	   "swap_optab_enable (optab op, machine_mode m, bool set)\n"
	   "{\n"
	   "  unsigned scode = (op << 16) | m;\n"
	   "  int i = lookup_handler (scode);\n"
	   "  if (i >= 0)\n"
	   "    {\n"
	   "      bool ret = this_fn_optabs->pat_enable[i];\n"
	   "      this_fn_optabs->pat_enable[i] = set;\n"
	   "      return ret;\n"
	   "    }\n"
	   "  else\n"
	   "    {\n"
	   "      gcc_assert (!set);\n"
	   "      return false;\n"
	   "    }\n"
	   "}\n\n");

  /* C++ (even G++) does not support (non-trivial) designated initializers.
     To work around that, generate these arrays programatically rather than
     by our traditional multiple inclusion of def files.  */

  fprintf (s_file,
	   "const struct convert_optab_libcall_d "
	   "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
  for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
    fprintf (s_file, "  { %s, %s },\n", optabs[i].base, optabs[i].libcall);
  fprintf (s_file, "};\n\n");

  fprintf (s_file,
	   "const struct optab_libcall_d "
	   "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
  for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
    fprintf (s_file, "  { %s, %s, %s },\n",
	     optabs[i].suffix, optabs[i].base, optabs[i].libcall);
  fprintf (s_file, "};\n\n");

  fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
  for (i = 0; i < n; ++i)
    fprintf (s_file, "  %s,\n", rtx_upname[optabs[i].fcode]);
  fprintf (s_file, "};\n\n");

  qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);

  fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
  for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
    continue;
  for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
    {
      if (j < n && optabs[j].rcode == i)
	fprintf (s_file, "  %s,\n", optabs[j++].name);
      else
	fprintf (s_file, "  unknown_optab,\n");
    }
  fprintf (s_file, "};\n\n");

  fprintf (h_file, "#endif\n");
  return (fclose (h_file) == 0 && fclose (s_file) == 0
	  ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
}