1*38fd1498Szrj /* Generate code to initialize optabs from machine description.
2*38fd1498Szrj Copyright (C) 1993-2018 Free Software Foundation, Inc.
3*38fd1498Szrj
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3. If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>. */
19*38fd1498Szrj
20*38fd1498Szrj
21*38fd1498Szrj #include "bconfig.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "tm.h"
25*38fd1498Szrj #include "rtl.h"
26*38fd1498Szrj #include "errors.h"
27*38fd1498Szrj #include "gensupport.h"
28*38fd1498Szrj
29*38fd1498Szrj
30*38fd1498Szrj #define DEF_RTL_EXPR(V, N, X, C) #V,
31*38fd1498Szrj
32*38fd1498Szrj static const char * const rtx_upname[] = {
33*38fd1498Szrj #include "rtl.def"
34*38fd1498Szrj };
35*38fd1498Szrj
36*38fd1498Szrj #undef DEF_RTL_EXPR
37*38fd1498Szrj
38*38fd1498Szrj /* Vector in which to collect insns that match. */
39*38fd1498Szrj static vec<optab_pattern> patterns;
40*38fd1498Szrj
41*38fd1498Szrj static void
gen_insn(md_rtx_info * info)42*38fd1498Szrj gen_insn (md_rtx_info *info)
43*38fd1498Szrj {
44*38fd1498Szrj optab_pattern p;
45*38fd1498Szrj if (find_optab (&p, XSTR (info->def, 0)))
46*38fd1498Szrj patterns.safe_push (p);
47*38fd1498Szrj }
48*38fd1498Szrj
49*38fd1498Szrj static int
pattern_cmp(const void * va,const void * vb)50*38fd1498Szrj pattern_cmp (const void *va, const void *vb)
51*38fd1498Szrj {
52*38fd1498Szrj const optab_pattern *a = (const optab_pattern *)va;
53*38fd1498Szrj const optab_pattern *b = (const optab_pattern *)vb;
54*38fd1498Szrj return a->sort_num - b->sort_num;
55*38fd1498Szrj }
56*38fd1498Szrj
57*38fd1498Szrj static int
optab_kind_cmp(const void * va,const void * vb)58*38fd1498Szrj optab_kind_cmp (const void *va, const void *vb)
59*38fd1498Szrj {
60*38fd1498Szrj const optab_def *a = (const optab_def *)va;
61*38fd1498Szrj const optab_def *b = (const optab_def *)vb;
62*38fd1498Szrj int diff = a->kind - b->kind;
63*38fd1498Szrj if (diff == 0)
64*38fd1498Szrj diff = a->op - b->op;
65*38fd1498Szrj return diff;
66*38fd1498Szrj }
67*38fd1498Szrj
68*38fd1498Szrj static int
optab_rcode_cmp(const void * va,const void * vb)69*38fd1498Szrj optab_rcode_cmp (const void *va, const void *vb)
70*38fd1498Szrj {
71*38fd1498Szrj const optab_def *a = (const optab_def *)va;
72*38fd1498Szrj const optab_def *b = (const optab_def *)vb;
73*38fd1498Szrj return a->rcode - b->rcode;
74*38fd1498Szrj }
75*38fd1498Szrj
76*38fd1498Szrj static const char *header_file_name = "init-opinit.h";
77*38fd1498Szrj static const char *source_file_name = "init-opinit.c";
78*38fd1498Szrj
79*38fd1498Szrj static bool
handle_arg(const char * arg)80*38fd1498Szrj handle_arg (const char *arg)
81*38fd1498Szrj {
82*38fd1498Szrj switch (arg[1])
83*38fd1498Szrj {
84*38fd1498Szrj case 'h':
85*38fd1498Szrj header_file_name = &arg[2];
86*38fd1498Szrj return true;
87*38fd1498Szrj case 'c':
88*38fd1498Szrj source_file_name = &arg[2];
89*38fd1498Szrj return true;
90*38fd1498Szrj default:
91*38fd1498Szrj return false;
92*38fd1498Szrj }
93*38fd1498Szrj }
94*38fd1498Szrj
95*38fd1498Szrj static FILE *
open_outfile(const char * file_name)96*38fd1498Szrj open_outfile (const char *file_name)
97*38fd1498Szrj {
98*38fd1498Szrj FILE *f = fopen (file_name, "w");
99*38fd1498Szrj if (!f)
100*38fd1498Szrj fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
101*38fd1498Szrj fprintf (f,
102*38fd1498Szrj "/* Generated automatically by the program `genopinit'\n"
103*38fd1498Szrj " from the machine description file `md'. */\n\n");
104*38fd1498Szrj return f;
105*38fd1498Szrj }
106*38fd1498Szrj
107*38fd1498Szrj int
main(int argc,const char ** argv)108*38fd1498Szrj main (int argc, const char **argv)
109*38fd1498Szrj {
110*38fd1498Szrj FILE *h_file, *s_file;
111*38fd1498Szrj unsigned int i, j, n, last_kind[5];
112*38fd1498Szrj optab_pattern *p;
113*38fd1498Szrj
114*38fd1498Szrj progname = "genopinit";
115*38fd1498Szrj
116*38fd1498Szrj if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
117*38fd1498Szrj fatal ("genopinit range assumptions invalid");
118*38fd1498Szrj
119*38fd1498Szrj if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
120*38fd1498Szrj return (FATAL_EXIT_CODE);
121*38fd1498Szrj
122*38fd1498Szrj h_file = open_outfile (header_file_name);
123*38fd1498Szrj s_file = open_outfile (source_file_name);
124*38fd1498Szrj
125*38fd1498Szrj /* Read the machine description. */
126*38fd1498Szrj md_rtx_info info;
127*38fd1498Szrj while (read_md_rtx (&info))
128*38fd1498Szrj switch (GET_CODE (info.def))
129*38fd1498Szrj {
130*38fd1498Szrj case DEFINE_INSN:
131*38fd1498Szrj case DEFINE_EXPAND:
132*38fd1498Szrj gen_insn (&info);
133*38fd1498Szrj break;
134*38fd1498Szrj
135*38fd1498Szrj default:
136*38fd1498Szrj break;
137*38fd1498Szrj }
138*38fd1498Szrj
139*38fd1498Szrj /* Sort the collected patterns. */
140*38fd1498Szrj patterns.qsort (pattern_cmp);
141*38fd1498Szrj
142*38fd1498Szrj /* Now that we've handled the "extra" patterns, eliminate them from
143*38fd1498Szrj the optabs array. That way they don't get in the way below. */
144*38fd1498Szrj n = num_optabs;
145*38fd1498Szrj for (i = 0; i < n; )
146*38fd1498Szrj if (optabs[i].base == NULL)
147*38fd1498Szrj optabs[i] = optabs[--n];
148*38fd1498Szrj else
149*38fd1498Szrj ++i;
150*38fd1498Szrj
151*38fd1498Szrj /* Sort the (real) optabs. Better than forcing the optabs.def file to
152*38fd1498Szrj remain sorted by kind. We also scrogged any real ordering with the
153*38fd1498Szrj purging of the X patterns above. */
154*38fd1498Szrj qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
155*38fd1498Szrj
156*38fd1498Szrj fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
157*38fd1498Szrj fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
158*38fd1498Szrj
159*38fd1498Szrj /* Emit the optab enumeration for the header file. */
160*38fd1498Szrj fprintf (h_file, "enum optab_tag {\n");
161*38fd1498Szrj for (i = j = 0; i < n; ++i)
162*38fd1498Szrj {
163*38fd1498Szrj optabs[i].op = i;
164*38fd1498Szrj fprintf (h_file, " %s,\n", optabs[i].name);
165*38fd1498Szrj if (optabs[i].kind != j)
166*38fd1498Szrj last_kind[j++] = i - 1;
167*38fd1498Szrj }
168*38fd1498Szrj fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
169*38fd1498Szrj fprintf (h_file, " LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
170*38fd1498Szrj fprintf (h_file, " LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
171*38fd1498Szrj fprintf (h_file, " FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
172*38fd1498Szrj fprintf (h_file, " LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
173*38fd1498Szrj fprintf (h_file, " LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
174*38fd1498Szrj fprintf (h_file, "};\n\n");
175*38fd1498Szrj
176*38fd1498Szrj fprintf (h_file, "#define NUM_OPTABS %u\n", n);
177*38fd1498Szrj fprintf (h_file, "#define NUM_CONVLIB_OPTABS %u\n",
178*38fd1498Szrj last_kind[1] - last_kind[0]);
179*38fd1498Szrj fprintf (h_file, "#define NUM_NORMLIB_OPTABS %u\n",
180*38fd1498Szrj last_kind[3] - last_kind[2]);
181*38fd1498Szrj fprintf (h_file, "#define NUM_OPTAB_PATTERNS %u\n",
182*38fd1498Szrj (unsigned) patterns.length ());
183*38fd1498Szrj
184*38fd1498Szrj fprintf (h_file,
185*38fd1498Szrj "typedef enum optab_tag optab;\n"
186*38fd1498Szrj "typedef enum optab_tag convert_optab;\n"
187*38fd1498Szrj "typedef enum optab_tag direct_optab;\n"
188*38fd1498Szrj "\n"
189*38fd1498Szrj "struct optab_libcall_d\n"
190*38fd1498Szrj "{\n"
191*38fd1498Szrj " char libcall_suffix;\n"
192*38fd1498Szrj " const char *libcall_basename;\n"
193*38fd1498Szrj " void (*libcall_gen) (optab, const char *name,\n"
194*38fd1498Szrj " char suffix, machine_mode);\n"
195*38fd1498Szrj "};\n"
196*38fd1498Szrj "\n"
197*38fd1498Szrj "struct convert_optab_libcall_d\n"
198*38fd1498Szrj "{\n"
199*38fd1498Szrj " const char *libcall_basename;\n"
200*38fd1498Szrj " void (*libcall_gen) (convert_optab, const char *name,\n"
201*38fd1498Szrj " machine_mode, machine_mode);\n"
202*38fd1498Szrj "};\n"
203*38fd1498Szrj "\n"
204*38fd1498Szrj "/* Given an enum insn_code, access the function to construct\n"
205*38fd1498Szrj " the body of that kind of insn. */\n"
206*38fd1498Szrj "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
207*38fd1498Szrj "\n"
208*38fd1498Szrj "#ifdef NUM_RTX_CODE\n"
209*38fd1498Szrj "/* Contains the optab used for each rtx code, and vice-versa. */\n"
210*38fd1498Szrj "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
211*38fd1498Szrj "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
212*38fd1498Szrj "\n"
213*38fd1498Szrj "static inline optab\n"
214*38fd1498Szrj "code_to_optab (enum rtx_code code)\n"
215*38fd1498Szrj "{\n"
216*38fd1498Szrj " return code_to_optab_[code];\n"
217*38fd1498Szrj "}\n"
218*38fd1498Szrj "\n"
219*38fd1498Szrj "static inline enum rtx_code\n"
220*38fd1498Szrj "optab_to_code (optab op)\n"
221*38fd1498Szrj "{\n"
222*38fd1498Szrj " return optab_to_code_[op];\n"
223*38fd1498Szrj "}\n"
224*38fd1498Szrj "#endif\n"
225*38fd1498Szrj "\n"
226*38fd1498Szrj "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
227*38fd1498Szrj "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
228*38fd1498Szrj "\n"
229*38fd1498Szrj "/* Returns the active icode for the given (encoded) optab. */\n"
230*38fd1498Szrj "extern enum insn_code raw_optab_handler (unsigned);\n"
231*38fd1498Szrj "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
232*38fd1498Szrj "\n"
233*38fd1498Szrj "/* Target-dependent globals. */\n"
234*38fd1498Szrj "struct target_optabs {\n"
235*38fd1498Szrj " /* Patterns that are used by optabs that are enabled for this target. */\n"
236*38fd1498Szrj " bool pat_enable[NUM_OPTAB_PATTERNS];\n"
237*38fd1498Szrj "\n"
238*38fd1498Szrj " /* Cache if the target supports vec_gather_load for at least one vector\n"
239*38fd1498Szrj " mode. */\n"
240*38fd1498Szrj " bool supports_vec_gather_load;\n"
241*38fd1498Szrj " bool supports_vec_gather_load_cached;\n"
242*38fd1498Szrj " bool supports_vec_scatter_store;\n"
243*38fd1498Szrj " bool supports_vec_scatter_store_cached;\n"
244*38fd1498Szrj "};\n"
245*38fd1498Szrj "extern void init_all_optabs (struct target_optabs *);\n"
246*38fd1498Szrj "\n"
247*38fd1498Szrj "extern struct target_optabs default_target_optabs;\n"
248*38fd1498Szrj "extern struct target_optabs *this_fn_optabs;\n"
249*38fd1498Szrj "#if SWITCHABLE_TARGET\n"
250*38fd1498Szrj "extern struct target_optabs *this_target_optabs;\n"
251*38fd1498Szrj "#else\n"
252*38fd1498Szrj "#define this_target_optabs (&default_target_optabs)\n"
253*38fd1498Szrj "#endif\n");
254*38fd1498Szrj
255*38fd1498Szrj fprintf (s_file,
256*38fd1498Szrj "#define IN_TARGET_CODE 1\n"
257*38fd1498Szrj "#include \"config.h\"\n"
258*38fd1498Szrj "#include \"system.h\"\n"
259*38fd1498Szrj "#include \"coretypes.h\"\n"
260*38fd1498Szrj "#include \"backend.h\"\n"
261*38fd1498Szrj "#include \"predict.h\"\n"
262*38fd1498Szrj "#include \"tree.h\"\n"
263*38fd1498Szrj "#include \"rtl.h\"\n"
264*38fd1498Szrj "#include \"alias.h\"\n"
265*38fd1498Szrj "#include \"varasm.h\"\n"
266*38fd1498Szrj "#include \"stor-layout.h\"\n"
267*38fd1498Szrj "#include \"calls.h\"\n"
268*38fd1498Szrj "#include \"memmodel.h\"\n"
269*38fd1498Szrj "#include \"tm_p.h\"\n"
270*38fd1498Szrj "#include \"flags.h\"\n"
271*38fd1498Szrj "#include \"insn-config.h\"\n"
272*38fd1498Szrj "#include \"expmed.h\"\n"
273*38fd1498Szrj "#include \"dojump.h\"\n"
274*38fd1498Szrj "#include \"explow.h\"\n"
275*38fd1498Szrj "#include \"emit-rtl.h\"\n"
276*38fd1498Szrj "#include \"stmt.h\"\n"
277*38fd1498Szrj "#include \"expr.h\"\n"
278*38fd1498Szrj "#include \"insn-codes.h\"\n"
279*38fd1498Szrj "#include \"optabs.h\"\n"
280*38fd1498Szrj "\n"
281*38fd1498Szrj "struct optab_pat {\n"
282*38fd1498Szrj " unsigned scode;\n"
283*38fd1498Szrj " enum insn_code icode;\n"
284*38fd1498Szrj "};\n\n");
285*38fd1498Szrj
286*38fd1498Szrj fprintf (s_file,
287*38fd1498Szrj "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
288*38fd1498Szrj for (i = 0; patterns.iterate (i, &p); ++i)
289*38fd1498Szrj fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
290*38fd1498Szrj fprintf (s_file, "};\n\n");
291*38fd1498Szrj
292*38fd1498Szrj fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
293*38fd1498Szrj fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
294*38fd1498Szrj for (i = 0; patterns.iterate (i, &p); ++i)
295*38fd1498Szrj fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name);
296*38fd1498Szrj fprintf (s_file, "}\n\n");
297*38fd1498Szrj
298*38fd1498Szrj /* Perform a binary search on a pre-encoded optab+mode*2. */
299*38fd1498Szrj /* ??? Perhaps even better to generate a minimal perfect hash.
300*38fd1498Szrj Using gperf directly is awkward since it's so geared to working
301*38fd1498Szrj with strings. Plus we have no visibility into the ordering of
302*38fd1498Szrj the hash entries, which complicates the pat_enable array. */
303*38fd1498Szrj fprintf (s_file,
304*38fd1498Szrj "static int\n"
305*38fd1498Szrj "lookup_handler (unsigned scode)\n"
306*38fd1498Szrj "{\n"
307*38fd1498Szrj " int l = 0, h = ARRAY_SIZE (pats), m;\n"
308*38fd1498Szrj " while (h > l)\n"
309*38fd1498Szrj " {\n"
310*38fd1498Szrj " m = (h + l) / 2;\n"
311*38fd1498Szrj " if (scode == pats[m].scode)\n"
312*38fd1498Szrj " return m;\n"
313*38fd1498Szrj " else if (scode < pats[m].scode)\n"
314*38fd1498Szrj " h = m;\n"
315*38fd1498Szrj " else\n"
316*38fd1498Szrj " l = m + 1;\n"
317*38fd1498Szrj " }\n"
318*38fd1498Szrj " return -1;\n"
319*38fd1498Szrj "}\n\n");
320*38fd1498Szrj
321*38fd1498Szrj fprintf (s_file,
322*38fd1498Szrj "enum insn_code\n"
323*38fd1498Szrj "raw_optab_handler (unsigned scode)\n"
324*38fd1498Szrj "{\n"
325*38fd1498Szrj " int i = lookup_handler (scode);\n"
326*38fd1498Szrj " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
327*38fd1498Szrj " ? pats[i].icode : CODE_FOR_nothing);\n"
328*38fd1498Szrj "}\n\n");
329*38fd1498Szrj
330*38fd1498Szrj fprintf (s_file,
331*38fd1498Szrj "bool\n"
332*38fd1498Szrj "swap_optab_enable (optab op, machine_mode m, bool set)\n"
333*38fd1498Szrj "{\n"
334*38fd1498Szrj " unsigned scode = (op << 16) | m;\n"
335*38fd1498Szrj " int i = lookup_handler (scode);\n"
336*38fd1498Szrj " if (i >= 0)\n"
337*38fd1498Szrj " {\n"
338*38fd1498Szrj " bool ret = this_fn_optabs->pat_enable[i];\n"
339*38fd1498Szrj " this_fn_optabs->pat_enable[i] = set;\n"
340*38fd1498Szrj " return ret;\n"
341*38fd1498Szrj " }\n"
342*38fd1498Szrj " else\n"
343*38fd1498Szrj " {\n"
344*38fd1498Szrj " gcc_assert (!set);\n"
345*38fd1498Szrj " return false;\n"
346*38fd1498Szrj " }\n"
347*38fd1498Szrj "}\n\n");
348*38fd1498Szrj
349*38fd1498Szrj /* C++ (even G++) does not support (non-trivial) designated initializers.
350*38fd1498Szrj To work around that, generate these arrays programatically rather than
351*38fd1498Szrj by our traditional multiple inclusion of def files. */
352*38fd1498Szrj
353*38fd1498Szrj fprintf (s_file,
354*38fd1498Szrj "const struct convert_optab_libcall_d "
355*38fd1498Szrj "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
356*38fd1498Szrj for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
357*38fd1498Szrj fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall);
358*38fd1498Szrj fprintf (s_file, "};\n\n");
359*38fd1498Szrj
360*38fd1498Szrj fprintf (s_file,
361*38fd1498Szrj "const struct optab_libcall_d "
362*38fd1498Szrj "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
363*38fd1498Szrj for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
364*38fd1498Szrj fprintf (s_file, " { %s, %s, %s },\n",
365*38fd1498Szrj optabs[i].suffix, optabs[i].base, optabs[i].libcall);
366*38fd1498Szrj fprintf (s_file, "};\n\n");
367*38fd1498Szrj
368*38fd1498Szrj fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
369*38fd1498Szrj for (i = 0; i < n; ++i)
370*38fd1498Szrj fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]);
371*38fd1498Szrj fprintf (s_file, "};\n\n");
372*38fd1498Szrj
373*38fd1498Szrj qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
374*38fd1498Szrj
375*38fd1498Szrj fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
376*38fd1498Szrj for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
377*38fd1498Szrj continue;
378*38fd1498Szrj for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
379*38fd1498Szrj {
380*38fd1498Szrj if (j < n && optabs[j].rcode == i)
381*38fd1498Szrj fprintf (s_file, " %s,\n", optabs[j++].name);
382*38fd1498Szrj else
383*38fd1498Szrj fprintf (s_file, " unknown_optab,\n");
384*38fd1498Szrj }
385*38fd1498Szrj fprintf (s_file, "};\n\n");
386*38fd1498Szrj
387*38fd1498Szrj fprintf (h_file, "#endif\n");
388*38fd1498Szrj return (fclose (h_file) == 0 && fclose (s_file) == 0
389*38fd1498Szrj ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
390*38fd1498Szrj }
391