OSDN Git Service

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