OSDN Git Service

* genattrtab.c: Make generated file use system.h, instead of
[pf3gnuchains/gcc-fork.git] / gcc / genopinit.c
1 /* Generate code to initialize optabs from machine description.
2    Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 #include "hconfig.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "obstack.h"
26
27 static struct obstack obstack;
28 struct obstack *rtl_obstack = &obstack;
29
30 #define obstack_chunk_alloc xmalloc
31 #define obstack_chunk_free free
32
33 char *xmalloc PROTO((unsigned));
34 static void fatal ();
35 void fancy_abort PROTO((void));
36
37 /* Many parts of GCC use arrays that are indexed by machine mode and
38    contain the insn codes for pattern in the MD file that perform a given
39    operation on operands of that mode.
40
41    These patterns are present in the MD file with names that contain
42    the mode(s) used and the name of the operation.  This program
43    writes a function `init_all_optabs' that initializes the optabs with
44    all the insn codes of the relevant patterns present in the MD file.
45
46    This array contains a list of optabs that need to be initialized.  Within
47    each string, the name of the pattern to be matched against is delimited
48    with %( and %).  In the string, %a and %b are used to match a short mode
49    name (the part of the mode name not including `mode' and converted to
50    lower-case).  When writing out the initializer, the entire string is
51    used.  %A and %B are replaced with the full name of the mode; %a and %b
52    are replaced with the short form of the name, as above.
53
54    If %N is present in the pattern, it means the two modes must be consecutive
55    widths in the same mode class (e.g, QImode and HImode).  %I means that
56    only integer modes should be considered for the next mode, and %F means
57    that only float modes should be considered.
58
59    For some optabs, we store the operation by RTL codes.  These are only
60    used for comparisons.  In that case, %c and %C are the lower-case and
61    upper-case forms of the comparison, respectively.  */
62
63 /* The reason we use \% is to avoid sequences of the form %-capletter-%
64    which SCCS treats as magic.  This gets warnings which you should ignore.  */
65
66 char *optabs[] =
67 { "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)",
68   "extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)",
69   "fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)",
70   "fixtab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns%F\%a%b2%)",
71   "fixtrunctab[(int) %A][(int) %B][0] = CODE_FOR_%(fix_trunc%F\%a%I\%b2%)",
72   "fixtrunctab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns_trunc%F\%a%I\%b2%)",
73   "floattab[(int) %B][(int) %A][0] = CODE_FOR_%(float%I\%a%F\%b2%)",
74   "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)",
75   "add_optab->handlers[(int) %A].insn_code = CODE_FOR_%(add%a3%)",
76   "sub_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sub%a3%)",
77   "smul_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mul%a3%)",
78   "umul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umul%a3_highpart%)",
79   "smul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smul%a3_highpart%)",
80   "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N",
81   "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N",
82   "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)",
83   "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)",
84   "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)",
85   "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)",
86   "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)",
87   "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)",
88   "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)",
89   "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)",
90   "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)",
91   "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)",
92   "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)",
93   "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)",
94   "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)",
95   "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)",
96   "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)",
97   "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)",
98   "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)",
99   "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)",
100   "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)",
101   "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)",
102   "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)",
103   "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)",
104   "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)",
105   "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)",
106   "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)",
107   "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)",
108   "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)",
109   "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
110   "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)",
111   "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)",
112   "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)",
113   "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)",
114   "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)",
115   "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)",
116   "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
117   "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
118   "movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)",
119   "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
120   "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
121   "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)",
122   "clrstr_optab[(int) %A] = CODE_FOR_%(clrstr%a%)" };
123
124 /* Allow linking with print-rtl.c.  */
125 char **insn_name_ptr;
126
127 static void
128 gen_insn (insn)
129      rtx insn;
130 {
131   char *name = XSTR (insn, 0);
132   int m1, m2, op;
133   size_t pindex;
134   int i;
135   char *np, *pp, *p, *q;
136
137   /* Don't mention instructions whose names are the null string.
138      They are in the machine description just to be recognized.  */
139   if (*name == 0)
140     return;
141
142   /* See if NAME matches one of the patterns we have for the optabs we know
143      about.  */
144
145   for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
146     {
147       int force_float = 0, force_int = 0;
148       int force_consec = 0;
149       int matches = 1;
150
151       for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
152         ;
153
154       for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
155            pp++)
156         {
157           if (*pp != '%')
158             {
159               if (*pp != *np++)
160                 break;
161             }
162           else
163             switch (*++pp)
164               {
165               case 'N':
166                 force_consec = 1;
167                 break;
168               case 'I':
169                 force_int = 1;
170                 break;
171               case 'F':
172                 force_float = 1;
173                 break;
174               case 'c':
175                 for (op = 0; op < NUM_RTX_CODE; op++)
176                   {
177                     for (p = rtx_name[op], q = np; *p; p++, q++)
178                       if (*p != *q)
179                         break;
180
181                     /* We have to be concerned about matching "gt" and
182                        missing "gtu", e.g., so verify we have reached the
183                        end of thing we are to match.  */
184                     if (*p == 0 && *q == 0 && rtx_class[op] == '<')
185                       break;
186                   }
187
188                 if (op == NUM_RTX_CODE)
189                   matches = 0;
190                 else
191                   np += strlen (rtx_name[op]);
192                 break;
193               case 'a':
194               case 'b':
195                 /* This loop will stop at the first prefix match, so
196                    look through the modes in reverse order, in case
197                    EXTRA_CC_MODES was used and CC is a prefix of the
198                    CC modes (as it should be).  */
199                 for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
200                   {
201                     for (p = mode_name[i], q = np; *p; p++, q++)
202                       if (tolower (*p) != *q)
203                         break;
204
205                     if (*p == 0
206                         && (! force_int || mode_class[i] == MODE_INT)
207                         && (! force_float || mode_class[i] == MODE_FLOAT))
208                       break;
209                   }
210
211                 if (i < 0)
212                   matches = 0;
213                 else if (*pp == 'a')
214                   m1 = i, np += strlen (mode_name[i]);
215                 else
216                   m2 = i, np += strlen (mode_name[i]);
217
218                 force_int = force_float = 0;
219                 break;
220
221               default:
222                 abort ();
223               }
224         }
225
226       if (matches && pp[0] == '%' && pp[1] == ')'
227           && *np == 0
228           && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
229         break;
230     }
231
232   if (pindex == sizeof optabs / sizeof optabs[0])
233     return;
234
235   /* We found a match.  If this pattern is only conditionally present,
236      write out the "if" and two extra blanks.  */
237
238   if (*XSTR (insn, 2) != 0)
239     printf ("  if (HAVE_%s)\n  ", name);
240
241   printf ("  ");
242
243   /* Now write out the initialization, making all required substitutions.  */
244   for (pp = optabs[pindex]; *pp; pp++)
245     {
246       if (*pp != '%')
247         printf ("%c", *pp);
248       else
249         switch (*++pp)
250           {
251           case '(':  case ')':
252           case 'I':  case 'F':  case 'N':
253             break;
254           case 'a':
255             for (np = mode_name[m1]; *np; np++)
256               printf ("%c", tolower (*np));
257             break;
258           case 'b':
259             for (np = mode_name[m2]; *np; np++)
260               printf ("%c", tolower (*np));
261             break;
262           case 'A':
263             printf ("%smode", mode_name[m1]);
264             break;
265           case 'B':
266             printf ("%smode", mode_name[m2]);
267             break;
268           case 'c':
269             printf ("%s", rtx_name[op]);
270             break;
271           case 'C':
272             for (np = rtx_name[op]; *np; np++)
273               printf ("%c", toupper (*np));
274             break;
275           }
276     }
277
278   printf (";\n");
279 }
280 \f
281 char *
282 xmalloc (size)
283      unsigned size;
284 {
285   register char *val = (char *) malloc (size);
286
287   if (val == 0)
288     fatal ("virtual memory exhausted");
289
290   return val;
291 }
292
293 char *
294 xrealloc (ptr, size)
295      char *ptr;
296      unsigned size;
297 {
298   char *result = (char *) realloc (ptr, size);
299   if (!result)
300     fatal ("virtual memory exhausted");
301   return result;
302 }
303
304 static void
305 fatal (s, a1, a2)
306      char *s;
307 {
308   fprintf (stderr, "genopinit: ");
309   fprintf (stderr, s, a1, a2);
310   fprintf (stderr, "\n");
311   exit (FATAL_EXIT_CODE);
312 }
313
314 /* More 'friendly' abort that prints the line and file.
315    config.h can #define abort fancy_abort if you like that sort of thing.  */
316
317 void
318 fancy_abort ()
319 {
320   fatal ("Internal gcc abort.");
321 }
322 \f
323 int
324 main (argc, argv)
325      int argc;
326      char **argv;
327 {
328   rtx desc;
329   FILE *infile;
330   register int c;
331
332   obstack_init (rtl_obstack);
333
334   if (argc <= 1)
335     fatal ("No input file name.");
336
337   infile = fopen (argv[1], "r");
338   if (infile == 0)
339     {
340       perror (argv[1]);
341       exit (FATAL_EXIT_CODE);
342     }
343
344   init_rtl ();
345
346   printf ("/* Generated automatically by the program `genopinit'\n\
347 from the machine description file `md'.  */\n\n");
348
349   printf ("#include \"config.h\"\n");
350   printf ("#include \"system.h\"\n");
351   printf ("#include \"rtl.h\"\n");
352   printf ("#include \"flags.h\"\n");
353   printf ("#include \"insn-flags.h\"\n");
354   printf ("#include \"insn-codes.h\"\n");
355   printf ("#include \"insn-config.h\"\n");
356   printf ("#include \"recog.h\"\n");
357   printf ("#include \"expr.h\"\n");
358   printf ("#include \"reload.h\"\n\n");
359
360   printf ("void\ninit_all_optabs ()\n{\n");
361
362   /* Read the machine description.  */
363
364   while (1)
365     {
366       c = read_skip_spaces (infile);
367       if (c == EOF)
368         break;
369       ungetc (c, infile);
370
371       desc = read_rtx (infile);
372       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
373         gen_insn (desc);
374     }
375
376   printf ("}\n");
377
378   fflush (stdout);
379   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
380   /* NOTREACHED */
381   return 0;
382 }