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
[] = {
38 /* Vector in which to collect insns that match. */
39 static vec
<optab_pattern
> patterns
;
42 gen_insn (md_rtx_info
*info
)
45 if (find_optab (&p
, XSTR (info
->def
, 0)))
46 patterns
.safe_push (p
);
50 pattern_cmp (const void *va
, const void *vb
)
52 const optab_pattern
*a
= (const optab_pattern
*)va
;
53 const optab_pattern
*b
= (const optab_pattern
*)vb
;
54 return a
->sort_num
- b
->sort_num
;
58 optab_kind_cmp (const void *va
, const void *vb
)
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
;
69 optab_rcode_cmp (const void *va
, const void *vb
)
71 const optab_def
*a
= (const optab_def
*)va
;
72 const optab_def
*b
= (const optab_def
*)vb
;
73 return a
->rcode
- b
->rcode
;
76 static const char *header_file_name
= "init-opinit.h";
77 static const char *source_file_name
= "init-opinit.c";
80 handle_arg (const char *arg
)
85 header_file_name
= &arg
[2];
88 source_file_name
= &arg
[2];
96 open_outfile (const char *file_name
)
98 FILE *f
= fopen (file_name
, "w");
100 fatal ("cannot open file %s: %s", file_name
, xstrerror (errno
));
102 "/* Generated automatically by the program `genopinit'\n"
103 " from the machine description file `md'. */\n\n");
108 main (int argc
, char **argv
)
110 FILE *h_file
, *s_file
;
111 unsigned int i
, j
, n
, last_kind
[5];
114 progname
= "genopinit";
116 if (NUM_OPTABS
> 0xffff || MAX_MACHINE_MODE
>= 0xff)
117 fatal ("genopinit range assumptions invalid");
119 if (!init_rtx_reader_args_cb (argc
, argv
, handle_arg
))
120 return (FATAL_EXIT_CODE
);
122 h_file
= open_outfile (header_file_name
);
123 s_file
= open_outfile (source_file_name
);
125 /* Read the machine description. */
127 while (read_md_rtx (&info
))
128 switch (GET_CODE (info
.def
))
139 /* Sort the collected patterns. */
140 patterns
.qsort (pattern_cmp
);
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. */
146 if (optabs
[i
].base
== NULL
)
147 optabs
[i
] = optabs
[--n
];
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. */
154 qsort (optabs
, n
, sizeof (optab_def
), optab_kind_cmp
);
156 fprintf (h_file
, "#ifndef GCC_INSN_OPINIT_H\n");
157 fprintf (h_file
, "#define GCC_INSN_OPINIT_H 1\n");
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
)
164 fprintf (h_file
, " %s,\n", optabs
[i
].name
);
165 if (optabs
[i
].kind
!= j
)
166 last_kind
[j
++] = i
- 1;
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");
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",
182 (unsigned) patterns
.length ());
185 "typedef enum optab_tag optab;\n"
186 "typedef enum optab_tag convert_optab;\n"
187 "typedef enum optab_tag direct_optab;\n"
189 "struct optab_libcall_d\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"
197 "struct convert_optab_libcall_d\n"
199 " const char *libcall_basename;\n"
200 " void (*libcall_gen) (convert_optab, const char *name,\n"
201 " machine_mode, machine_mode);\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"
208 "#ifdef NUM_RTX_CODE\n"
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"
213 "static inline optab\n"
214 "code_to_optab (enum rtx_code code)\n"
216 " return code_to_optab_[code];\n"
219 "static inline enum rtx_code\n"
220 "optab_to_code (optab op)\n"
222 " return optab_to_code_[op];\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"
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"
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"
238 "extern void init_all_optabs (struct target_optabs *);\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"
245 "#define this_target_optabs (&default_target_optabs)\n"
249 "#include \"config.h\"\n"
250 "#include \"system.h\"\n"
251 "#include \"coretypes.h\"\n"
252 "#include \"backend.h\"\n"
253 "#include \"predict.h\"\n"
254 "#include \"tree.h\"\n"
255 "#include \"rtl.h\"\n"
256 "#include \"alias.h\"\n"
257 "#include \"varasm.h\"\n"
258 "#include \"stor-layout.h\"\n"
259 "#include \"calls.h\"\n"
260 "#include \"tm_p.h\"\n"
261 "#include \"flags.h\"\n"
262 "#include \"insn-config.h\"\n"
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"
268 "#include \"expr.h\"\n"
269 "#include \"insn-codes.h\"\n"
270 "#include \"optabs.h\"\n"
272 "struct optab_pat {\n"
274 " enum insn_code icode;\n"
278 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
279 for (i
= 0; patterns
.iterate (i
, &p
); ++i
)
280 fprintf (s_file
, " { %#08x, CODE_FOR_%s },\n", p
->sort_num
, p
->name
);
281 fprintf (s_file
, "};\n\n");
283 fprintf (s_file
, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
284 fprintf (s_file
, " bool *ena = optabs->pat_enable;\n");
285 for (i
= 0; patterns
.iterate (i
, &p
); ++i
)
286 fprintf (s_file
, " ena[%u] = HAVE_%s;\n", i
, p
->name
);
287 fprintf (s_file
, "}\n\n");
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. */
296 "lookup_handler (unsigned scode)\n"
298 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
301 " m = (h + l) / 2;\n"
302 " if (scode == pats[m].scode)\n"
304 " else if (scode < pats[m].scode)\n"
314 "raw_optab_handler (unsigned scode)\n"
316 " int i = lookup_handler (scode);\n"
317 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
318 " ? pats[i].icode : CODE_FOR_nothing);\n"
323 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
325 " unsigned scode = (op << 16) | m;\n"
326 " int i = lookup_handler (scode);\n"
329 " bool ret = this_fn_optabs->pat_enable[i];\n"
330 " this_fn_optabs->pat_enable[i] = set;\n"
335 " gcc_assert (!set);\n"
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. */
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");
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");
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");
364 qsort (optabs
, n
, sizeof (optab_def
), optab_rcode_cmp
);
366 fprintf (s_file
, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
367 for (j
= 0; optabs
[j
].rcode
== UNKNOWN
; ++j
)
369 for (i
= 0; i
< NON_GENERATOR_NUM_RTX_CODE
; ++i
)
371 if (j
< n
&& optabs
[j
].rcode
== i
)
372 fprintf (s_file
, " %s,\n", optabs
[j
++].name
);
374 fprintf (s_file
, " unknown_optab,\n");
376 fprintf (s_file
, "};\n\n");
378 fprintf (h_file
, "#endif\n");
379 return (fclose (h_file
) == 0 && fclose (s_file
) == 0
380 ? SUCCESS_EXIT_CODE
: FATAL_EXIT_CODE
);