xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/genopinit.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Generate code to initialize optabs from machine description.
2*8feb0f0bSmrg    Copyright (C) 1993-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3.  If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>.  */
191debfc3dSmrg 
201debfc3dSmrg 
211debfc3dSmrg #include "bconfig.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "tm.h"
251debfc3dSmrg #include "rtl.h"
261debfc3dSmrg #include "errors.h"
271debfc3dSmrg #include "gensupport.h"
281debfc3dSmrg 
291debfc3dSmrg 
301debfc3dSmrg #define DEF_RTL_EXPR(V, N, X, C) #V,
311debfc3dSmrg 
321debfc3dSmrg static const char * const rtx_upname[] = {
331debfc3dSmrg #include "rtl.def"
341debfc3dSmrg };
351debfc3dSmrg 
361debfc3dSmrg #undef DEF_RTL_EXPR
371debfc3dSmrg 
381debfc3dSmrg /* Vector in which to collect insns that match.  */
391debfc3dSmrg static vec<optab_pattern> patterns;
401debfc3dSmrg 
411debfc3dSmrg static void
gen_insn(md_rtx_info * info)421debfc3dSmrg gen_insn (md_rtx_info *info)
431debfc3dSmrg {
441debfc3dSmrg   optab_pattern p;
451debfc3dSmrg   if (find_optab (&p, XSTR (info->def, 0)))
461debfc3dSmrg     patterns.safe_push (p);
471debfc3dSmrg }
481debfc3dSmrg 
491debfc3dSmrg static int
pattern_cmp(const void * va,const void * vb)501debfc3dSmrg pattern_cmp (const void *va, const void *vb)
511debfc3dSmrg {
521debfc3dSmrg   const optab_pattern *a = (const optab_pattern *)va;
531debfc3dSmrg   const optab_pattern *b = (const optab_pattern *)vb;
541debfc3dSmrg   return a->sort_num - b->sort_num;
551debfc3dSmrg }
561debfc3dSmrg 
571debfc3dSmrg static int
optab_kind_cmp(const void * va,const void * vb)581debfc3dSmrg optab_kind_cmp (const void *va, const void *vb)
591debfc3dSmrg {
601debfc3dSmrg   const optab_def *a = (const optab_def *)va;
611debfc3dSmrg   const optab_def *b = (const optab_def *)vb;
621debfc3dSmrg   int diff = a->kind - b->kind;
631debfc3dSmrg   if (diff == 0)
641debfc3dSmrg     diff = a->op - b->op;
651debfc3dSmrg   return diff;
661debfc3dSmrg }
671debfc3dSmrg 
681debfc3dSmrg static int
optab_rcode_cmp(const void * va,const void * vb)691debfc3dSmrg optab_rcode_cmp (const void *va, const void *vb)
701debfc3dSmrg {
711debfc3dSmrg   const optab_def *a = (const optab_def *)va;
721debfc3dSmrg   const optab_def *b = (const optab_def *)vb;
731debfc3dSmrg   return a->rcode - b->rcode;
741debfc3dSmrg }
751debfc3dSmrg 
761debfc3dSmrg static const char *header_file_name = "init-opinit.h";
771debfc3dSmrg static const char *source_file_name = "init-opinit.c";
781debfc3dSmrg 
791debfc3dSmrg static bool
handle_arg(const char * arg)801debfc3dSmrg handle_arg (const char *arg)
811debfc3dSmrg {
821debfc3dSmrg   switch (arg[1])
831debfc3dSmrg     {
841debfc3dSmrg     case 'h':
851debfc3dSmrg       header_file_name = &arg[2];
861debfc3dSmrg       return true;
871debfc3dSmrg     case 'c':
881debfc3dSmrg       source_file_name = &arg[2];
891debfc3dSmrg       return true;
901debfc3dSmrg     default:
911debfc3dSmrg       return false;
921debfc3dSmrg     }
931debfc3dSmrg }
941debfc3dSmrg 
951debfc3dSmrg static FILE *
open_outfile(const char * file_name)961debfc3dSmrg open_outfile (const char *file_name)
971debfc3dSmrg {
981debfc3dSmrg   FILE *f = fopen (file_name, "w");
991debfc3dSmrg   if (!f)
1001debfc3dSmrg     fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
1011debfc3dSmrg   fprintf (f,
1021debfc3dSmrg 	   "/* Generated automatically by the program `genopinit'\n"
1031debfc3dSmrg 	   "   from the machine description file `md'.  */\n\n");
1041debfc3dSmrg   return f;
1051debfc3dSmrg }
1061debfc3dSmrg 
107c0a68be4Smrg /* Declare the maybe_code_for_* function for ONAME, and provide
108c0a68be4Smrg    an inline definition of the assserting code_for_* wrapper.  */
109c0a68be4Smrg 
110c0a68be4Smrg static void
handle_overloaded_code_for(FILE * file,overloaded_name * oname)111c0a68be4Smrg handle_overloaded_code_for (FILE *file, overloaded_name *oname)
112c0a68be4Smrg {
113c0a68be4Smrg   fprintf (file, "\nextern insn_code maybe_code_for_%s (", oname->name);
114c0a68be4Smrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
115c0a68be4Smrg     fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
116c0a68be4Smrg   fprintf (file, ");\n");
117c0a68be4Smrg 
118c0a68be4Smrg   fprintf (file, "inline insn_code\ncode_for_%s (", oname->name);
119c0a68be4Smrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
120c0a68be4Smrg     fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
121c0a68be4Smrg   fprintf (file, ")\n{\n  insn_code code = maybe_code_for_%s (", oname->name);
122c0a68be4Smrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
123c0a68be4Smrg     fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
124c0a68be4Smrg   fprintf (file,
125c0a68be4Smrg 	   ");\n"
126c0a68be4Smrg 	   "  gcc_assert (code != CODE_FOR_nothing);\n"
127c0a68be4Smrg 	   "  return code;\n"
128c0a68be4Smrg 	   "}\n");
129c0a68be4Smrg }
130c0a68be4Smrg 
131c0a68be4Smrg /* Declare the maybe_gen_* function for ONAME, and provide
132c0a68be4Smrg    an inline definition of the assserting gen_* wrapper.  */
133c0a68be4Smrg 
134c0a68be4Smrg static void
handle_overloaded_gen(FILE * file,overloaded_name * oname)135c0a68be4Smrg handle_overloaded_gen (FILE *file, overloaded_name *oname)
136c0a68be4Smrg {
137*8feb0f0bSmrg   unsigned HOST_WIDE_INT seen = 0;
138*8feb0f0bSmrg   for (overloaded_instance *instance = oname->first_instance->next;
139*8feb0f0bSmrg        instance; instance = instance->next)
140*8feb0f0bSmrg     {
141c0a68be4Smrg       pattern_stats stats;
142*8feb0f0bSmrg       get_pattern_stats (&stats, XVEC (instance->insn, 1));
143*8feb0f0bSmrg       unsigned HOST_WIDE_INT mask
144*8feb0f0bSmrg 	= HOST_WIDE_INT_1U << stats.num_generator_args;
145*8feb0f0bSmrg       if (seen & mask)
146*8feb0f0bSmrg 	continue;
147*8feb0f0bSmrg 
148*8feb0f0bSmrg       seen |= mask;
149c0a68be4Smrg 
150c0a68be4Smrg       fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
151c0a68be4Smrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
152c0a68be4Smrg 	fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
153c0a68be4Smrg       for (int i = 0; i < stats.num_generator_args; ++i)
154c0a68be4Smrg 	fprintf (file, ", rtx");
155c0a68be4Smrg       fprintf (file, ");\n");
156c0a68be4Smrg 
157c0a68be4Smrg       fprintf (file, "inline rtx\ngen_%s (", oname->name);
158c0a68be4Smrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
159*8feb0f0bSmrg 	fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ",
160*8feb0f0bSmrg 		 oname->arg_types[i], i);
161c0a68be4Smrg       for (int i = 0; i < stats.num_generator_args; ++i)
162c0a68be4Smrg 	fprintf (file, ", rtx x%d", i);
163c0a68be4Smrg       fprintf (file, ")\n{\n  rtx res = maybe_gen_%s (", oname->name);
164c0a68be4Smrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
165c0a68be4Smrg 	fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
166c0a68be4Smrg       for (int i = 0; i < stats.num_generator_args; ++i)
167c0a68be4Smrg 	fprintf (file, ", x%d", i);
168c0a68be4Smrg       fprintf (file,
169c0a68be4Smrg 	       ");\n"
170c0a68be4Smrg 	       "  gcc_assert (res);\n"
171c0a68be4Smrg 	       "  return res;\n"
172c0a68be4Smrg 	       "}\n");
173c0a68be4Smrg     }
174*8feb0f0bSmrg }
175c0a68be4Smrg 
1761debfc3dSmrg int
main(int argc,const char ** argv)1771debfc3dSmrg main (int argc, const char **argv)
1781debfc3dSmrg {
1791debfc3dSmrg   FILE *h_file, *s_file;
1801debfc3dSmrg   unsigned int i, j, n, last_kind[5];
1811debfc3dSmrg   optab_pattern *p;
1821debfc3dSmrg 
1831debfc3dSmrg   progname = "genopinit";
1841debfc3dSmrg 
1851debfc3dSmrg   if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
1861debfc3dSmrg     fatal ("genopinit range assumptions invalid");
1871debfc3dSmrg 
1881debfc3dSmrg   if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
1891debfc3dSmrg     return (FATAL_EXIT_CODE);
1901debfc3dSmrg 
1911debfc3dSmrg   h_file = open_outfile (header_file_name);
1921debfc3dSmrg   s_file = open_outfile (source_file_name);
1931debfc3dSmrg 
1941debfc3dSmrg   /* Read the machine description.  */
1951debfc3dSmrg   md_rtx_info info;
1961debfc3dSmrg   while (read_md_rtx (&info))
1971debfc3dSmrg     switch (GET_CODE (info.def))
1981debfc3dSmrg       {
1991debfc3dSmrg       case DEFINE_INSN:
2001debfc3dSmrg       case DEFINE_EXPAND:
2011debfc3dSmrg 	gen_insn (&info);
2021debfc3dSmrg 	break;
2031debfc3dSmrg 
2041debfc3dSmrg       default:
2051debfc3dSmrg 	break;
2061debfc3dSmrg       }
2071debfc3dSmrg 
2081debfc3dSmrg   /* Sort the collected patterns.  */
2091debfc3dSmrg   patterns.qsort (pattern_cmp);
2101debfc3dSmrg 
2111debfc3dSmrg   /* Now that we've handled the "extra" patterns, eliminate them from
2121debfc3dSmrg      the optabs array.  That way they don't get in the way below.  */
2131debfc3dSmrg   n = num_optabs;
2141debfc3dSmrg   for (i = 0; i < n; )
2151debfc3dSmrg     if (optabs[i].base == NULL)
2161debfc3dSmrg       optabs[i] = optabs[--n];
2171debfc3dSmrg     else
2181debfc3dSmrg       ++i;
2191debfc3dSmrg 
2201debfc3dSmrg   /* Sort the (real) optabs.  Better than forcing the optabs.def file to
2211debfc3dSmrg      remain sorted by kind.  We also scrogged any real ordering with the
2221debfc3dSmrg      purging of the X patterns above.  */
2231debfc3dSmrg   qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
2241debfc3dSmrg 
2251debfc3dSmrg   fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
2261debfc3dSmrg   fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
2271debfc3dSmrg 
2281debfc3dSmrg   /* Emit the optab enumeration for the header file.  */
2291debfc3dSmrg   fprintf (h_file, "enum optab_tag {\n");
2301debfc3dSmrg   for (i = j = 0; i < n; ++i)
2311debfc3dSmrg     {
2321debfc3dSmrg       optabs[i].op = i;
2331debfc3dSmrg       fprintf (h_file, "  %s,\n", optabs[i].name);
2341debfc3dSmrg       if (optabs[i].kind != j)
2351debfc3dSmrg 	last_kind[j++] = i - 1;
2361debfc3dSmrg     }
2371debfc3dSmrg   fprintf (h_file, "  FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
2381debfc3dSmrg   fprintf (h_file, "  LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
2391debfc3dSmrg   fprintf (h_file, "  LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
2401debfc3dSmrg   fprintf (h_file, "  FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
2411debfc3dSmrg   fprintf (h_file, "  LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
2421debfc3dSmrg   fprintf (h_file, "  LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
2431debfc3dSmrg   fprintf (h_file, "};\n\n");
2441debfc3dSmrg 
2451debfc3dSmrg   fprintf (h_file, "#define NUM_OPTABS          %u\n", n);
2461debfc3dSmrg   fprintf (h_file, "#define NUM_CONVLIB_OPTABS  %u\n",
2471debfc3dSmrg 	   last_kind[1] - last_kind[0]);
2481debfc3dSmrg   fprintf (h_file, "#define NUM_NORMLIB_OPTABS  %u\n",
2491debfc3dSmrg 	   last_kind[3] - last_kind[2]);
2501debfc3dSmrg   fprintf (h_file, "#define NUM_OPTAB_PATTERNS  %u\n",
2511debfc3dSmrg 	   (unsigned) patterns.length ());
2521debfc3dSmrg 
2531debfc3dSmrg   fprintf (h_file,
2541debfc3dSmrg 	   "typedef enum optab_tag optab;\n"
2551debfc3dSmrg 	   "typedef enum optab_tag convert_optab;\n"
2561debfc3dSmrg 	   "typedef enum optab_tag direct_optab;\n"
2571debfc3dSmrg 	   "\n"
2581debfc3dSmrg 	   "struct optab_libcall_d\n"
2591debfc3dSmrg 	   "{\n"
2601debfc3dSmrg 	   "  char libcall_suffix;\n"
2611debfc3dSmrg 	   "  const char *libcall_basename;\n"
2621debfc3dSmrg 	   "  void (*libcall_gen) (optab, const char *name,\n"
2631debfc3dSmrg 	   "		       char suffix, machine_mode);\n"
2641debfc3dSmrg 	   "};\n"
2651debfc3dSmrg 	   "\n"
2661debfc3dSmrg 	   "struct convert_optab_libcall_d\n"
2671debfc3dSmrg 	   "{\n"
2681debfc3dSmrg 	   "  const char *libcall_basename;\n"
2691debfc3dSmrg 	   "  void (*libcall_gen) (convert_optab, const char *name,\n"
2701debfc3dSmrg 	   "		       machine_mode, machine_mode);\n"
2711debfc3dSmrg 	   "};\n"
2721debfc3dSmrg 	   "\n"
2731debfc3dSmrg 	   "/* Given an enum insn_code, access the function to construct\n"
2741debfc3dSmrg 	   "   the body of that kind of insn.  */\n"
2751debfc3dSmrg 	   "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
2761debfc3dSmrg 	   "\n"
2771debfc3dSmrg 	   "#ifdef NUM_RTX_CODE\n"
2781debfc3dSmrg 	   "/* Contains the optab used for each rtx code, and vice-versa.  */\n"
2791debfc3dSmrg 	   "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
2801debfc3dSmrg 	   "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
2811debfc3dSmrg 	   "\n"
2821debfc3dSmrg 	   "static inline optab\n"
2831debfc3dSmrg 	   "code_to_optab (enum rtx_code code)\n"
2841debfc3dSmrg 	   "{\n"
2851debfc3dSmrg 	   "  return code_to_optab_[code];\n"
2861debfc3dSmrg 	   "}\n"
2871debfc3dSmrg 	   "\n"
2881debfc3dSmrg 	   "static inline enum rtx_code\n"
2891debfc3dSmrg 	   "optab_to_code (optab op)\n"
2901debfc3dSmrg 	   "{\n"
2911debfc3dSmrg 	   "  return optab_to_code_[op];\n"
292c0a68be4Smrg 	   "}\n");
293c0a68be4Smrg 
294c0a68be4Smrg   for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
295c0a68be4Smrg        oname; oname = oname->next)
296c0a68be4Smrg     {
297c0a68be4Smrg       handle_overloaded_code_for (h_file, oname);
298c0a68be4Smrg       handle_overloaded_gen (h_file, oname);
299c0a68be4Smrg     }
300c0a68be4Smrg 
301c0a68be4Smrg   fprintf (h_file,
3021debfc3dSmrg 	   "#endif\n"
3031debfc3dSmrg 	   "\n"
3041debfc3dSmrg 	   "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
3051debfc3dSmrg 	   "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
3061debfc3dSmrg 	   "\n"
3071debfc3dSmrg 	   "/* Returns the active icode for the given (encoded) optab.  */\n"
3081debfc3dSmrg 	   "extern enum insn_code raw_optab_handler (unsigned);\n"
3091debfc3dSmrg 	   "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
3101debfc3dSmrg 	   "\n"
3111debfc3dSmrg 	   "/* Target-dependent globals.  */\n"
3121debfc3dSmrg 	   "struct target_optabs {\n"
3131debfc3dSmrg 	   "  /* Patterns that are used by optabs that are enabled for this target.  */\n"
3141debfc3dSmrg 	   "  bool pat_enable[NUM_OPTAB_PATTERNS];\n"
315a2dc1f3fSmrg 	   "\n"
316a2dc1f3fSmrg 	   "  /* Cache if the target supports vec_gather_load for at least one vector\n"
317a2dc1f3fSmrg 	   "     mode.  */\n"
318a2dc1f3fSmrg 	   "  bool supports_vec_gather_load;\n"
319a2dc1f3fSmrg 	   "  bool supports_vec_gather_load_cached;\n"
320a2dc1f3fSmrg 	   "  bool supports_vec_scatter_store;\n"
321a2dc1f3fSmrg 	   "  bool supports_vec_scatter_store_cached;\n"
3221debfc3dSmrg 	   "};\n"
3231debfc3dSmrg 	   "extern void init_all_optabs (struct target_optabs *);\n"
3241debfc3dSmrg 	   "\n"
3251debfc3dSmrg 	   "extern struct target_optabs default_target_optabs;\n"
3261debfc3dSmrg 	   "extern struct target_optabs *this_fn_optabs;\n"
3271debfc3dSmrg 	   "#if SWITCHABLE_TARGET\n"
3281debfc3dSmrg 	   "extern struct target_optabs *this_target_optabs;\n"
3291debfc3dSmrg 	   "#else\n"
3301debfc3dSmrg 	   "#define this_target_optabs (&default_target_optabs)\n"
3311debfc3dSmrg 	   "#endif\n");
3321debfc3dSmrg 
3331debfc3dSmrg   fprintf (s_file,
334a2dc1f3fSmrg 	   "#define IN_TARGET_CODE 1\n"
3351debfc3dSmrg 	   "#include \"config.h\"\n"
3361debfc3dSmrg 	   "#include \"system.h\"\n"
3371debfc3dSmrg 	   "#include \"coretypes.h\"\n"
3381debfc3dSmrg 	   "#include \"backend.h\"\n"
3391debfc3dSmrg 	   "#include \"predict.h\"\n"
3401debfc3dSmrg 	   "#include \"tree.h\"\n"
3411debfc3dSmrg 	   "#include \"rtl.h\"\n"
3421debfc3dSmrg 	   "#include \"alias.h\"\n"
3431debfc3dSmrg 	   "#include \"varasm.h\"\n"
3441debfc3dSmrg 	   "#include \"stor-layout.h\"\n"
3451debfc3dSmrg 	   "#include \"calls.h\"\n"
3461debfc3dSmrg 	   "#include \"memmodel.h\"\n"
3471debfc3dSmrg 	   "#include \"tm_p.h\"\n"
3481debfc3dSmrg 	   "#include \"flags.h\"\n"
3491debfc3dSmrg 	   "#include \"insn-config.h\"\n"
3501debfc3dSmrg 	   "#include \"expmed.h\"\n"
3511debfc3dSmrg 	   "#include \"dojump.h\"\n"
3521debfc3dSmrg 	   "#include \"explow.h\"\n"
3531debfc3dSmrg 	   "#include \"emit-rtl.h\"\n"
3541debfc3dSmrg 	   "#include \"stmt.h\"\n"
3551debfc3dSmrg 	   "#include \"expr.h\"\n"
3561debfc3dSmrg 	   "#include \"insn-codes.h\"\n"
3571debfc3dSmrg 	   "#include \"optabs.h\"\n"
3581debfc3dSmrg 	   "\n"
3591debfc3dSmrg 	   "struct optab_pat {\n"
3601debfc3dSmrg 	   "  unsigned scode;\n"
3611debfc3dSmrg 	   "  enum insn_code icode;\n"
3621debfc3dSmrg 	   "};\n\n");
3631debfc3dSmrg 
3641debfc3dSmrg   fprintf (s_file,
3651debfc3dSmrg 	   "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
3661debfc3dSmrg   for (i = 0; patterns.iterate (i, &p); ++i)
3671debfc3dSmrg     fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
3681debfc3dSmrg   fprintf (s_file, "};\n\n");
3691debfc3dSmrg 
3701debfc3dSmrg   fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
3711debfc3dSmrg   fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
3721debfc3dSmrg   for (i = 0; patterns.iterate (i, &p); ++i)
3731debfc3dSmrg     fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
3741debfc3dSmrg   fprintf (s_file, "}\n\n");
3751debfc3dSmrg 
3761debfc3dSmrg   /* Perform a binary search on a pre-encoded optab+mode*2.  */
3771debfc3dSmrg   /* ??? Perhaps even better to generate a minimal perfect hash.
3781debfc3dSmrg      Using gperf directly is awkward since it's so geared to working
3791debfc3dSmrg      with strings.  Plus we have no visibility into the ordering of
3801debfc3dSmrg      the hash entries, which complicates the pat_enable array.  */
3811debfc3dSmrg   fprintf (s_file,
3821debfc3dSmrg 	   "static int\n"
3831debfc3dSmrg 	   "lookup_handler (unsigned scode)\n"
3841debfc3dSmrg 	   "{\n"
3851debfc3dSmrg 	   "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
3861debfc3dSmrg 	   "  while (h > l)\n"
3871debfc3dSmrg 	   "    {\n"
3881debfc3dSmrg 	   "      m = (h + l) / 2;\n"
3891debfc3dSmrg 	   "      if (scode == pats[m].scode)\n"
3901debfc3dSmrg 	   "        return m;\n"
3911debfc3dSmrg 	   "      else if (scode < pats[m].scode)\n"
3921debfc3dSmrg 	   "        h = m;\n"
3931debfc3dSmrg 	   "      else\n"
3941debfc3dSmrg 	   "        l = m + 1;\n"
3951debfc3dSmrg 	   "    }\n"
3961debfc3dSmrg 	   "  return -1;\n"
3971debfc3dSmrg 	   "}\n\n");
3981debfc3dSmrg 
3991debfc3dSmrg   fprintf (s_file,
4001debfc3dSmrg 	   "enum insn_code\n"
4011debfc3dSmrg 	   "raw_optab_handler (unsigned scode)\n"
4021debfc3dSmrg 	   "{\n"
4031debfc3dSmrg 	   "  int i = lookup_handler (scode);\n"
4041debfc3dSmrg 	   "  return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
4051debfc3dSmrg 	   "          ? pats[i].icode : CODE_FOR_nothing);\n"
4061debfc3dSmrg 	   "}\n\n");
4071debfc3dSmrg 
4081debfc3dSmrg   fprintf (s_file,
4091debfc3dSmrg 	   "bool\n"
4101debfc3dSmrg 	   "swap_optab_enable (optab op, machine_mode m, bool set)\n"
4111debfc3dSmrg 	   "{\n"
4121debfc3dSmrg 	   "  unsigned scode = (op << 16) | m;\n"
4131debfc3dSmrg 	   "  int i = lookup_handler (scode);\n"
4141debfc3dSmrg 	   "  if (i >= 0)\n"
4151debfc3dSmrg 	   "    {\n"
4161debfc3dSmrg 	   "      bool ret = this_fn_optabs->pat_enable[i];\n"
4171debfc3dSmrg 	   "      this_fn_optabs->pat_enable[i] = set;\n"
4181debfc3dSmrg 	   "      return ret;\n"
4191debfc3dSmrg 	   "    }\n"
4201debfc3dSmrg 	   "  else\n"
4211debfc3dSmrg 	   "    {\n"
4221debfc3dSmrg 	   "      gcc_assert (!set);\n"
4231debfc3dSmrg 	   "      return false;\n"
4241debfc3dSmrg 	   "    }\n"
4251debfc3dSmrg 	   "}\n\n");
4261debfc3dSmrg 
4271debfc3dSmrg   /* C++ (even G++) does not support (non-trivial) designated initializers.
4281debfc3dSmrg      To work around that, generate these arrays programatically rather than
4291debfc3dSmrg      by our traditional multiple inclusion of def files.  */
4301debfc3dSmrg 
4311debfc3dSmrg   fprintf (s_file,
4321debfc3dSmrg 	   "const struct convert_optab_libcall_d "
4331debfc3dSmrg 	   "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
4341debfc3dSmrg   for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
4351debfc3dSmrg     fprintf (s_file, "  { %s, %s },\n", optabs[i].base, optabs[i].libcall);
4361debfc3dSmrg   fprintf (s_file, "};\n\n");
4371debfc3dSmrg 
4381debfc3dSmrg   fprintf (s_file,
4391debfc3dSmrg 	   "const struct optab_libcall_d "
4401debfc3dSmrg 	   "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
4411debfc3dSmrg   for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
4421debfc3dSmrg     fprintf (s_file, "  { %s, %s, %s },\n",
4431debfc3dSmrg 	     optabs[i].suffix, optabs[i].base, optabs[i].libcall);
4441debfc3dSmrg   fprintf (s_file, "};\n\n");
4451debfc3dSmrg 
4461debfc3dSmrg   fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
4471debfc3dSmrg   for (i = 0; i < n; ++i)
4481debfc3dSmrg     fprintf (s_file, "  %s,\n", rtx_upname[optabs[i].fcode]);
4491debfc3dSmrg   fprintf (s_file, "};\n\n");
4501debfc3dSmrg 
4511debfc3dSmrg   qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
4521debfc3dSmrg 
4531debfc3dSmrg   fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
4541debfc3dSmrg   for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
4551debfc3dSmrg     continue;
4561debfc3dSmrg   for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
4571debfc3dSmrg     {
4581debfc3dSmrg       if (j < n && optabs[j].rcode == i)
4591debfc3dSmrg 	fprintf (s_file, "  %s,\n", optabs[j++].name);
4601debfc3dSmrg       else
4611debfc3dSmrg 	fprintf (s_file, "  unknown_optab,\n");
4621debfc3dSmrg     }
4631debfc3dSmrg   fprintf (s_file, "};\n\n");
4641debfc3dSmrg 
4651debfc3dSmrg   fprintf (h_file, "#endif\n");
4661debfc3dSmrg   return (fclose (h_file) == 0 && fclose (s_file) == 0
4671debfc3dSmrg 	  ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
4681debfc3dSmrg }
469