]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genopinit.c
Update copyright years.
[thirdparty/gcc.git] / gcc / genopinit.c
CommitLineData
5079aa9a 1/* Generate code to initialize optabs from machine description.
f1717362 2 Copyright (C) 1993-2016 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
ee65118b 38/* Vector in which to collect insns that match. */
592e7d69 39static vec<optab_pattern> patterns;
12693c81 40
5079aa9a 41static void
c04601c1 42gen_insn (md_rtx_info *info)
5079aa9a 43{
592e7d69 44 optab_pattern p;
45 if (find_optab (&p, XSTR (info->def, 0)))
46 patterns.safe_push (p);
ee65118b 47}
5079aa9a 48
ee65118b 49static int
50pattern_cmp (const void *va, const void *vb)
51{
592e7d69 52 const optab_pattern *a = (const optab_pattern *)va;
53 const optab_pattern *b = (const optab_pattern *)vb;
ee65118b 54 return a->sort_num - b->sort_num;
55}
5079aa9a 56
ee65118b 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}
5079aa9a 67
ee65118b 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}
5079aa9a 75
ee65118b 76static const char *header_file_name = "init-opinit.h";
77static const char *source_file_name = "init-opinit.c";
5079aa9a 78
ee65118b 79static bool
80handle_arg (const char *arg)
81{
82 switch (arg[1])
5079aa9a 83 {
ee65118b 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;
5079aa9a 92 }
5079aa9a 93}
5079aa9a 94
ee65118b 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}
947491b7 106
5079aa9a 107int
1a97be37 108main (int argc, char **argv)
5079aa9a 109{
ee65118b 110 FILE *h_file, *s_file;
111 unsigned int i, j, n, last_kind[5];
592e7d69 112 optab_pattern *p;
5079aa9a 113
04b58880 114 progname = "genopinit";
5079aa9a 115
ee65118b 116 if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
117 fatal ("genopinit range assumptions invalid");
118
119 if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
c5ddd6b5 120 return (FATAL_EXIT_CODE);
5079aa9a 121
ee65118b 122 h_file = open_outfile (header_file_name);
123 s_file = open_outfile (source_file_name);
0beae642 124
5079aa9a 125 /* Read the machine description. */
c04601c1 126 md_rtx_info info;
127 while (read_md_rtx (&info))
128 switch (GET_CODE (info.def))
129 {
130 case DEFINE_INSN:
131 case DEFINE_EXPAND:
132 gen_insn (&info);
5079aa9a 133 break;
c04601c1 134
135 default:
136 break;
137 }
5079aa9a 138
ee65118b 139 /* Sort the collected patterns. */
90a2d741 140 patterns.qsort (pattern_cmp);
ee65118b 141
142 /* Now that we've handled the "extra" patterns, eliminate them from
143 the optabs array. That way they don't get in the way below. */
592e7d69 144 n = num_optabs;
ee65118b 145 for (i = 0; i < n; )
146 if (optabs[i].base == NULL)
147 optabs[i] = optabs[--n];
148 else
149 ++i;
150
151 /* Sort the (real) optabs. Better than forcing the optabs.def file to
152 remain sorted by kind. We also scrogged any real ordering with the
153 purging of the X patterns above. */
9af5ce0c 154 qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
ee65118b 155
947ed59a 156 fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
157 fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
158
ee65118b 159 /* Emit the optab enumeration for the header file. */
160 fprintf (h_file, "enum optab_tag {\n");
161 for (i = j = 0; i < n; ++i)
162 {
163 optabs[i].op = i;
164 fprintf (h_file, " %s,\n", optabs[i].name);
165 if (optabs[i].kind != j)
166 last_kind[j++] = i - 1;
167 }
168 fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
169 fprintf (h_file, " LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
170 fprintf (h_file, " LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
171 fprintf (h_file, " FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
172 fprintf (h_file, " LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
173 fprintf (h_file, " LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
174 fprintf (h_file, "};\n\n");
175
176 fprintf (h_file, "#define NUM_OPTABS %u\n", n);
177 fprintf (h_file, "#define NUM_CONVLIB_OPTABS %u\n",
178 last_kind[1] - last_kind[0]);
179 fprintf (h_file, "#define NUM_NORMLIB_OPTABS %u\n",
180 last_kind[3] - last_kind[2]);
181 fprintf (h_file, "#define NUM_OPTAB_PATTERNS %u\n",
f1f41a6c 182 (unsigned) patterns.length ());
ee65118b 183
34517c64 184 fprintf (h_file,
185 "typedef enum optab_tag optab;\n"
186 "typedef enum optab_tag convert_optab;\n"
187 "typedef enum optab_tag direct_optab;\n"
188 "\n"
189 "struct optab_libcall_d\n"
190 "{\n"
191 " char libcall_suffix;\n"
192 " const char *libcall_basename;\n"
193 " void (*libcall_gen) (optab, const char *name,\n"
194 " char suffix, machine_mode);\n"
195 "};\n"
196 "\n"
197 "struct convert_optab_libcall_d\n"
198 "{\n"
199 " const char *libcall_basename;\n"
200 " void (*libcall_gen) (convert_optab, const char *name,\n"
201 " machine_mode, machine_mode);\n"
202 "};\n"
203 "\n"
204 "/* Given an enum insn_code, access the function to construct\n"
205 " the body of that kind of insn. */\n"
206 "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
207 "\n"
947ed59a 208 "#ifdef NUM_RTX_CODE\n"
34517c64 209 "/* Contains the optab used for each rtx code, and vice-versa. */\n"
210 "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
211 "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
212 "\n"
213 "static inline optab\n"
214 "code_to_optab (enum rtx_code code)\n"
215 "{\n"
216 " return code_to_optab_[code];\n"
217 "}\n"
218 "\n"
219 "static inline enum rtx_code\n"
220 "optab_to_code (optab op)\n"
221 "{\n"
222 " return optab_to_code_[op];\n"
223 "}\n"
947ed59a 224 "#endif\n"
34517c64 225 "\n"
226 "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
227 "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
228 "\n"
229 "/* Returns the active icode for the given (encoded) optab. */\n"
230 "extern enum insn_code raw_optab_handler (unsigned);\n"
231 "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
232 "\n"
233 "/* Target-dependent globals. */\n"
234 "struct target_optabs {\n"
235 " /* Patterns that are used by optabs that are enabled for this target. */\n"
236 " bool pat_enable[NUM_OPTAB_PATTERNS];\n"
237 "};\n"
238 "extern void init_all_optabs (struct target_optabs *);\n"
239 "\n"
240 "extern struct target_optabs default_target_optabs;\n"
241 "extern struct target_optabs *this_fn_optabs;\n"
242 "#if SWITCHABLE_TARGET\n"
243 "extern struct target_optabs *this_target_optabs;\n"
244 "#else\n"
245 "#define this_target_optabs (&default_target_optabs)\n"
246 "#endif\n");
247
ee65118b 248 fprintf (s_file,
249 "#include \"config.h\"\n"
250 "#include \"system.h\"\n"
251 "#include \"coretypes.h\"\n"
9ef16211 252 "#include \"backend.h\"\n"
d040a5b0 253 "#include \"predict.h\"\n"
41a8aa41 254 "#include \"tree.h\"\n"
9ef16211 255 "#include \"rtl.h\"\n"
256 "#include \"alias.h\"\n"
9ed99284 257 "#include \"varasm.h\"\n"
258 "#include \"stor-layout.h\"\n"
259 "#include \"calls.h\"\n"
ee65118b 260 "#include \"tm_p.h\"\n"
261 "#include \"flags.h\"\n"
262 "#include \"insn-config.h\"\n"
d53441c8 263 "#include \"expmed.h\"\n"
264 "#include \"dojump.h\"\n"
265 "#include \"explow.h\"\n"
266 "#include \"emit-rtl.h\"\n"
267 "#include \"stmt.h\"\n"
ee65118b 268 "#include \"expr.h\"\n"
34517c64 269 "#include \"insn-codes.h\"\n"
ee65118b 270 "#include \"optabs.h\"\n"
271 "\n"
272 "struct optab_pat {\n"
273 " unsigned scode;\n"
274 " enum insn_code icode;\n"
275 "};\n\n");
276
277 fprintf (s_file,
278 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
f1f41a6c 279 for (i = 0; patterns.iterate (i, &p); ++i)
ee65118b 280 fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
281 fprintf (s_file, "};\n\n");
282
08c7d04b 283 fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
284 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
f1f41a6c 285 for (i = 0; patterns.iterate (i, &p); ++i)
ee65118b 286 fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name);
287 fprintf (s_file, "}\n\n");
288
289 /* Perform a binary search on a pre-encoded optab+mode*2. */
290 /* ??? Perhaps even better to generate a minimal perfect hash.
291 Using gperf directly is awkward since it's so geared to working
292 with strings. Plus we have no visibility into the ordering of
293 the hash entries, which complicates the pat_enable array. */
294 fprintf (s_file,
295 "static int\n"
296 "lookup_handler (unsigned scode)\n"
297 "{\n"
298 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
299 " while (h > l)\n"
300 " {\n"
301 " m = (h + l) / 2;\n"
302 " if (scode == pats[m].scode)\n"
303 " return m;\n"
304 " else if (scode < pats[m].scode)\n"
305 " h = m;\n"
306 " else\n"
307 " l = m + 1;\n"
308 " }\n"
309 " return -1;\n"
310 "}\n\n");
311
312 fprintf (s_file,
313 "enum insn_code\n"
314 "raw_optab_handler (unsigned scode)\n"
315 "{\n"
316 " int i = lookup_handler (scode);\n"
08c7d04b 317 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
ee65118b 318 " ? pats[i].icode : CODE_FOR_nothing);\n"
319 "}\n\n");
320
321 fprintf (s_file,
322 "bool\n"
3754d046 323 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
ee65118b 324 "{\n"
325 " unsigned scode = (op << 16) | m;\n"
326 " int i = lookup_handler (scode);\n"
327 " if (i >= 0)\n"
328 " {\n"
08c7d04b 329 " bool ret = this_fn_optabs->pat_enable[i];\n"
330 " this_fn_optabs->pat_enable[i] = set;\n"
ee65118b 331 " return ret;\n"
332 " }\n"
333 " else\n"
334 " {\n"
335 " gcc_assert (!set);\n"
336 " return false;\n"
337 " }\n"
338 "}\n\n");
339
340 /* C++ (even G++) does not support (non-trivial) designated initializers.
341 To work around that, generate these arrays programatically rather than
342 by our traditional multiple inclusion of def files. */
343
344 fprintf (s_file,
345 "const struct convert_optab_libcall_d "
346 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
347 for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
348 fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall);
349 fprintf (s_file, "};\n\n");
350
351 fprintf (s_file,
352 "const struct optab_libcall_d "
353 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
354 for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
355 fprintf (s_file, " { %s, %s, %s },\n",
356 optabs[i].suffix, optabs[i].base, optabs[i].libcall);
357 fprintf (s_file, "};\n\n");
358
359 fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
360 for (i = 0; i < n; ++i)
361 fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]);
362 fprintf (s_file, "};\n\n");
363
364 qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
365
366 fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
367 for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
368 continue;
369 for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
370 {
371 if (j < n && optabs[j].rcode == i)
372 fprintf (s_file, " %s,\n", optabs[j++].name);
373 else
374 fprintf (s_file, " unknown_optab,\n");
375 }
376 fprintf (s_file, "};\n\n");
377
947ed59a 378 fprintf (h_file, "#endif\n");
ee65118b 379 return (fclose (h_file) == 0 && fclose (s_file) == 0
380 ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
5079aa9a 381}