]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genopinit.cc
aarch64: Avoid using mismatched ZERO ZA sizes
[thirdparty/gcc.git] / gcc / genopinit.cc
CommitLineData
af9e4a0c 1/* Generate code to initialize optabs from machine description.
a945c346 2 Copyright (C) 1993-2024 Free Software Foundation, Inc.
af9e4a0c 3
1322177d 4This file is part of GCC.
af9e4a0c 5
1322177d
LB
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
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
1322177d 9version.
af9e4a0c 10
1322177d
LB
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.
af9e4a0c
RK
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
af9e4a0c
RK
19
20
4977bab6 21#include "bconfig.h"
0b93b64e 22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
af9e4a0c 25#include "rtl.h"
f8b6598e 26#include "errors.h"
c88c0d42 27#include "gensupport.h"
ccd043a9 28
af9e4a0c 29
cd1440b1 30#define DEF_RTL_EXPR(V, N, X, C) #V,
af9e4a0c 31
cd1440b1
RH
32static const char * const rtx_upname[] = {
33#include "rtl.def"
34};
35
36#undef DEF_RTL_EXPR
37
cd1440b1 38/* Vector in which to collect insns that match. */
886456e2 39static vec<optab_pattern> patterns;
56c0e996 40
af9e4a0c 41static void
5d2d3e43 42gen_insn (md_rtx_info *info)
af9e4a0c 43{
886456e2
RS
44 optab_pattern p;
45 if (find_optab (&p, XSTR (info->def, 0)))
46 patterns.safe_push (p);
cd1440b1 47}
af9e4a0c 48
cd1440b1
RH
49static int
50pattern_cmp (const void *va, const void *vb)
51{
886456e2
RS
52 const optab_pattern *a = (const optab_pattern *)va;
53 const optab_pattern *b = (const optab_pattern *)vb;
cd1440b1
RH
54 return a->sort_num - b->sort_num;
55}
af9e4a0c 56
cd1440b1
RH
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}
af9e4a0c 67
cd1440b1
RH
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}
af9e4a0c 75
cd1440b1
RH
76static const char *header_file_name = "init-opinit.h";
77static const char *source_file_name = "init-opinit.c";
af9e4a0c 78
cd1440b1
RH
79static bool
80handle_arg (const char *arg)
81{
82 switch (arg[1])
af9e4a0c 83 {
cd1440b1
RH
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;
af9e4a0c 92 }
af9e4a0c 93}
af9e4a0c 94
cd1440b1
RH
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}
c1b59dce 106
0016d8d9
RS
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{
d281492d
RS
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 }
0016d8d9
RS
174}
175
af9e4a0c 176int
66b0fe8f 177main (int argc, const char **argv)
af9e4a0c 178{
cd1440b1
RH
179 FILE *h_file, *s_file;
180 unsigned int i, j, n, last_kind[5];
886456e2 181 optab_pattern *p;
af9e4a0c 182
f8b6598e 183 progname = "genopinit";
af9e4a0c 184
a454325b 185 if (NUM_OPTABS > 0xfff || NUM_MACHINE_MODES > 0x3ff)
cd1440b1
RH
186 fatal ("genopinit range assumptions invalid");
187
188 if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
c88c0d42 189 return (FATAL_EXIT_CODE);
af9e4a0c 190
cd1440b1
RH
191 h_file = open_outfile (header_file_name);
192 s_file = open_outfile (source_file_name);
dcc3fcf2 193
af9e4a0c 194 /* Read the machine description. */
5d2d3e43
RS
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);
af9e4a0c 202 break;
5d2d3e43
RS
203
204 default:
205 break;
206 }
af9e4a0c 207
cd1440b1 208 /* Sort the collected patterns. */
75509ba2 209 patterns.qsort (pattern_cmp);
cd1440b1
RH
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. */
886456e2 213 n = num_optabs;
cd1440b1
RH
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. */
c3284718 223 qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
cd1440b1 224
385399a8
RS
225 fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
226 fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
227
cd1440b1
RH
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",
9771b263 251 (unsigned) patterns.length ());
cd1440b1 252
b0710fe1
AM
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"
385399a8 277 "#ifdef NUM_RTX_CODE\n"
b0710fe1
AM
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"
0016d8d9
RS
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,
385399a8 302 "#endif\n"
b0710fe1
AM
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"
bfaa08b7 315 "\n"
0fb2ab50
RS
316 " /* Index VOIDmode caches if the target supports vec_gather_load for any\n"
317 " vector mode. Every other index X caches specifically for mode X.\n"
318 " 1 means yes, -1 means no. */\n"
319 " signed char supports_vec_gather_load[NUM_MACHINE_MODES];\n"
320 " signed char supports_vec_scatter_store[NUM_MACHINE_MODES];\n"
b0710fe1
AM
321 "};\n"
322 "extern void init_all_optabs (struct target_optabs *);\n"
d3ff7420 323 "extern bool partial_vectors_supported_p (void);\n"
b0710fe1
AM
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
cd1440b1 333 fprintf (s_file,
8fcc61f8 334 "#define IN_TARGET_CODE 1\n"
cd1440b1
RH
335 "#include \"config.h\"\n"
336 "#include \"system.h\"\n"
337 "#include \"coretypes.h\"\n"
c7131fb2 338 "#include \"backend.h\"\n"
9fdcd34e 339 "#include \"predict.h\"\n"
4d648807 340 "#include \"tree.h\"\n"
c7131fb2
AM
341 "#include \"rtl.h\"\n"
342 "#include \"alias.h\"\n"
d8a2d370
DN
343 "#include \"varasm.h\"\n"
344 "#include \"stor-layout.h\"\n"
345 "#include \"calls.h\"\n"
4d0cdd0c 346 "#include \"memmodel.h\"\n"
cd1440b1
RH
347 "#include \"tm_p.h\"\n"
348 "#include \"flags.h\"\n"
349 "#include \"insn-config.h\"\n"
36566b39
PK
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"
cd1440b1 355 "#include \"expr.h\"\n"
b0710fe1 356 "#include \"insn-codes.h\"\n"
cd1440b1
RH
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");
9771b263 366 for (i = 0; patterns.iterate (i, &p); ++i)
cd1440b1
RH
367 fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
368 fprintf (s_file, "};\n\n");
369
861997a9
RD
370 /* Some targets like riscv have a large number of patterns. In order to
371 prevent pathological situations in dataflow analysis split the init
372 function into separate ones that initialize 1000 patterns each. */
373
374 const int patterns_per_function = 1000;
375
376 if (patterns.length () > patterns_per_function)
377 {
378 unsigned num_init_functions
379 = patterns.length () / patterns_per_function + 1;
380 for (i = 0; i < num_init_functions; i++)
381 {
382 fprintf (s_file, "static void\ninit_optabs_%02d "
383 "(struct target_optabs *optabs)\n{\n", i);
384 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
385 unsigned start = i * patterns_per_function;
386 unsigned end = MIN (patterns.length (),
387 (i + 1) * patterns_per_function);
388 for (j = start; j < end; ++j)
389 fprintf (s_file, " ena[%u] = HAVE_%s;\n", j, patterns[j].name);
390 fprintf (s_file, "}\n\n");
391 }
392
393 fprintf (s_file, "void\ninit_all_optabs "
394 "(struct target_optabs *optabs)\n{\n");
395 for (i = 0; i < num_init_functions; ++i)
396 fprintf (s_file, " init_optabs_%02d (optabs);\n", i);
397 fprintf (s_file, "}\n\n");
398 }
399 else
400 {
401 fprintf (s_file, "void\ninit_all_optabs "
402 "(struct target_optabs *optabs)\n{\n");
403 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
404 for (i = 0; patterns.iterate (i, &p); ++i)
405 fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name);
406 fprintf (s_file, "}\n\n");
407 }
cd1440b1 408
d3ff7420
AV
409 fprintf (s_file,
410 "/* Returns TRUE if the target supports any of the partial vector\n"
ccfdda34 411 " optabs: while_ult_optab, len_load_optab, len_store_optab,\n"
bd68b33f 412 " mask_len_load_optab or mask_len_store_optab,\n"
d3ff7420
AV
413 " for any mode. */\n"
414 "bool\npartial_vectors_supported_p (void)\n{\n");
415 bool any_match = false;
416 fprintf (s_file, "\treturn");
417 bool first = true;
418 for (i = 0; patterns.iterate (i, &p); ++i)
419 {
420#define CMP_NAME(N) !strncmp (p->name, (N), strlen ((N)))
421 if (CMP_NAME("while_ult") || CMP_NAME ("len_load")
bd68b33f
JZ
422 || CMP_NAME ("len_store")|| CMP_NAME ("mask_len_load")
423 || CMP_NAME ("mask_len_store"))
d3ff7420
AV
424 {
425 if (first)
426 fprintf (s_file, " HAVE_%s", p->name);
427 else
428 fprintf (s_file, " || HAVE_%s", p->name);
429 first = false;
430 any_match = true;
431 }
432 }
433 if (!any_match)
434 fprintf (s_file, " false");
435 fprintf (s_file, ";\n}\n");
436
437
cd1440b1
RH
438 /* Perform a binary search on a pre-encoded optab+mode*2. */
439 /* ??? Perhaps even better to generate a minimal perfect hash.
440 Using gperf directly is awkward since it's so geared to working
441 with strings. Plus we have no visibility into the ordering of
442 the hash entries, which complicates the pat_enable array. */
443 fprintf (s_file,
444 "static int\n"
445 "lookup_handler (unsigned scode)\n"
446 "{\n"
447 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
448 " while (h > l)\n"
449 " {\n"
450 " m = (h + l) / 2;\n"
451 " if (scode == pats[m].scode)\n"
452 " return m;\n"
453 " else if (scode < pats[m].scode)\n"
454 " h = m;\n"
455 " else\n"
456 " l = m + 1;\n"
457 " }\n"
458 " return -1;\n"
459 "}\n\n");
460
461 fprintf (s_file,
462 "enum insn_code\n"
463 "raw_optab_handler (unsigned scode)\n"
464 "{\n"
465 " int i = lookup_handler (scode);\n"
135204dd 466 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
cd1440b1
RH
467 " ? pats[i].icode : CODE_FOR_nothing);\n"
468 "}\n\n");
469
470 fprintf (s_file,
471 "bool\n"
ef4bddc2 472 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
cd1440b1 473 "{\n"
a454325b 474 " unsigned scode = (op << 20) | m;\n"
cd1440b1
RH
475 " int i = lookup_handler (scode);\n"
476 " if (i >= 0)\n"
477 " {\n"
135204dd
AH
478 " bool ret = this_fn_optabs->pat_enable[i];\n"
479 " this_fn_optabs->pat_enable[i] = set;\n"
cd1440b1
RH
480 " return ret;\n"
481 " }\n"
482 " else\n"
483 " {\n"
484 " gcc_assert (!set);\n"
485 " return false;\n"
486 " }\n"
487 "}\n\n");
488
489 /* C++ (even G++) does not support (non-trivial) designated initializers.
490 To work around that, generate these arrays programatically rather than
491 by our traditional multiple inclusion of def files. */
492
493 fprintf (s_file,
494 "const struct convert_optab_libcall_d "
495 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
496 for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
497 fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall);
498 fprintf (s_file, "};\n\n");
499
500 fprintf (s_file,
501 "const struct optab_libcall_d "
502 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
503 for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
504 fprintf (s_file, " { %s, %s, %s },\n",
505 optabs[i].suffix, optabs[i].base, optabs[i].libcall);
506 fprintf (s_file, "};\n\n");
507
508 fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
509 for (i = 0; i < n; ++i)
510 fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]);
511 fprintf (s_file, "};\n\n");
512
513 qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
514
515 fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
516 for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
517 continue;
518 for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
519 {
520 if (j < n && optabs[j].rcode == i)
521 fprintf (s_file, " %s,\n", optabs[j++].name);
522 else
523 fprintf (s_file, " unknown_optab,\n");
524 }
525 fprintf (s_file, "};\n\n");
526
385399a8 527 fprintf (h_file, "#endif\n");
cd1440b1
RH
528 return (fclose (h_file) == 0 && fclose (s_file) == 0
529 ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
af9e4a0c 530}