]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genopinit.c
RISC-V: Preserve arch version info during normalizing arch string
[thirdparty/gcc.git] / gcc / genopinit.c
CommitLineData
af9e4a0c 1/* Generate code to initialize optabs from machine description.
8d9254fc 2 Copyright (C) 1993-2020 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
cd1440b1
RH
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))
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
RS
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"
f307441a
RS
320 " bool supports_vec_scatter_store;\n"
321 " bool supports_vec_scatter_store_cached;\n"
b0710fe1
AM
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
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
135204dd
AH
370 fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
371 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
9771b263 372 for (i = 0; patterns.iterate (i, &p); ++i)
cd1440b1
RH
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"
135204dd 404 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
cd1440b1
RH
405 " ? pats[i].icode : CODE_FOR_nothing);\n"
406 "}\n\n");
407
408 fprintf (s_file,
409 "bool\n"
ef4bddc2 410 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
cd1440b1
RH
411 "{\n"
412 " unsigned scode = (op << 16) | m;\n"
413 " int i = lookup_handler (scode);\n"
414 " if (i >= 0)\n"
415 " {\n"
135204dd
AH
416 " bool ret = this_fn_optabs->pat_enable[i];\n"
417 " this_fn_optabs->pat_enable[i] = set;\n"
cd1440b1
RH
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
385399a8 465 fprintf (h_file, "#endif\n");
cd1440b1
RH
466 return (fclose (h_file) == 0 && fclose (s_file) == 0
467 ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
af9e4a0c 468}