OSDN Git Service

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