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