Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Generate code to initialize optabs from machine description.
      2  1.1  mrg    Copyright (C) 1993-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      7  1.1  mrg the terms of the GNU General Public License as published by the Free
      8  1.1  mrg Software Foundation; either version 3, or (at your option) any later
      9  1.1  mrg version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  1.1  mrg for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg 
     21  1.1  mrg #include "bconfig.h"
     22  1.1  mrg #include "system.h"
     23  1.1  mrg #include "coretypes.h"
     24  1.1  mrg #include "tm.h"
     25  1.1  mrg #include "rtl.h"
     26  1.1  mrg #include "errors.h"
     27  1.1  mrg #include "gensupport.h"
     28  1.1  mrg 
     29  1.1  mrg 
     30  1.1  mrg #define DEF_RTL_EXPR(V, N, X, C) #V,
     31  1.1  mrg 
     32  1.1  mrg static const char * const rtx_upname[] = {
     33  1.1  mrg #include "rtl.def"
     34  1.1  mrg };
     35  1.1  mrg 
     36  1.1  mrg #undef DEF_RTL_EXPR
     37  1.1  mrg 
     38  1.1  mrg /* Vector in which to collect insns that match.  */
     39  1.1  mrg static vec<optab_pattern> patterns;
     40  1.1  mrg 
     41  1.1  mrg static void
     42  1.1  mrg gen_insn (md_rtx_info *info)
     43  1.1  mrg {
     44  1.1  mrg   optab_pattern p;
     45  1.1  mrg   if (find_optab (&p, XSTR (info->def, 0)))
     46  1.1  mrg     patterns.safe_push (p);
     47  1.1  mrg }
     48  1.1  mrg 
     49  1.1  mrg static int
     50  1.1  mrg pattern_cmp (const void *va, const void *vb)
     51  1.1  mrg {
     52  1.1  mrg   const optab_pattern *a = (const optab_pattern *)va;
     53  1.1  mrg   const optab_pattern *b = (const optab_pattern *)vb;
     54  1.1  mrg   return a->sort_num - b->sort_num;
     55  1.1  mrg }
     56  1.1  mrg 
     57  1.1  mrg static int
     58  1.1  mrg optab_kind_cmp (const void *va, const void *vb)
     59  1.1  mrg {
     60  1.1  mrg   const optab_def *a = (const optab_def *)va;
     61  1.1  mrg   const optab_def *b = (const optab_def *)vb;
     62  1.1  mrg   int diff = a->kind - b->kind;
     63  1.1  mrg   if (diff == 0)
     64  1.1  mrg     diff = a->op - b->op;
     65  1.1  mrg   return diff;
     66  1.1  mrg }
     67  1.1  mrg 
     68  1.1  mrg static int
     69  1.1  mrg optab_rcode_cmp (const void *va, const void *vb)
     70  1.1  mrg {
     71  1.1  mrg   const optab_def *a = (const optab_def *)va;
     72  1.1  mrg   const optab_def *b = (const optab_def *)vb;
     73  1.1  mrg   return a->rcode - b->rcode;
     74  1.1  mrg }
     75  1.1  mrg 
     76  1.1  mrg static const char *header_file_name = "init-opinit.h";
     77  1.1  mrg static const char *source_file_name = "init-opinit.c";
     78  1.1  mrg 
     79  1.1  mrg static bool
     80  1.1  mrg handle_arg (const char *arg)
     81  1.1  mrg {
     82  1.1  mrg   switch (arg[1])
     83  1.1  mrg     {
     84  1.1  mrg     case 'h':
     85  1.1  mrg       header_file_name = &arg[2];
     86  1.1  mrg       return true;
     87  1.1  mrg     case 'c':
     88  1.1  mrg       source_file_name = &arg[2];
     89  1.1  mrg       return true;
     90  1.1  mrg     default:
     91  1.1  mrg       return false;
     92  1.1  mrg     }
     93  1.1  mrg }
     94  1.1  mrg 
     95  1.1  mrg static FILE *
     96  1.1  mrg open_outfile (const char *file_name)
     97  1.1  mrg {
     98  1.1  mrg   FILE *f = fopen (file_name, "w");
     99  1.1  mrg   if (!f)
    100  1.1  mrg     fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
    101  1.1  mrg   fprintf (f,
    102  1.1  mrg 	   "/* Generated automatically by the program `genopinit'\n"
    103  1.1  mrg 	   "   from the machine description file `md'.  */\n\n");
    104  1.1  mrg   return f;
    105  1.1  mrg }
    106  1.1  mrg 
    107  1.1  mrg /* Declare the maybe_code_for_* function for ONAME, and provide
    108  1.1  mrg    an inline definition of the assserting code_for_* wrapper.  */
    109  1.1  mrg 
    110  1.1  mrg static void
    111  1.1  mrg handle_overloaded_code_for (FILE *file, overloaded_name *oname)
    112  1.1  mrg {
    113  1.1  mrg   fprintf (file, "\nextern insn_code maybe_code_for_%s (", oname->name);
    114  1.1  mrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    115  1.1  mrg     fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
    116  1.1  mrg   fprintf (file, ");\n");
    117  1.1  mrg 
    118  1.1  mrg   fprintf (file, "inline insn_code\ncode_for_%s (", oname->name);
    119  1.1  mrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    120  1.1  mrg     fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
    121  1.1  mrg   fprintf (file, ")\n{\n  insn_code code = maybe_code_for_%s (", oname->name);
    122  1.1  mrg   for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    123  1.1  mrg     fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
    124  1.1  mrg   fprintf (file,
    125  1.1  mrg 	   ");\n"
    126  1.1  mrg 	   "  gcc_assert (code != CODE_FOR_nothing);\n"
    127  1.1  mrg 	   "  return code;\n"
    128  1.1  mrg 	   "}\n");
    129  1.1  mrg }
    130  1.1  mrg 
    131  1.1  mrg /* Declare the maybe_gen_* function for ONAME, and provide
    132  1.1  mrg    an inline definition of the assserting gen_* wrapper.  */
    133  1.1  mrg 
    134  1.1  mrg static void
    135  1.1  mrg handle_overloaded_gen (FILE *file, overloaded_name *oname)
    136  1.1  mrg {
    137  1.1  mrg   unsigned HOST_WIDE_INT seen = 0;
    138  1.1  mrg   for (overloaded_instance *instance = oname->first_instance->next;
    139  1.1  mrg        instance; instance = instance->next)
    140  1.1  mrg     {
    141  1.1  mrg       pattern_stats stats;
    142  1.1  mrg       get_pattern_stats (&stats, XVEC (instance->insn, 1));
    143  1.1  mrg       unsigned HOST_WIDE_INT mask
    144  1.1  mrg 	= HOST_WIDE_INT_1U << stats.num_generator_args;
    145  1.1  mrg       if (seen & mask)
    146  1.1  mrg 	continue;
    147  1.1  mrg 
    148  1.1  mrg       seen |= mask;
    149  1.1  mrg 
    150  1.1  mrg       fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
    151  1.1  mrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    152  1.1  mrg 	fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
    153  1.1  mrg       for (int i = 0; i < stats.num_generator_args; ++i)
    154  1.1  mrg 	fprintf (file, ", rtx");
    155  1.1  mrg       fprintf (file, ");\n");
    156  1.1  mrg 
    157  1.1  mrg       fprintf (file, "inline rtx\ngen_%s (", oname->name);
    158  1.1  mrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    159  1.1  mrg 	fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ",
    160  1.1  mrg 		 oname->arg_types[i], i);
    161  1.1  mrg       for (int i = 0; i < stats.num_generator_args; ++i)
    162  1.1  mrg 	fprintf (file, ", rtx x%d", i);
    163  1.1  mrg       fprintf (file, ")\n{\n  rtx res = maybe_gen_%s (", oname->name);
    164  1.1  mrg       for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
    165  1.1  mrg 	fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
    166  1.1  mrg       for (int i = 0; i < stats.num_generator_args; ++i)
    167  1.1  mrg 	fprintf (file, ", x%d", i);
    168  1.1  mrg       fprintf (file,
    169  1.1  mrg 	       ");\n"
    170  1.1  mrg 	       "  gcc_assert (res);\n"
    171  1.1  mrg 	       "  return res;\n"
    172  1.1  mrg 	       "}\n");
    173  1.1  mrg     }
    174  1.1  mrg }
    175  1.1  mrg 
    176  1.1  mrg int
    177  1.1  mrg main (int argc, const char **argv)
    178  1.1  mrg {
    179  1.1  mrg   FILE *h_file, *s_file;
    180  1.1  mrg   unsigned int i, j, n, last_kind[5];
    181  1.1  mrg   optab_pattern *p;
    182  1.1  mrg 
    183  1.1  mrg   progname = "genopinit";
    184  1.1  mrg 
    185  1.1  mrg   if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
    186  1.1  mrg     fatal ("genopinit range assumptions invalid");
    187  1.1  mrg 
    188  1.1  mrg   if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
    189  1.1  mrg     return (FATAL_EXIT_CODE);
    190  1.1  mrg 
    191  1.1  mrg   h_file = open_outfile (header_file_name);
    192  1.1  mrg   s_file = open_outfile (source_file_name);
    193  1.1  mrg 
    194  1.1  mrg   /* Read the machine description.  */
    195  1.1  mrg   md_rtx_info info;
    196  1.1  mrg   while (read_md_rtx (&info))
    197  1.1  mrg     switch (GET_CODE (info.def))
    198  1.1  mrg       {
    199  1.1  mrg       case DEFINE_INSN:
    200  1.1  mrg       case DEFINE_EXPAND:
    201  1.1  mrg 	gen_insn (&info);
    202  1.1  mrg 	break;
    203  1.1  mrg 
    204  1.1  mrg       default:
    205  1.1  mrg 	break;
    206  1.1  mrg       }
    207  1.1  mrg 
    208  1.1  mrg   /* Sort the collected patterns.  */
    209  1.1  mrg   patterns.qsort (pattern_cmp);
    210  1.1  mrg 
    211  1.1  mrg   /* Now that we've handled the "extra" patterns, eliminate them from
    212  1.1  mrg      the optabs array.  That way they don't get in the way below.  */
    213  1.1  mrg   n = num_optabs;
    214  1.1  mrg   for (i = 0; i < n; )
    215  1.1  mrg     if (optabs[i].base == NULL)
    216  1.1  mrg       optabs[i] = optabs[--n];
    217  1.1  mrg     else
    218  1.1  mrg       ++i;
    219  1.1  mrg 
    220  1.1  mrg   /* Sort the (real) optabs.  Better than forcing the optabs.def file to
    221  1.1  mrg      remain sorted by kind.  We also scrogged any real ordering with the
    222  1.1  mrg      purging of the X patterns above.  */
    223  1.1  mrg   qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
    224  1.1  mrg 
    225  1.1  mrg   fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
    226  1.1  mrg   fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
    227  1.1  mrg 
    228  1.1  mrg   /* Emit the optab enumeration for the header file.  */
    229  1.1  mrg   fprintf (h_file, "enum optab_tag {\n");
    230  1.1  mrg   for (i = j = 0; i < n; ++i)
    231  1.1  mrg     {
    232  1.1  mrg       optabs[i].op = i;
    233  1.1  mrg       fprintf (h_file, "  %s,\n", optabs[i].name);
    234  1.1  mrg       if (optabs[i].kind != j)
    235  1.1  mrg 	last_kind[j++] = i - 1;
    236  1.1  mrg     }
    237  1.1  mrg   fprintf (h_file, "  FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
    238  1.1  mrg   fprintf (h_file, "  LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
    239  1.1  mrg   fprintf (h_file, "  LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
    240  1.1  mrg   fprintf (h_file, "  FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
    241  1.1  mrg   fprintf (h_file, "  LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
    242  1.1  mrg   fprintf (h_file, "  LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
    243  1.1  mrg   fprintf (h_file, "};\n\n");
    244  1.1  mrg 
    245  1.1  mrg   fprintf (h_file, "#define NUM_OPTABS          %u\n", n);
    246  1.1  mrg   fprintf (h_file, "#define NUM_CONVLIB_OPTABS  %u\n",
    247  1.1  mrg 	   last_kind[1] - last_kind[0]);
    248  1.1  mrg   fprintf (h_file, "#define NUM_NORMLIB_OPTABS  %u\n",
    249  1.1  mrg 	   last_kind[3] - last_kind[2]);
    250  1.1  mrg   fprintf (h_file, "#define NUM_OPTAB_PATTERNS  %u\n",
    251  1.1  mrg 	   (unsigned) patterns.length ());
    252  1.1  mrg 
    253  1.1  mrg   fprintf (h_file,
    254  1.1  mrg 	   "typedef enum optab_tag optab;\n"
    255  1.1  mrg 	   "typedef enum optab_tag convert_optab;\n"
    256  1.1  mrg 	   "typedef enum optab_tag direct_optab;\n"
    257  1.1  mrg 	   "\n"
    258  1.1  mrg 	   "struct optab_libcall_d\n"
    259  1.1  mrg 	   "{\n"
    260  1.1  mrg 	   "  char libcall_suffix;\n"
    261  1.1  mrg 	   "  const char *libcall_basename;\n"
    262  1.1  mrg 	   "  void (*libcall_gen) (optab, const char *name,\n"
    263  1.1  mrg 	   "		       char suffix, machine_mode);\n"
    264  1.1  mrg 	   "};\n"
    265  1.1  mrg 	   "\n"
    266  1.1  mrg 	   "struct convert_optab_libcall_d\n"
    267  1.1  mrg 	   "{\n"
    268  1.1  mrg 	   "  const char *libcall_basename;\n"
    269  1.1  mrg 	   "  void (*libcall_gen) (convert_optab, const char *name,\n"
    270  1.1  mrg 	   "		       machine_mode, machine_mode);\n"
    271  1.1  mrg 	   "};\n"
    272  1.1  mrg 	   "\n"
    273  1.1  mrg 	   "/* Given an enum insn_code, access the function to construct\n"
    274  1.1  mrg 	   "   the body of that kind of insn.  */\n"
    275  1.1  mrg 	   "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
    276  1.1  mrg 	   "\n"
    277  1.1  mrg 	   "#ifdef NUM_RTX_CODE\n"
    278  1.1  mrg 	   "/* Contains the optab used for each rtx code, and vice-versa.  */\n"
    279  1.1  mrg 	   "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
    280  1.1  mrg 	   "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
    281  1.1  mrg 	   "\n"
    282  1.1  mrg 	   "static inline optab\n"
    283  1.1  mrg 	   "code_to_optab (enum rtx_code code)\n"
    284  1.1  mrg 	   "{\n"
    285  1.1  mrg 	   "  return code_to_optab_[code];\n"
    286  1.1  mrg 	   "}\n"
    287  1.1  mrg 	   "\n"
    288  1.1  mrg 	   "static inline enum rtx_code\n"
    289  1.1  mrg 	   "optab_to_code (optab op)\n"
    290  1.1  mrg 	   "{\n"
    291  1.1  mrg 	   "  return optab_to_code_[op];\n"
    292  1.1  mrg 	   "}\n");
    293  1.1  mrg 
    294  1.1  mrg   for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
    295  1.1  mrg        oname; oname = oname->next)
    296  1.1  mrg     {
    297  1.1  mrg       handle_overloaded_code_for (h_file, oname);
    298  1.1  mrg       handle_overloaded_gen (h_file, oname);
    299  1.1  mrg     }
    300  1.1  mrg 
    301  1.1  mrg   fprintf (h_file,
    302  1.1  mrg 	   "#endif\n"
    303  1.1  mrg 	   "\n"
    304  1.1  mrg 	   "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
    305  1.1  mrg 	   "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
    306  1.1  mrg 	   "\n"
    307  1.1  mrg 	   "/* Returns the active icode for the given (encoded) optab.  */\n"
    308  1.1  mrg 	   "extern enum insn_code raw_optab_handler (unsigned);\n"
    309  1.1  mrg 	   "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
    310  1.1  mrg 	   "\n"
    311  1.1  mrg 	   "/* Target-dependent globals.  */\n"
    312  1.1  mrg 	   "struct target_optabs {\n"
    313  1.1  mrg 	   "  /* Patterns that are used by optabs that are enabled for this target.  */\n"
    314  1.1  mrg 	   "  bool pat_enable[NUM_OPTAB_PATTERNS];\n"
    315  1.1  mrg 	   "\n"
    316  1.1  mrg 	   "  /* Index VOIDmode caches if the target supports vec_gather_load for any\n"
    317  1.1  mrg 	   "     vector mode.  Every other index X caches specifically for mode X.\n"
    318  1.1  mrg 	   "     1 means yes, -1 means no.  */\n"
    319  1.1  mrg 	   "  signed char supports_vec_gather_load[NUM_MACHINE_MODES];\n"
    320  1.1  mrg 	   "  signed char supports_vec_scatter_store[NUM_MACHINE_MODES];\n"
    321  1.1  mrg 	   "};\n"
    322  1.1  mrg 	   "extern void init_all_optabs (struct target_optabs *);\n"
    323  1.1  mrg 	   "extern bool partial_vectors_supported_p (void);\n"
    324  1.1  mrg 	   "\n"
    325  1.1  mrg 	   "extern struct target_optabs default_target_optabs;\n"
    326  1.1  mrg 	   "extern struct target_optabs *this_fn_optabs;\n"
    327  1.1  mrg 	   "#if SWITCHABLE_TARGET\n"
    328  1.1  mrg 	   "extern struct target_optabs *this_target_optabs;\n"
    329  1.1  mrg 	   "#else\n"
    330  1.1  mrg 	   "#define this_target_optabs (&default_target_optabs)\n"
    331  1.1  mrg 	   "#endif\n");
    332  1.1  mrg 
    333  1.1  mrg   fprintf (s_file,
    334  1.1  mrg 	   "#define IN_TARGET_CODE 1\n"
    335  1.1  mrg 	   "#include \"config.h\"\n"
    336  1.1  mrg 	   "#include \"system.h\"\n"
    337  1.1  mrg 	   "#include \"coretypes.h\"\n"
    338  1.1  mrg 	   "#include \"backend.h\"\n"
    339  1.1  mrg 	   "#include \"predict.h\"\n"
    340  1.1  mrg 	   "#include \"tree.h\"\n"
    341  1.1  mrg 	   "#include \"rtl.h\"\n"
    342  1.1  mrg 	   "#include \"alias.h\"\n"
    343  1.1  mrg 	   "#include \"varasm.h\"\n"
    344  1.1  mrg 	   "#include \"stor-layout.h\"\n"
    345  1.1  mrg 	   "#include \"calls.h\"\n"
    346  1.1  mrg 	   "#include \"memmodel.h\"\n"
    347  1.1  mrg 	   "#include \"tm_p.h\"\n"
    348  1.1  mrg 	   "#include \"flags.h\"\n"
    349  1.1  mrg 	   "#include \"insn-config.h\"\n"
    350  1.1  mrg 	   "#include \"expmed.h\"\n"
    351  1.1  mrg 	   "#include \"dojump.h\"\n"
    352  1.1  mrg 	   "#include \"explow.h\"\n"
    353  1.1  mrg 	   "#include \"emit-rtl.h\"\n"
    354  1.1  mrg 	   "#include \"stmt.h\"\n"
    355  1.1  mrg 	   "#include \"expr.h\"\n"
    356  1.1  mrg 	   "#include \"insn-codes.h\"\n"
    357  1.1  mrg 	   "#include \"optabs.h\"\n"
    358  1.1  mrg 	   "\n"
    359  1.1  mrg 	   "struct optab_pat {\n"
    360  1.1  mrg 	   "  unsigned scode;\n"
    361  1.1  mrg 	   "  enum insn_code icode;\n"
    362  1.1  mrg 	   "};\n\n");
    363  1.1  mrg 
    364  1.1  mrg   fprintf (s_file,
    365  1.1  mrg 	   "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
    366  1.1  mrg   for (i = 0; patterns.iterate (i, &p); ++i)
    367  1.1  mrg     fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
    368  1.1  mrg   fprintf (s_file, "};\n\n");
    369  1.1  mrg 
    370  1.1  mrg   fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
    371  1.1  mrg   fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
    372  1.1  mrg   for (i = 0; patterns.iterate (i, &p); ++i)
    373  1.1  mrg     fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
    374  1.1  mrg   fprintf (s_file, "}\n\n");
    375  1.1  mrg 
    376  1.1  mrg   fprintf (s_file,
    377  1.1  mrg 	   "/* Returns TRUE if the target supports any of the partial vector\n"
    378  1.1  mrg 	   "   optabs: while_ult_optab, len_load_optab or len_store_optab,\n"
    379  1.1  mrg 	   "   for any mode.  */\n"
    380  1.1  mrg 	   "bool\npartial_vectors_supported_p (void)\n{\n");
    381  1.1  mrg   bool any_match = false;
    382  1.1  mrg   fprintf (s_file, "\treturn");
    383  1.1  mrg   bool first = true;
    384  1.1  mrg   for (i = 0; patterns.iterate (i, &p); ++i)
    385  1.1  mrg     {
    386  1.1  mrg #define CMP_NAME(N) !strncmp (p->name, (N), strlen ((N)))
    387  1.1  mrg       if (CMP_NAME("while_ult") || CMP_NAME ("len_load")
    388  1.1  mrg 	  || CMP_NAME ("len_store"))
    389  1.1  mrg 	{
    390  1.1  mrg 	  if (first)
    391  1.1  mrg 	    fprintf (s_file, " HAVE_%s", p->name);
    392  1.1  mrg 	  else
    393  1.1  mrg 	    fprintf (s_file, " || HAVE_%s", p->name);
    394  1.1  mrg 	  first = false;
    395  1.1  mrg 	  any_match = true;
    396  1.1  mrg 	}
    397  1.1  mrg     }
    398  1.1  mrg   if (!any_match)
    399  1.1  mrg     fprintf (s_file, " false");
    400  1.1  mrg   fprintf (s_file, ";\n}\n");
    401  1.1  mrg 
    402  1.1  mrg 
    403  1.1  mrg   /* Perform a binary search on a pre-encoded optab+mode*2.  */
    404  1.1  mrg   /* ??? Perhaps even better to generate a minimal perfect hash.
    405  1.1  mrg      Using gperf directly is awkward since it's so geared to working
    406  1.1  mrg      with strings.  Plus we have no visibility into the ordering of
    407  1.1  mrg      the hash entries, which complicates the pat_enable array.  */
    408  1.1  mrg   fprintf (s_file,
    409  1.1  mrg 	   "static int\n"
    410  1.1  mrg 	   "lookup_handler (unsigned scode)\n"
    411  1.1  mrg 	   "{\n"
    412  1.1  mrg 	   "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
    413  1.1  mrg 	   "  while (h > l)\n"
    414  1.1  mrg 	   "    {\n"
    415  1.1  mrg 	   "      m = (h + l) / 2;\n"
    416  1.1  mrg 	   "      if (scode == pats[m].scode)\n"
    417  1.1  mrg 	   "        return m;\n"
    418  1.1  mrg 	   "      else if (scode < pats[m].scode)\n"
    419  1.1  mrg 	   "        h = m;\n"
    420  1.1  mrg 	   "      else\n"
    421  1.1  mrg 	   "        l = m + 1;\n"
    422  1.1  mrg 	   "    }\n"
    423  1.1  mrg 	   "  return -1;\n"
    424  1.1  mrg 	   "}\n\n");
    425  1.1  mrg 
    426  1.1  mrg   fprintf (s_file,
    427  1.1  mrg 	   "enum insn_code\n"
    428  1.1  mrg 	   "raw_optab_handler (unsigned scode)\n"
    429  1.1  mrg 	   "{\n"
    430  1.1  mrg 	   "  int i = lookup_handler (scode);\n"
    431  1.1  mrg 	   "  return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
    432  1.1  mrg 	   "          ? pats[i].icode : CODE_FOR_nothing);\n"
    433  1.1  mrg 	   "}\n\n");
    434  1.1  mrg 
    435  1.1  mrg   fprintf (s_file,
    436  1.1  mrg 	   "bool\n"
    437  1.1  mrg 	   "swap_optab_enable (optab op, machine_mode m, bool set)\n"
    438  1.1  mrg 	   "{\n"
    439  1.1  mrg 	   "  unsigned scode = (op << 16) | m;\n"
    440  1.1  mrg 	   "  int i = lookup_handler (scode);\n"
    441  1.1  mrg 	   "  if (i >= 0)\n"
    442  1.1  mrg 	   "    {\n"
    443  1.1  mrg 	   "      bool ret = this_fn_optabs->pat_enable[i];\n"
    444  1.1  mrg 	   "      this_fn_optabs->pat_enable[i] = set;\n"
    445  1.1  mrg 	   "      return ret;\n"
    446  1.1  mrg 	   "    }\n"
    447  1.1  mrg 	   "  else\n"
    448  1.1  mrg 	   "    {\n"
    449  1.1  mrg 	   "      gcc_assert (!set);\n"
    450  1.1  mrg 	   "      return false;\n"
    451  1.1  mrg 	   "    }\n"
    452  1.1  mrg 	   "}\n\n");
    453  1.1  mrg 
    454  1.1  mrg   /* C++ (even G++) does not support (non-trivial) designated initializers.
    455  1.1  mrg      To work around that, generate these arrays programatically rather than
    456  1.1  mrg      by our traditional multiple inclusion of def files.  */
    457  1.1  mrg 
    458  1.1  mrg   fprintf (s_file,
    459  1.1  mrg 	   "const struct convert_optab_libcall_d "
    460  1.1  mrg 	   "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
    461  1.1  mrg   for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
    462  1.1  mrg     fprintf (s_file, "  { %s, %s },\n", optabs[i].base, optabs[i].libcall);
    463  1.1  mrg   fprintf (s_file, "};\n\n");
    464  1.1  mrg 
    465  1.1  mrg   fprintf (s_file,
    466  1.1  mrg 	   "const struct optab_libcall_d "
    467  1.1  mrg 	   "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
    468  1.1  mrg   for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
    469  1.1  mrg     fprintf (s_file, "  { %s, %s, %s },\n",
    470  1.1  mrg 	     optabs[i].suffix, optabs[i].base, optabs[i].libcall);
    471  1.1  mrg   fprintf (s_file, "};\n\n");
    472  1.1  mrg 
    473  1.1  mrg   fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
    474  1.1  mrg   for (i = 0; i < n; ++i)
    475  1.1  mrg     fprintf (s_file, "  %s,\n", rtx_upname[optabs[i].fcode]);
    476  1.1  mrg   fprintf (s_file, "};\n\n");
    477  1.1  mrg 
    478  1.1  mrg   qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
    479  1.1  mrg 
    480  1.1  mrg   fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
    481  1.1  mrg   for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
    482  1.1  mrg     continue;
    483  1.1  mrg   for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
    484  1.1  mrg     {
    485  1.1  mrg       if (j < n && optabs[j].rcode == i)
    486  1.1  mrg 	fprintf (s_file, "  %s,\n", optabs[j++].name);
    487  1.1  mrg       else
    488  1.1  mrg 	fprintf (s_file, "  unknown_optab,\n");
    489  1.1  mrg     }
    490  1.1  mrg   fprintf (s_file, "};\n\n");
    491  1.1  mrg 
    492  1.1  mrg   fprintf (h_file, "#endif\n");
    493  1.1  mrg   return (fclose (h_file) == 0 && fclose (s_file) == 0
    494  1.1  mrg 	  ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
    495  1.1  mrg }
    496