1 /* Generate code to initialize optabs from machine description.
2 Copyright (C) 1993-2015 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
23 #include "coretypes.h"
27 #include "gensupport.h"
30 #define DEF_RTL_EXPR(V, N, X, C) #V,
32 static const char * const rtx_upname
[] = {
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
46 CX, NX, VX: An extra pattern entry for a conversion or normal optab.
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).
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.
56 $P means that both full and partial integer modes should be considered.
57 $Q means that only fixed-point modes should be considered.
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
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,
75 typedef enum optab_tag
{
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 },
107 typedef struct optab_def_d
120 static optab_def optabs
[] = {
121 { "unknown_optab", NULL
, NS
, ZS
, NS
, unknown_optab
, UNKNOWN
, UNKNOWN
, 0 },
122 #include "optabs.def"
137 /* Vector in which to collect insns that match. */
139 typedef struct pattern_d
144 unsigned int sort_num
;
148 static vec
<pattern
> patterns
;
151 match_pattern (pattern
*p
, const char *name
, const char *pat
)
153 bool force_float
= false;
154 bool force_int
= false;
155 bool force_partial_int
= false;
156 bool force_fixed
= false;
176 force_partial_int
= 1;
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
--)
197 for (p
= GET_MODE_NAME (i
), q
= name
; *p
; p
++, q
++)
198 if (TOLOWER (*p
) != *q
)
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
)
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
)
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
))
226 name
+= strlen (GET_MODE_NAME (i
));
233 force_partial_int
= false;
248 const char *name
= XSTR (insn
, 0);
252 /* Don't mention "unnamed" instructions. */
253 if (*name
== 0 || *name
== '*')
257 /* See if NAME matches one of the patterns we have for the optabs
259 for (pindex
= 0; pindex
< ARRAY_SIZE (optabs
); pindex
++)
262 if (match_pattern (&p
, name
, optabs
[pindex
].pattern
))
264 p
.op
= optabs
[pindex
].op
;
265 p
.sort_num
= (p
.op
<< 16) | (p
.m2
<< 8) | p
.m1
;
266 patterns
.safe_push (p
);
273 pattern_cmp (const void *va
, const void *vb
)
275 const pattern
*a
= (const pattern
*)va
;
276 const pattern
*b
= (const pattern
*)vb
;
277 return a
->sort_num
- b
->sort_num
;
281 optab_kind_cmp (const void *va
, const void *vb
)
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
;
287 diff
= a
->op
- b
->op
;
292 optab_rcode_cmp (const void *va
, const void *vb
)
294 const optab_def
*a
= (const optab_def
*)va
;
295 const optab_def
*b
= (const optab_def
*)vb
;
296 return a
->rcode
- b
->rcode
;
299 static const char *header_file_name
= "init-opinit.h";
300 static const char *source_file_name
= "init-opinit.c";
303 handle_arg (const char *arg
)
308 header_file_name
= &arg
[2];
311 source_file_name
= &arg
[2];
319 open_outfile (const char *file_name
)
321 FILE *f
= fopen (file_name
, "w");
323 fatal ("cannot open file %s: %s", file_name
, xstrerror (errno
));
325 "/* Generated automatically by the program `genopinit'\n"
326 " from the machine description file `md'. */\n\n");
331 main (int argc
, char **argv
)
333 FILE *h_file
, *s_file
;
334 unsigned int i
, j
, n
, last_kind
[5];
337 progname
= "genopinit";
339 if (NUM_OPTABS
> 0xffff || MAX_MACHINE_MODE
>= 0xff)
340 fatal ("genopinit range assumptions invalid");
342 if (!init_rtx_reader_args_cb (argc
, argv
, handle_arg
))
343 return (FATAL_EXIT_CODE
);
345 h_file
= open_outfile (header_file_name
);
346 s_file
= open_outfile (source_file_name
);
348 /* Read the machine description. */
351 int line_no
, insn_code_number
= 0;
352 rtx desc
= read_md_rtx (&line_no
, &insn_code_number
);
355 if (GET_CODE (desc
) == DEFINE_INSN
|| GET_CODE (desc
) == DEFINE_EXPAND
)
359 /* Sort the collected patterns. */
360 patterns
.qsort (pattern_cmp
);
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
);
366 if (optabs
[i
].base
== NULL
)
367 optabs
[i
] = optabs
[--n
];
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. */
374 qsort (optabs
, n
, sizeof (optab_def
), optab_kind_cmp
);
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
)
381 fprintf (h_file
, " %s,\n", optabs
[i
].name
);
382 if (optabs
[i
].kind
!= j
)
383 last_kind
[j
++] = i
- 1;
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");
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",
399 (unsigned) patterns
.length ());
402 "typedef enum optab_tag optab;\n"
403 "typedef enum optab_tag convert_optab;\n"
404 "typedef enum optab_tag direct_optab;\n"
406 "struct optab_libcall_d\n"
408 " char libcall_suffix;\n"
409 " const char *libcall_basename;\n"
410 " void (*libcall_gen) (optab, const char *name,\n"
411 " char suffix, machine_mode);\n"
414 "struct convert_optab_libcall_d\n"
416 " const char *libcall_basename;\n"
417 " void (*libcall_gen) (convert_optab, const char *name,\n"
418 " machine_mode, machine_mode);\n"
421 "/* Given an enum insn_code, access the function to construct\n"
422 " the body of that kind of insn. */\n"
423 "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
425 "/* Contains the optab used for each rtx code, and vice-versa. */\n"
426 "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
427 "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
429 "static inline optab\n"
430 "code_to_optab (enum rtx_code code)\n"
432 " return code_to_optab_[code];\n"
435 "static inline enum rtx_code\n"
436 "optab_to_code (optab op)\n"
438 " return optab_to_code_[op];\n"
441 "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
442 "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
444 "/* Returns the active icode for the given (encoded) optab. */\n"
445 "extern enum insn_code raw_optab_handler (unsigned);\n"
446 "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
448 "/* Target-dependent globals. */\n"
449 "struct target_optabs {\n"
450 " /* Patterns that are used by optabs that are enabled for this target. */\n"
451 " bool pat_enable[NUM_OPTAB_PATTERNS];\n"
453 "extern void init_all_optabs (struct target_optabs *);\n"
455 "extern struct target_optabs default_target_optabs;\n"
456 "extern struct target_optabs *this_fn_optabs;\n"
457 "#if SWITCHABLE_TARGET\n"
458 "extern struct target_optabs *this_target_optabs;\n"
460 "#define this_target_optabs (&default_target_optabs)\n"
464 "#include \"config.h\"\n"
465 "#include \"system.h\"\n"
466 "#include \"coretypes.h\"\n"
467 "#include \"backend.h\"\n"
468 "#include \"predict.h\"\n"
469 "#include \"tree.h\"\n"
470 "#include \"rtl.h\"\n"
471 "#include \"alias.h\"\n"
472 "#include \"varasm.h\"\n"
473 "#include \"stor-layout.h\"\n"
474 "#include \"calls.h\"\n"
475 "#include \"tm_p.h\"\n"
476 "#include \"flags.h\"\n"
477 "#include \"insn-config.h\"\n"
478 "#include \"expmed.h\"\n"
479 "#include \"dojump.h\"\n"
480 "#include \"explow.h\"\n"
481 "#include \"emit-rtl.h\"\n"
482 "#include \"stmt.h\"\n"
483 "#include \"expr.h\"\n"
484 "#include \"insn-codes.h\"\n"
485 "#include \"optabs.h\"\n"
487 "struct optab_pat {\n"
489 " enum insn_code icode;\n"
493 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
494 for (i
= 0; patterns
.iterate (i
, &p
); ++i
)
495 fprintf (s_file
, " { %#08x, CODE_FOR_%s },\n", p
->sort_num
, p
->name
);
496 fprintf (s_file
, "};\n\n");
498 fprintf (s_file
, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
499 fprintf (s_file
, " bool *ena = optabs->pat_enable;\n");
500 for (i
= 0; patterns
.iterate (i
, &p
); ++i
)
501 fprintf (s_file
, " ena[%u] = HAVE_%s;\n", i
, p
->name
);
502 fprintf (s_file
, "}\n\n");
504 /* Perform a binary search on a pre-encoded optab+mode*2. */
505 /* ??? Perhaps even better to generate a minimal perfect hash.
506 Using gperf directly is awkward since it's so geared to working
507 with strings. Plus we have no visibility into the ordering of
508 the hash entries, which complicates the pat_enable array. */
511 "lookup_handler (unsigned scode)\n"
513 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
516 " m = (h + l) / 2;\n"
517 " if (scode == pats[m].scode)\n"
519 " else if (scode < pats[m].scode)\n"
529 "raw_optab_handler (unsigned scode)\n"
531 " int i = lookup_handler (scode);\n"
532 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
533 " ? pats[i].icode : CODE_FOR_nothing);\n"
538 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
540 " unsigned scode = (op << 16) | m;\n"
541 " int i = lookup_handler (scode);\n"
544 " bool ret = this_fn_optabs->pat_enable[i];\n"
545 " this_fn_optabs->pat_enable[i] = set;\n"
550 " gcc_assert (!set);\n"
555 /* C++ (even G++) does not support (non-trivial) designated initializers.
556 To work around that, generate these arrays programatically rather than
557 by our traditional multiple inclusion of def files. */
560 "const struct convert_optab_libcall_d "
561 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
562 for (i
= last_kind
[0] + 1; i
<= last_kind
[1]; ++i
)
563 fprintf (s_file
, " { %s, %s },\n", optabs
[i
].base
, optabs
[i
].libcall
);
564 fprintf (s_file
, "};\n\n");
567 "const struct optab_libcall_d "
568 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
569 for (i
= last_kind
[2] + 1; i
<= last_kind
[3]; ++i
)
570 fprintf (s_file
, " { %s, %s, %s },\n",
571 optabs
[i
].suffix
, optabs
[i
].base
, optabs
[i
].libcall
);
572 fprintf (s_file
, "};\n\n");
574 fprintf (s_file
, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
575 for (i
= 0; i
< n
; ++i
)
576 fprintf (s_file
, " %s,\n", rtx_upname
[optabs
[i
].fcode
]);
577 fprintf (s_file
, "};\n\n");
579 qsort (optabs
, n
, sizeof (optab_def
), optab_rcode_cmp
);
581 fprintf (s_file
, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
582 for (j
= 0; optabs
[j
].rcode
== UNKNOWN
; ++j
)
584 for (i
= 0; i
< NON_GENERATOR_NUM_RTX_CODE
; ++i
)
586 if (j
< n
&& optabs
[j
].rcode
== i
)
587 fprintf (s_file
, " %s,\n", optabs
[j
++].name
);
589 fprintf (s_file
, " unknown_optab,\n");
591 fprintf (s_file
, "};\n\n");
593 return (fclose (h_file
) == 0 && fclose (s_file
) == 0
594 ? SUCCESS_EXIT_CODE
: FATAL_EXIT_CODE
);