]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genopinit.c
gcc/ada/
[thirdparty/gcc.git] / gcc / genopinit.c
CommitLineData
5079aa9a 1/* Generate code to initialize optabs from machine description.
3aea1f79 2 Copyright (C) 1993-2014 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
38
39/* The entries in optabs.def are categorized:
40 C: A "conversion" optab, which uses two modes; has libcall data.
41 N: A "normal" optab, which uses one mode; has libcall data.
42 D: A "direct" optab, which uses one mode; does not have libcall data.
43 V: An "oVerflow" optab. Like N, but does not record its code in
44 code_to_optab.
5079aa9a 45
ee65118b 46 CX, NX, VX: An extra pattern entry for a conversion or normal optab.
5079aa9a 47
ee65118b 48 These patterns may be present in the MD file with names that contain
49 the mode(s) used and the name of the operation. This array contains
50 a list of optabs that need to be initialized. Within each name,
51 $a and $b are used to match a short mode name (the part of the mode
52 name not including `mode' and converted to lower-case).
5a574e8b 53
54 $I means that only full integer modes should be considered for the
55 next mode, and $F means that only float modes should be considered.
bec2d490 56 $P means that both full and partial integer modes should be considered.
68a556d6 57 $Q means that only fixed-point modes should be considered.
bec2d490 58
ee65118b 59 The pattern may be NULL if the optab exists only for the libcalls
60 that we plan to attach to it, and there are no named patterns in
61 the md files. */
62
63#define OPTAB_CL(name, pat, c, b, l) name,
64#define OPTAB_CX(name, pat)
65#define OPTAB_CD(name, pat) name,
66#define OPTAB_NL(name, pat, c, b, s, l) name,
67#define OPTAB_NC(name, pat, c) name,
68#define OPTAB_NX(name, pat)
69#define OPTAB_VL(name, pat, c, b, s, l) name,
70#define OPTAB_VC(name, pat, c) name,
71#define OPTAB_VX(name, pat)
72#define OPTAB_DC(name, pat, c) name,
73#define OPTAB_D(name, pat) name,
74
75typedef enum optab_tag {
76 unknown_optab,
77#include "optabs.def"
78 NUM_OPTABS
79} optab;
80
81#undef OPTAB_CL
82#undef OPTAB_CX
83#undef OPTAB_CD
84#undef OPTAB_NL
85#undef OPTAB_NC
86#undef OPTAB_NX
87#undef OPTAB_VL
88#undef OPTAB_VC
89#undef OPTAB_VX
90#undef OPTAB_DC
91#undef OPTAB_D
92
93#define NS "NULL"
94#define ZS "'\\0'"
95#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
96#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
97#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
98#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
99#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 },
100#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
101#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
102#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
103#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
104#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
105#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
106
107typedef struct optab_def_d
108{
109 const char *name;
110 const char *pattern;
111 const char *base;
112 const char *suffix;
113 const char *libcall;
114 unsigned int op;
115 enum rtx_code fcode;
116 enum rtx_code rcode;
117 unsigned int kind;
118} optab_def;
119
120static optab_def optabs[] = {
121 { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
122#include "optabs.def"
b6a5fc45 123};
5079aa9a 124
ee65118b 125#undef OPTAB_CL
126#undef OPTAB_CX
127#undef OPTAB_CD
128#undef OPTAB_NL
129#undef OPTAB_NC
130#undef OPTAB_NX
131#undef OPTAB_VL
132#undef OPTAB_VC
133#undef OPTAB_VX
134#undef OPTAB_DC
135#undef OPTAB_D
136
137/* Vector in which to collect insns that match. */
138
139typedef struct pattern_d
140{
141 const char *name;
142 unsigned int op;
143 unsigned int m1, m2;
144 unsigned int sort_num;
145} pattern;
146
ee65118b 147
f1f41a6c 148static vec<pattern> patterns;
ee65118b 149
150static bool
151match_pattern (pattern *p, const char *name, const char *pat)
152{
153 bool force_float = false;
154 bool force_int = false;
155 bool force_partial_int = false;
156 bool force_fixed = false;
157
158 if (pat == NULL)
159 return false;
160 for (; ; ++pat)
161 {
162 if (*pat != '$')
163 {
164 if (*pat != *name++)
165 return false;
166 if (*pat == '\0')
167 return true;
168 continue;
169 }
170 switch (*++pat)
171 {
172 case 'I':
173 force_int = 1;
174 break;
175 case 'P':
176 force_partial_int = 1;
177 break;
178 case 'F':
179 force_float = 1;
180 break;
181 case 'Q':
182 force_fixed = 1;
183 break;
184
185 case 'a':
186 case 'b':
187 {
188 int i;
189
190 /* This loop will stop at the first prefix match, so
191 look through the modes in reverse order, in case
192 there are extra CC modes and CC is a prefix of the
193 CC modes (as it should be). */
194 for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
195 {
196 const char *p, *q;
9af5ce0c 197 for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
ee65118b 198 if (TOLOWER (*p) != *q)
199 break;
200 if (*p == 0
201 && (! force_int || mode_class[i] == MODE_INT
202 || mode_class[i] == MODE_VECTOR_INT)
203 && (! force_partial_int
204 || mode_class[i] == MODE_INT
205 || mode_class[i] == MODE_PARTIAL_INT
206 || mode_class[i] == MODE_VECTOR_INT)
207 && (! force_float
208 || mode_class[i] == MODE_FLOAT
209 || mode_class[i] == MODE_DECIMAL_FLOAT
210 || mode_class[i] == MODE_COMPLEX_FLOAT
211 || mode_class[i] == MODE_VECTOR_FLOAT)
212 && (! force_fixed
213 || mode_class[i] == MODE_FRACT
214 || mode_class[i] == MODE_UFRACT
215 || mode_class[i] == MODE_ACCUM
216 || mode_class[i] == MODE_UACCUM
217 || mode_class[i] == MODE_VECTOR_FRACT
218 || mode_class[i] == MODE_VECTOR_UFRACT
219 || mode_class[i] == MODE_VECTOR_ACCUM
220 || mode_class[i] == MODE_VECTOR_UACCUM))
221 break;
222 }
223
224 if (i < 0)
225 return false;
226 name += strlen (GET_MODE_NAME (i));
227 if (*pat == 'a')
228 p->m1 = i;
229 else
230 p->m2 = i;
231
232 force_int = false;
233 force_partial_int = false;
234 force_float = false;
235 force_fixed = false;
236 }
237 break;
238
239 default:
240 gcc_unreachable ();
241 }
242 }
243}
12693c81 244
5079aa9a 245static void
1a97be37 246gen_insn (rtx insn)
5079aa9a 247{
9a356c3c 248 const char *name = XSTR (insn, 0);
ee65118b 249 pattern p;
250 unsigned pindex;
5079aa9a 251
ee65118b 252 /* Don't mention "unnamed" instructions. */
253 if (*name == 0 || *name == '*')
254 return;
255 p.name = name;
5079aa9a 256
ee65118b 257 /* See if NAME matches one of the patterns we have for the optabs
258 we know about. */
3098b2d3 259 for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
5079aa9a 260 {
ee65118b 261 p.m1 = p.m2 = 0;
262 if (match_pattern (&p, name, optabs[pindex].pattern))
5079aa9a 263 {
ee65118b 264 p.op = optabs[pindex].op;
265 p.sort_num = (p.op << 16) | (p.m2 << 8) | p.m1;
f1f41a6c 266 patterns.safe_push (p);
ee65118b 267 return;
5079aa9a 268 }
5079aa9a 269 }
ee65118b 270}
5079aa9a 271
ee65118b 272static int
273pattern_cmp (const void *va, const void *vb)
274{
275 const pattern *a = (const pattern *)va;
276 const pattern *b = (const pattern *)vb;
277 return a->sort_num - b->sort_num;
278}
5079aa9a 279
ee65118b 280static int
281optab_kind_cmp (const void *va, const void *vb)
282{
283 const optab_def *a = (const optab_def *)va;
284 const optab_def *b = (const optab_def *)vb;
285 int diff = a->kind - b->kind;
286 if (diff == 0)
287 diff = a->op - b->op;
288 return diff;
289}
5079aa9a 290
ee65118b 291static int
292optab_rcode_cmp (const void *va, const void *vb)
293{
294 const optab_def *a = (const optab_def *)va;
295 const optab_def *b = (const optab_def *)vb;
296 return a->rcode - b->rcode;
297}
5079aa9a 298
ee65118b 299static const char *header_file_name = "init-opinit.h";
300static const char *source_file_name = "init-opinit.c";
5079aa9a 301
ee65118b 302static bool
303handle_arg (const char *arg)
304{
305 switch (arg[1])
5079aa9a 306 {
ee65118b 307 case 'h':
308 header_file_name = &arg[2];
309 return true;
310 case 'c':
311 source_file_name = &arg[2];
312 return true;
313 default:
314 return false;
5079aa9a 315 }
5079aa9a 316}
5079aa9a 317
ee65118b 318static FILE *
319open_outfile (const char *file_name)
320{
321 FILE *f = fopen (file_name, "w");
322 if (!f)
323 fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
324 fprintf (f,
325 "/* Generated automatically by the program `genopinit'\n"
326 " from the machine description file `md'. */\n\n");
327 return f;
328}
947491b7 329
5079aa9a 330int
1a97be37 331main (int argc, char **argv)
5079aa9a 332{
ee65118b 333 FILE *h_file, *s_file;
334 unsigned int i, j, n, last_kind[5];
335 pattern *p;
5079aa9a 336
04b58880 337 progname = "genopinit";
5079aa9a 338
ee65118b 339 if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
340 fatal ("genopinit range assumptions invalid");
341
342 if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
c5ddd6b5 343 return (FATAL_EXIT_CODE);
5079aa9a 344
ee65118b 345 h_file = open_outfile (header_file_name);
346 s_file = open_outfile (source_file_name);
0beae642 347
5079aa9a 348 /* Read the machine description. */
5079aa9a 349 while (1)
350 {
c5ddd6b5 351 int line_no, insn_code_number = 0;
ee65118b 352 rtx desc = read_md_rtx (&line_no, &insn_code_number);
c5ddd6b5 353 if (desc == NULL)
5079aa9a 354 break;
5079aa9a 355 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
356 gen_insn (desc);
357 }
358
ee65118b 359 /* Sort the collected patterns. */
90a2d741 360 patterns.qsort (pattern_cmp);
ee65118b 361
362 /* Now that we've handled the "extra" patterns, eliminate them from
363 the optabs array. That way they don't get in the way below. */
364 n = ARRAY_SIZE (optabs);
365 for (i = 0; i < n; )
366 if (optabs[i].base == NULL)
367 optabs[i] = optabs[--n];
368 else
369 ++i;
370
371 /* Sort the (real) optabs. Better than forcing the optabs.def file to
372 remain sorted by kind. We also scrogged any real ordering with the
373 purging of the X patterns above. */
9af5ce0c 374 qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
ee65118b 375
376 /* Emit the optab enumeration for the header file. */
377 fprintf (h_file, "enum optab_tag {\n");
378 for (i = j = 0; i < n; ++i)
379 {
380 optabs[i].op = i;
381 fprintf (h_file, " %s,\n", optabs[i].name);
382 if (optabs[i].kind != j)
383 last_kind[j++] = i - 1;
384 }
385 fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
386 fprintf (h_file, " LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
387 fprintf (h_file, " LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
388 fprintf (h_file, " FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
389 fprintf (h_file, " LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
390 fprintf (h_file, " LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
391 fprintf (h_file, "};\n\n");
392
393 fprintf (h_file, "#define NUM_OPTABS %u\n", n);
394 fprintf (h_file, "#define NUM_CONVLIB_OPTABS %u\n",
395 last_kind[1] - last_kind[0]);
396 fprintf (h_file, "#define NUM_NORMLIB_OPTABS %u\n",
397 last_kind[3] - last_kind[2]);
398 fprintf (h_file, "#define NUM_OPTAB_PATTERNS %u\n",
f1f41a6c 399 (unsigned) patterns.length ());
ee65118b 400
401 fprintf (s_file,
402 "#include \"config.h\"\n"
403 "#include \"system.h\"\n"
404 "#include \"coretypes.h\"\n"
405 "#include \"tm.h\"\n"
41a8aa41 406 "#include \"tree.h\"\n"
9ed99284 407 "#include \"varasm.h\"\n"
408 "#include \"stor-layout.h\"\n"
409 "#include \"calls.h\"\n"
ee65118b 410 "#include \"rtl.h\"\n"
e5a23585 411 "#include \"predict.h\"\n"
ee65118b 412 "#include \"tm_p.h\"\n"
413 "#include \"flags.h\"\n"
414 "#include \"insn-config.h\"\n"
415 "#include \"expr.h\"\n"
416 "#include \"optabs.h\"\n"
417 "\n"
418 "struct optab_pat {\n"
419 " unsigned scode;\n"
420 " enum insn_code icode;\n"
421 "};\n\n");
422
423 fprintf (s_file,
424 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
f1f41a6c 425 for (i = 0; patterns.iterate (i, &p); ++i)
ee65118b 426 fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
427 fprintf (s_file, "};\n\n");
428
08c7d04b 429 fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
430 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
f1f41a6c 431 for (i = 0; patterns.iterate (i, &p); ++i)
ee65118b 432 fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name);
433 fprintf (s_file, "}\n\n");
434
435 /* Perform a binary search on a pre-encoded optab+mode*2. */
436 /* ??? Perhaps even better to generate a minimal perfect hash.
437 Using gperf directly is awkward since it's so geared to working
438 with strings. Plus we have no visibility into the ordering of
439 the hash entries, which complicates the pat_enable array. */
440 fprintf (s_file,
441 "static int\n"
442 "lookup_handler (unsigned scode)\n"
443 "{\n"
444 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
445 " while (h > l)\n"
446 " {\n"
447 " m = (h + l) / 2;\n"
448 " if (scode == pats[m].scode)\n"
449 " return m;\n"
450 " else if (scode < pats[m].scode)\n"
451 " h = m;\n"
452 " else\n"
453 " l = m + 1;\n"
454 " }\n"
455 " return -1;\n"
456 "}\n\n");
457
458 fprintf (s_file,
459 "enum insn_code\n"
460 "raw_optab_handler (unsigned scode)\n"
461 "{\n"
462 " int i = lookup_handler (scode);\n"
08c7d04b 463 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
ee65118b 464 " ? pats[i].icode : CODE_FOR_nothing);\n"
465 "}\n\n");
466
467 fprintf (s_file,
468 "bool\n"
3754d046 469 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
ee65118b 470 "{\n"
471 " unsigned scode = (op << 16) | m;\n"
472 " int i = lookup_handler (scode);\n"
473 " if (i >= 0)\n"
474 " {\n"
08c7d04b 475 " bool ret = this_fn_optabs->pat_enable[i];\n"
476 " this_fn_optabs->pat_enable[i] = set;\n"
ee65118b 477 " return ret;\n"
478 " }\n"
479 " else\n"
480 " {\n"
481 " gcc_assert (!set);\n"
482 " return false;\n"
483 " }\n"
484 "}\n\n");
485
486 /* C++ (even G++) does not support (non-trivial) designated initializers.
487 To work around that, generate these arrays programatically rather than
488 by our traditional multiple inclusion of def files. */
489
490 fprintf (s_file,
491 "const struct convert_optab_libcall_d "
492 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
493 for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
494 fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall);
495 fprintf (s_file, "};\n\n");
496
497 fprintf (s_file,
498 "const struct optab_libcall_d "
499 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
500 for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
501 fprintf (s_file, " { %s, %s, %s },\n",
502 optabs[i].suffix, optabs[i].base, optabs[i].libcall);
503 fprintf (s_file, "};\n\n");
504
505 fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
506 for (i = 0; i < n; ++i)
507 fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]);
508 fprintf (s_file, "};\n\n");
509
510 qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
511
512 fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
513 for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
514 continue;
515 for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
516 {
517 if (j < n && optabs[j].rcode == i)
518 fprintf (s_file, " %s,\n", optabs[j++].name);
519 else
520 fprintf (s_file, " unknown_optab,\n");
521 }
522 fprintf (s_file, "};\n\n");
523
524 return (fclose (h_file) == 0 && fclose (s_file) == 0
525 ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
5079aa9a 526}