OSDN Git Service

2012-10-08 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / genopinit.c
1 /* Generate code to initialize optabs from machine description.
2    Copyright (C) 1993-2012 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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
9 version.
10
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
14 for more details.
15
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/>.  */
19
20
21 #include "bconfig.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "errors.h"
27 #include "gensupport.h"
28
29
30 #define DEF_RTL_EXPR(V, N, X, C) #V,
31
32 static const char * const rtx_upname[] = {
33 #include "rtl.def"
34 };
35
36 #undef DEF_RTL_EXPR
37
38
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
44         code_to_optab.
45
46      CX, NX, VX: An extra pattern entry for a conversion or normal optab.
47
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).
53
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.
58
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
61    the md files.  */
62
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,
74
75 typedef enum optab_tag {
76   unknown_optab,
77 #include "optabs.def"
78   NUM_OPTABS
79 } optab;
80
81 #undef OPTAB_CL
82 #undef OPTAB_CX
83 #undef OPTAB_CD
84 #undef OPTAB_NL
85 #undef OPTAB_NC
86 #undef OPTAB_NX
87 #undef OPTAB_VL
88 #undef OPTAB_VC
89 #undef OPTAB_VX
90 #undef OPTAB_DC
91 #undef OPTAB_D
92
93 #define NS "NULL"
94 #define ZS "'\\0'"
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 },
106
107 typedef struct optab_def_d
108 {
109   const char *name;
110   const char *pattern;
111   const char *base;
112   const char *suffix;
113   const char *libcall;
114   unsigned int op;
115   enum rtx_code fcode;
116   enum rtx_code rcode;
117   unsigned int kind;
118 } optab_def;
119
120 static optab_def optabs[] = {
121   { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
122 #include "optabs.def"
123 };
124
125 #undef OPTAB_CL
126 #undef OPTAB_CX
127 #undef OPTAB_CD
128 #undef OPTAB_NL
129 #undef OPTAB_NC
130 #undef OPTAB_NX
131 #undef OPTAB_VL
132 #undef OPTAB_VC
133 #undef OPTAB_VX
134 #undef OPTAB_DC
135 #undef OPTAB_D
136
137 /* Vector in which to collect insns that match.  */
138
139 typedef struct pattern_d
140 {
141   const char *name;
142   unsigned int op;
143   unsigned int m1, m2;
144   unsigned int sort_num;
145 } pattern;
146
147 DEF_VEC_O(pattern);
148 DEF_VEC_ALLOC_O(pattern, heap);
149
150 static VEC(pattern, heap) *patterns;
151
152 static bool
153 match_pattern (pattern *p, const char *name, const char *pat)
154 {
155   bool force_float = false;
156   bool force_int = false;
157   bool force_partial_int = false;
158   bool force_fixed = false;
159
160   if (pat == NULL)
161     return false;
162   for (; ; ++pat)
163     {
164       if (*pat != '$')
165         {
166           if (*pat != *name++)
167             return false;
168           if (*pat == '\0')
169             return true;
170           continue;
171         }
172       switch (*++pat)
173         {
174         case 'I':
175           force_int = 1;
176           break;
177         case 'P':
178           force_partial_int = 1;
179           break;
180         case 'F':
181           force_float = 1;
182           break;
183         case 'Q':
184           force_fixed = 1;
185           break;
186
187         case 'a':
188         case 'b':
189           {
190             int i;
191
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--)
197               {
198                 const char *p, *q;
199                 for (p = GET_MODE_NAME(i), q = name; *p; p++, q++)
200                   if (TOLOWER (*p) != *q)
201                     break;
202                 if (*p == 0
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)
209                     && (! force_float
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)
214                     && (! force_fixed
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))
223                   break;
224               }
225
226             if (i < 0)
227               return false;
228             name += strlen (GET_MODE_NAME (i));
229             if (*pat == 'a')
230               p->m1 = i;
231             else
232               p->m2 = i;
233
234             force_int = false;
235             force_partial_int = false;
236             force_float = false;
237             force_fixed = false;
238           }
239           break;
240
241         default:
242           gcc_unreachable ();
243         }
244     }
245 }
246
247 static void
248 gen_insn (rtx insn)
249 {
250   const char *name = XSTR (insn, 0);
251   pattern p;
252   unsigned pindex;
253
254   /* Don't mention "unnamed" instructions.  */
255   if (*name == 0 || *name == '*')
256     return;
257   p.name = name;
258
259   /* See if NAME matches one of the patterns we have for the optabs
260      we know about.  */
261   for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
262     {
263       p.m1 = p.m2 = 0;
264       if (match_pattern (&p, name, optabs[pindex].pattern))
265         {
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);
269           return;
270         }
271     }
272 }
273
274 static int
275 pattern_cmp (const void *va, const void *vb)
276 {
277   const pattern *a = (const pattern *)va;
278   const pattern *b = (const pattern *)vb;
279   return a->sort_num - b->sort_num;
280 }
281
282 static int
283 optab_kind_cmp (const void *va, const void *vb)
284 {
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;
288   if (diff == 0)
289     diff = a->op - b->op;
290   return diff;
291 }
292
293 static int
294 optab_rcode_cmp (const void *va, const void *vb)
295 {
296   const optab_def *a = (const optab_def *)va;
297   const optab_def *b = (const optab_def *)vb;
298   return a->rcode - b->rcode;
299 }
300
301 static const char *header_file_name = "init-opinit.h";
302 static const char *source_file_name = "init-opinit.c";
303
304 static bool
305 handle_arg (const char *arg)
306 {
307   switch (arg[1])
308     {
309     case 'h':
310       header_file_name = &arg[2];
311       return true;
312     case 'c':
313       source_file_name = &arg[2];
314       return true;
315     default:
316       return false;
317     }
318 }
319
320 static FILE *
321 open_outfile (const char *file_name)
322 {
323   FILE *f = fopen (file_name, "w");
324   if (!f)
325     fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
326   fprintf (f,
327            "/* Generated automatically by the program `genopinit'\n"
328            "   from the machine description file `md'.  */\n\n");
329   return f;
330 }
331
332 int
333 main (int argc, char **argv)
334 {
335   FILE *h_file, *s_file;
336   unsigned int i, j, n, last_kind[5];
337   pattern *p;
338
339   progname = "genopinit";
340
341   if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
342     fatal ("genopinit range assumptions invalid");
343
344   if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
345     return (FATAL_EXIT_CODE);
346
347   h_file = open_outfile (header_file_name);
348   s_file = open_outfile (source_file_name);
349
350   /* Read the machine description.  */
351   while (1)
352     {
353       int line_no, insn_code_number = 0;
354       rtx desc = read_md_rtx (&line_no, &insn_code_number);
355       if (desc == NULL)
356         break;
357       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
358         gen_insn (desc);
359     }
360
361   /* Sort the collected patterns.  */
362   qsort (VEC_address (pattern, patterns), VEC_length (pattern, patterns),
363          sizeof (pattern), pattern_cmp);
364
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);
368   for (i = 0; i < n; )
369     if (optabs[i].base == NULL)
370       optabs[i] = optabs[--n];
371     else
372       ++i;
373
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);
378
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)
382     {
383       optabs[i].op = i;
384       fprintf (h_file, "  %s,\n", optabs[i].name);
385       if (optabs[i].kind != j)
386         last_kind[j++] = i - 1;
387     }
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");
395
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));
403
404   fprintf (s_file,
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"
415            "\n"
416            "struct optab_pat {\n"
417            "  unsigned scode;\n"
418            "  enum insn_code icode;\n"
419            "};\n\n");
420
421   fprintf (s_file,
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");
426
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");
432
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.  */
438   fprintf (s_file,
439            "static int\n"
440            "lookup_handler (unsigned scode)\n"
441            "{\n"
442            "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
443            "  while (h > l)\n"
444            "    {\n"
445            "      m = (h + l) / 2;\n"
446            "      if (scode == pats[m].scode)\n"
447            "        return m;\n"
448            "      else if (scode < pats[m].scode)\n"
449            "        h = m;\n"
450            "      else\n"
451            "        l = m + 1;\n"
452            "    }\n"
453            "  return -1;\n"
454            "}\n\n");
455
456   fprintf (s_file,
457            "enum insn_code\n"
458            "raw_optab_handler (unsigned scode)\n"
459            "{\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"
463            "}\n\n");
464
465   fprintf (s_file,
466            "bool\n"
467            "swap_optab_enable (optab op, enum machine_mode m, bool set)\n"
468            "{\n"
469            "  unsigned scode = (op << 16) | m;\n"
470            "  int i = lookup_handler (scode);\n"
471            "  if (i >= 0)\n"
472            "    {\n"
473            "      bool ret = this_target_optabs->pat_enable[i];\n"
474            "      this_target_optabs->pat_enable[i] = set;\n"
475            "      return ret;\n"
476            "    }\n"
477            "  else\n"
478            "    {\n"
479            "      gcc_assert (!set);\n"
480            "      return false;\n"
481            "    }\n"
482            "}\n\n");
483
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.  */
487
488   fprintf (s_file,
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");
494
495   fprintf (s_file,
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");
502
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");
507
508   qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
509
510   fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
511   for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
512     continue;
513   for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
514     {
515       if (j < n && optabs[j].rcode == i)
516         fprintf (s_file, "  %s,\n", optabs[j++].name);
517       else
518         fprintf (s_file, "  unknown_optab,\n");
519     }
520   fprintf (s_file, "};\n\n");
521
522   return (fclose (h_file) == 0 && fclose (s_file) == 0
523           ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
524 }