Example #1
0
static tree
make_fndecl (tree return_type,
	     const char *name,
	     vec <tree> &param_types,
	     bool is_variadic = false)
{
  tree fn_type;
  if (is_variadic)
    fn_type = build_varargs_function_type_array (return_type,
						 param_types.length (),
						 param_types.address ());
  else
    fn_type = build_function_type_array (return_type,
					 param_types.length (),
					 param_types.address ());
  /* FIXME: this uses input_location: */
  tree fndecl = build_fn_decl (name, fn_type);

  return fndecl;
}
Example #2
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);
}