85aa7b07ca88f8a5f042e23c95acec9b2f457662
[platform/upstream/gcc.git] / gcc / genflags.c
1 /* Generate from machine description:
2
3    - some flags HAVE_... saying which simple standard instructions are
4    available for this machine.
5    Copyright (C) 1987, 1991, 1995, 1998 Free Software Foundation, Inc.
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24
25 #include <stdio.h>
26 #include "hconfig.h"
27 #include "rtl.h"
28 #include "obstack.h"
29
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33
34 static struct obstack obstack;
35 struct obstack *rtl_obstack = &obstack;
36
37 #define obstack_chunk_alloc xmalloc
38 #define obstack_chunk_free free
39
40 #ifdef NEED_DECLARATION_FREE
41 extern void free ();
42 #endif
43 extern rtx read_rtx ();
44
45 char *xmalloc ();
46 static void fatal ();
47 void fancy_abort ();
48
49 /* Names for patterns.  Need to allow linking with print-rtl.  */
50 char **insn_name_ptr;
51
52 /* Obstacks to remember normal, and call insns.  */
53 static struct obstack call_obstack, normal_obstack;
54
55 /* Max size of names encountered.  */
56 static int max_id_len;
57
58 /* Count the number of match_operand's found.  */
59
60 static int
61 num_operands (x)
62      rtx x;
63 {
64   int count = 0;
65   int i, j;
66   enum rtx_code code = GET_CODE (x);
67   char *format_ptr = GET_RTX_FORMAT (code);
68
69   if (code == MATCH_OPERAND)
70     return 1;
71
72   if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
73     count++;
74
75   for (i = 0; i < GET_RTX_LENGTH (code); i++)
76     {
77       switch (*format_ptr++)
78         {
79         case 'u':
80         case 'e':
81           count += num_operands (XEXP (x, i));
82           break;
83
84         case 'E':
85           if (XVEC (x, i) != NULL)
86             for (j = 0; j < XVECLEN (x, i); j++)
87               count += num_operands (XVECEXP (x, i, j));
88
89           break;
90         }
91     }
92
93   return count;
94 }
95
96 /* Print out prototype information for a function.  */
97
98 static void
99 gen_proto (insn)
100      rtx insn;
101 {
102   int num = num_operands (insn);
103   printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
104
105   if (num == 0)
106     printf ("void");
107   else
108     {
109       while (num-- > 1)
110         printf ("rtx, ");
111
112       printf ("rtx");
113     }
114
115   printf ("));\n");
116 }
117
118 /* Print out a function declaration without a prototype.  */
119
120 static void
121 gen_nonproto (insn)
122      rtx insn;
123 {
124   printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
125 }
126
127 static void
128 gen_insn (insn)
129      rtx insn;
130 {
131   char *name = XSTR (insn, 0);
132   char *p;
133   struct obstack *obstack_ptr;
134   int len;
135
136   /* Don't mention instructions whose names are the null string
137      or begin with '*'.  They are in the machine description just
138      to be recognized.  */
139   if (name[0] == 0 || name[0] == '*')
140     return;
141
142   len = strlen (name);
143
144   if (len > max_id_len)
145     max_id_len = len;
146
147   printf ("#define HAVE_%s ", name);
148   if (strlen (XSTR (insn, 2)) == 0)
149     printf ("1\n");
150   else
151     {
152       /* Write the macro definition, putting \'s at the end of each line,
153          if more than one.  */
154       printf ("(");
155       for (p = XSTR (insn, 2); *p; p++)
156         {
157           if (*p == '\n')
158             printf (" \\\n");
159           else
160             printf ("%c", *p);
161         }
162       printf (")\n");
163     }
164
165   /* Save the current insn, so that we can later put out appropriate
166      prototypes.  At present, most md files have the wrong number of
167      arguments for the call insns (call, call_value, call_pop,
168      call_value_pop) ignoring the extra arguments that are passed for
169      some machines, so by default, turn off the prototype.  */
170
171   obstack_ptr = (name[0] == 'c'
172                  && (!strcmp (name, "call")
173                      || !strcmp (name, "call_value")
174                      || !strcmp (name, "call_pop")
175                      || !strcmp (name, "call_value_pop")))
176     ? &call_obstack : &normal_obstack;
177
178   obstack_grow (obstack_ptr, &insn, sizeof (rtx));
179 }
180 \f
181 char *
182 xmalloc (size)
183      unsigned size;
184 {
185   register char *val = (char *) malloc (size);
186
187   if (val == 0)
188     fatal ("virtual memory exhausted");
189
190   return val;
191 }
192
193 char *
194 xrealloc (ptr, size)
195      char *ptr;
196      unsigned size;
197 {
198   char *result = (char *) realloc (ptr, size);
199   if (!result)
200     fatal ("virtual memory exhausted");
201   return result;
202 }
203
204 static void
205 fatal (s, a1, a2)
206      char *s;
207 {
208   fprintf (stderr, "genflags: ");
209   fprintf (stderr, s, a1, a2);
210   fprintf (stderr, "\n");
211   exit (FATAL_EXIT_CODE);
212 }
213
214 /* More 'friendly' abort that prints the line and file.
215    config.h can #define abort fancy_abort if you like that sort of thing.  */
216
217 void
218 fancy_abort ()
219 {
220   fatal ("Internal gcc abort.");
221 }
222 \f
223 int
224 main (argc, argv)
225      int argc;
226      char **argv;
227 {
228   rtx desc;
229   rtx dummy;
230   rtx *call_insns;
231   rtx *normal_insns;
232   rtx *insn_ptr;
233   FILE *infile;
234   register int c;
235
236   obstack_init (rtl_obstack);
237   obstack_init (&call_obstack);
238   obstack_init (&normal_obstack);
239
240   if (argc <= 1)
241     fatal ("No input file name.");
242
243   infile = fopen (argv[1], "r");
244   if (infile == 0)
245     {
246       perror (argv[1]);
247       exit (FATAL_EXIT_CODE);
248     }
249
250   init_rtl ();
251
252   printf ("/* Generated automatically by the program `genflags'\n\
253 from the machine description file `md'.  */\n\n");
254
255   /* Read the machine description.  */
256
257   while (1)
258     {
259       c = read_skip_spaces (infile);
260       if (c == EOF)
261         break;
262       ungetc (c, infile);
263
264       desc = read_rtx (infile);
265       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
266         gen_insn (desc);
267     }
268
269   /* Print out the prototypes now.  */
270   dummy = (rtx) 0;
271   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
272   call_insns = (rtx *) obstack_finish (&call_obstack);
273
274   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
275   normal_insns = (rtx *) obstack_finish (&normal_obstack);
276
277   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
278   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
279     gen_proto (*insn_ptr);
280
281   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
282   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
283     gen_proto (*insn_ptr);
284
285   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
286   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
287     gen_nonproto (*insn_ptr);
288
289   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
290   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
291   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
292     gen_nonproto (*insn_ptr);
293
294   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
295     gen_nonproto (*insn_ptr);
296
297   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
298
299   fflush (stdout);
300   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
301   /* NOTREACHED */
302   return 0;
303 }