static tree make_fndecl (tree return_type, const char *name, vec <tree> ¶m_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; }
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); }