1 /* Generate code to initialize optabs from machine description.
2 Copyright (C) 1993-2012 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 DEF_VEC_ALLOC_O(pattern
, heap
);
150 static VEC(pattern
, heap
) *patterns
;
153 match_pattern (pattern
*p
, const char *name
, const char *pat
)
155 bool force_float
= false;
156 bool force_int
= false;
157 bool force_partial_int
= false;
158 bool force_fixed
= false;
178 force_partial_int
= 1;
192 /* This loop will stop at the first prefix match, so
193 look through the modes in reverse order, in case
194 there are extra CC modes and CC is a prefix of the
195 CC modes (as it should be). */
196 for (i
= (MAX_MACHINE_MODE
) - 1; i
>= 0; i
--)
199 for (p
= GET_MODE_NAME(i
), q
= name
; *p
; p
++, q
++)
200 if (TOLOWER (*p
) != *q
)
203 && (! force_int
|| mode_class
[i
] == MODE_INT
204 || mode_class
[i
] == MODE_VECTOR_INT
)
205 && (! force_partial_int
206 || mode_class
[i
] == MODE_INT
207 || mode_class
[i
] == MODE_PARTIAL_INT
208 || mode_class
[i
] == MODE_VECTOR_INT
)
210 || mode_class
[i
] == MODE_FLOAT
211 || mode_class
[i
] == MODE_DECIMAL_FLOAT
212 || mode_class
[i
] == MODE_COMPLEX_FLOAT
213 || mode_class
[i
] == MODE_VECTOR_FLOAT
)
215 || mode_class
[i
] == MODE_FRACT
216 || mode_class
[i
] == MODE_UFRACT
217 || mode_class
[i
] == MODE_ACCUM
218 || mode_class
[i
] == MODE_UACCUM
219 || mode_class
[i
] == MODE_VECTOR_FRACT
220 || mode_class
[i
] == MODE_VECTOR_UFRACT
221 || mode_class
[i
] == MODE_VECTOR_ACCUM
222 || mode_class
[i
] == MODE_VECTOR_UACCUM
))
228 name
+= strlen (GET_MODE_NAME (i
));
235 force_partial_int
= false;
250 const char *name
= XSTR (insn
, 0);
254 /* Don't mention "unnamed" instructions. */
255 if (*name
== 0 || *name
== '*')
259 /* See if NAME matches one of the patterns we have for the optabs
261 for (pindex
= 0; pindex
< ARRAY_SIZE (optabs
); pindex
++)
264 if (match_pattern (&p
, name
, optabs
[pindex
].pattern
))
266 p
.op
= optabs
[pindex
].op
;
267 p
.sort_num
= (p
.op
<< 16) | (p
.m2
<< 8) | p
.m1
;
268 VEC_safe_push (pattern
, heap
, patterns
, p
);
275 pattern_cmp (const void *va
, const void *vb
)
277 const pattern
*a
= (const pattern
*)va
;
278 const pattern
*b
= (const pattern
*)vb
;
279 return a
->sort_num
- b
->sort_num
;
283 optab_kind_cmp (const void *va
, const void *vb
)
285 const optab_def
*a
= (const optab_def
*)va
;
286 const optab_def
*b
= (const optab_def
*)vb
;
287 int diff
= a
->kind
- b
->kind
;
289 diff
= a
->op
- b
->op
;
294 optab_rcode_cmp (const void *va
, const void *vb
)
296 const optab_def
*a
= (const optab_def
*)va
;
297 const optab_def
*b
= (const optab_def
*)vb
;
298 return a
->rcode
- b
->rcode
;
301 static const char *header_file_name
= "init-opinit.h";
302 static const char *source_file_name
= "init-opinit.c";
305 handle_arg (const char *arg
)
310 header_file_name
= &arg
[2];
313 source_file_name
= &arg
[2];
321 open_outfile (const char *file_name
)
323 FILE *f
= fopen (file_name
, "w");
325 fatal ("cannot open file %s: %s", file_name
, xstrerror (errno
));
327 "/* Generated automatically by the program `genopinit'\n"
328 " from the machine description file `md'. */\n\n");
333 main (int argc
, char **argv
)
335 FILE *h_file
, *s_file
;
336 unsigned int i
, j
, n
, last_kind
[5];
339 progname
= "genopinit";
341 if (NUM_OPTABS
> 0xffff || MAX_MACHINE_MODE
>= 0xff)
342 fatal ("genopinit range assumptions invalid");
344 if (!init_rtx_reader_args_cb (argc
, argv
, handle_arg
))
345 return (FATAL_EXIT_CODE
);
347 h_file
= open_outfile (header_file_name
);
348 s_file
= open_outfile (source_file_name
);
350 /* Read the machine description. */
353 int line_no
, insn_code_number
= 0;
354 rtx desc
= read_md_rtx (&line_no
, &insn_code_number
);
357 if (GET_CODE (desc
) == DEFINE_INSN
|| GET_CODE (desc
) == DEFINE_EXPAND
)
361 /* Sort the collected patterns. */
362 qsort (VEC_address (pattern
, patterns
), VEC_length (pattern
, patterns
),
363 sizeof (pattern
), pattern_cmp
);
365 /* Now that we've handled the "extra" patterns, eliminate them from
366 the optabs array. That way they don't get in the way below. */
367 n
= ARRAY_SIZE (optabs
);
369 if (optabs
[i
].base
== NULL
)
370 optabs
[i
] = optabs
[--n
];
374 /* Sort the (real) optabs. Better than forcing the optabs.def file to
375 remain sorted by kind. We also scrogged any real ordering with the
376 purging of the X patterns above. */
377 qsort (optabs
, n
, sizeof(optab_def
), optab_kind_cmp
);
379 /* Emit the optab enumeration for the header file. */
380 fprintf (h_file
, "enum optab_tag {\n");
381 for (i
= j
= 0; i
< n
; ++i
)
384 fprintf (h_file
, " %s,\n", optabs
[i
].name
);
385 if (optabs
[i
].kind
!= j
)
386 last_kind
[j
++] = i
- 1;
388 fprintf (h_file
, " FIRST_CONV_OPTAB = %s,\n", optabs
[last_kind
[0]+1].name
);
389 fprintf (h_file
, " LAST_CONVLIB_OPTAB = %s,\n", optabs
[last_kind
[1]].name
);
390 fprintf (h_file
, " LAST_CONV_OPTAB = %s,\n", optabs
[last_kind
[2]].name
);
391 fprintf (h_file
, " FIRST_NORM_OPTAB = %s,\n", optabs
[last_kind
[2]+1].name
);
392 fprintf (h_file
, " LAST_NORMLIB_OPTAB = %s,\n", optabs
[last_kind
[3]].name
);
393 fprintf (h_file
, " LAST_NORM_OPTAB = %s\n", optabs
[i
-1].name
);
394 fprintf (h_file
, "};\n\n");
396 fprintf (h_file
, "#define NUM_OPTABS %u\n", n
);
397 fprintf (h_file
, "#define NUM_CONVLIB_OPTABS %u\n",
398 last_kind
[1] - last_kind
[0]);
399 fprintf (h_file
, "#define NUM_NORMLIB_OPTABS %u\n",
400 last_kind
[3] - last_kind
[2]);
401 fprintf (h_file
, "#define NUM_OPTAB_PATTERNS %u\n",
402 (unsigned) VEC_length (pattern
, patterns
));
405 "#include \"config.h\"\n"
406 "#include \"system.h\"\n"
407 "#include \"coretypes.h\"\n"
408 "#include \"tm.h\"\n"
409 "#include \"rtl.h\"\n"
410 "#include \"tm_p.h\"\n"
411 "#include \"flags.h\"\n"
412 "#include \"insn-config.h\"\n"
413 "#include \"expr.h\"\n"
414 "#include \"optabs.h\"\n"
416 "struct optab_pat {\n"
418 " enum insn_code icode;\n"
422 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
423 for (i
= 0; VEC_iterate (pattern
, patterns
, i
, p
); ++i
)
424 fprintf (s_file
, " { %#08x, CODE_FOR_%s },\n", p
->sort_num
, p
->name
);
425 fprintf (s_file
, "};\n\n");
427 fprintf (s_file
, "void\ninit_all_optabs (void)\n{\n");
428 fprintf (s_file
, " bool *ena = this_target_optabs->pat_enable;\n");
429 for (i
= 0; VEC_iterate (pattern
, patterns
, i
, p
); ++i
)
430 fprintf (s_file
, " ena[%u] = HAVE_%s;\n", i
, p
->name
);
431 fprintf (s_file
, "}\n\n");
433 /* Perform a binary search on a pre-encoded optab+mode*2. */
434 /* ??? Perhaps even better to generate a minimal perfect hash.
435 Using gperf directly is awkward since it's so geared to working
436 with strings. Plus we have no visibility into the ordering of
437 the hash entries, which complicates the pat_enable array. */
440 "lookup_handler (unsigned scode)\n"
442 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
445 " m = (h + l) / 2;\n"
446 " if (scode == pats[m].scode)\n"
448 " else if (scode < pats[m].scode)\n"
458 "raw_optab_handler (unsigned scode)\n"
460 " int i = lookup_handler (scode);\n"
461 " return (i >= 0 && this_target_optabs->pat_enable[i]\n"
462 " ? pats[i].icode : CODE_FOR_nothing);\n"
467 "swap_optab_enable (optab op, enum machine_mode m, bool set)\n"
469 " unsigned scode = (op << 16) | m;\n"
470 " int i = lookup_handler (scode);\n"
473 " bool ret = this_target_optabs->pat_enable[i];\n"
474 " this_target_optabs->pat_enable[i] = set;\n"
479 " gcc_assert (!set);\n"
484 /* C++ (even G++) does not support (non-trivial) designated initializers.
485 To work around that, generate these arrays programatically rather than
486 by our traditional multiple inclusion of def files. */
489 "const struct convert_optab_libcall_d "
490 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
491 for (i
= last_kind
[0] + 1; i
<= last_kind
[1]; ++i
)
492 fprintf (s_file
, " { %s, %s },\n", optabs
[i
].base
, optabs
[i
].libcall
);
493 fprintf (s_file
, "};\n\n");
496 "const struct optab_libcall_d "
497 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
498 for (i
= last_kind
[2] + 1; i
<= last_kind
[3]; ++i
)
499 fprintf (s_file
, " { %s, %s, %s },\n",
500 optabs
[i
].suffix
, optabs
[i
].base
, optabs
[i
].libcall
);
501 fprintf (s_file
, "};\n\n");
503 fprintf (s_file
, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
504 for (i
= 0; i
< n
; ++i
)
505 fprintf (s_file
, " %s,\n", rtx_upname
[optabs
[i
].fcode
]);
506 fprintf (s_file
, "};\n\n");
508 qsort (optabs
, n
, sizeof (optab_def
), optab_rcode_cmp
);
510 fprintf (s_file
, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
511 for (j
= 0; optabs
[j
].rcode
== UNKNOWN
; ++j
)
513 for (i
= 0; i
< NON_GENERATOR_NUM_RTX_CODE
; ++i
)
515 if (j
< n
&& optabs
[j
].rcode
== i
)
516 fprintf (s_file
, " %s,\n", optabs
[j
++].name
);
518 fprintf (s_file
, " unknown_optab,\n");
520 fprintf (s_file
, "};\n\n");
522 return (fclose (h_file
) == 0 && fclose (s_file
) == 0
523 ? SUCCESS_EXIT_CODE
: FATAL_EXIT_CODE
);