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