OSDN Git Service

update
[pf3gnuchains/gcc-fork.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 "hconfig.h"
26 #ifdef __STDC__
27 #include <stdarg.h>
28 #else
29 #include <varargs.h>
30 #endif
31 #include "system.h"
32 #include "rtl.h"
33 #include "obstack.h"
34
35 static struct obstack obstack;
36 struct obstack *rtl_obstack = &obstack;
37
38 #define obstack_chunk_alloc xmalloc
39 #define obstack_chunk_free free
40
41 char *xmalloc PROTO((unsigned));
42 static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
43 void fancy_abort PROTO((void));
44
45 /* Names for patterns.  Need to allow linking with print-rtl.  */
46 char **insn_name_ptr;
47
48 /* Obstacks to remember normal, and call insns.  */
49 static struct obstack call_obstack, normal_obstack;
50
51 /* Max size of names encountered.  */
52 static int max_id_len;
53
54 static int num_operands PROTO((rtx));
55 static void gen_proto PROTO((rtx));
56 static void gen_nonproto PROTO((rtx));
57 static void gen_insn PROTO((rtx));
58
59
60 /* Count the number of match_operand's found.  */
61
62 static int
63 num_operands (x)
64      rtx x;
65 {
66   int count = 0;
67   int i, j;
68   enum rtx_code code = GET_CODE (x);
69   char *format_ptr = GET_RTX_FORMAT (code);
70
71   if (code == MATCH_OPERAND)
72     return 1;
73
74   if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
75     count++;
76
77   for (i = 0; i < GET_RTX_LENGTH (code); i++)
78     {
79       switch (*format_ptr++)
80         {
81         case 'u':
82         case 'e':
83           count += num_operands (XEXP (x, i));
84           break;
85
86         case 'E':
87           if (XVEC (x, i) != NULL)
88             for (j = 0; j < XVECLEN (x, i); j++)
89               count += num_operands (XVECEXP (x, i, j));
90
91           break;
92         }
93     }
94
95   return count;
96 }
97
98 /* Print out prototype information for a function.  */
99
100 static void
101 gen_proto (insn)
102      rtx insn;
103 {
104   int num = num_operands (insn);
105   printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
106
107   if (num == 0)
108     printf ("void");
109   else
110     {
111       while (num-- > 1)
112         printf ("rtx, ");
113
114       printf ("rtx");
115     }
116
117   printf ("));\n");
118 }
119
120 /* Print out a function declaration without a prototype.  */
121
122 static void
123 gen_nonproto (insn)
124      rtx insn;
125 {
126   printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
127 }
128
129 static void
130 gen_insn (insn)
131      rtx insn;
132 {
133   char *name = XSTR (insn, 0);
134   char *p;
135   struct obstack *obstack_ptr;
136   int len;
137
138   /* Don't mention instructions whose names are the null string
139      or begin with '*'.  They are in the machine description just
140      to be recognized.  */
141   if (name[0] == 0 || name[0] == '*')
142     return;
143
144   len = strlen (name);
145
146   if (len > max_id_len)
147     max_id_len = len;
148
149   printf ("#define HAVE_%s ", name);
150   if (strlen (XSTR (insn, 2)) == 0)
151     printf ("1\n");
152   else
153     {
154       /* Write the macro definition, putting \'s at the end of each line,
155          if more than one.  */
156       printf ("(");
157       for (p = XSTR (insn, 2); *p; p++)
158         {
159           if (*p == '\n')
160             printf (" \\\n");
161           else
162             printf ("%c", *p);
163         }
164       printf (")\n");
165     }
166
167   /* Save the current insn, so that we can later put out appropriate
168      prototypes.  At present, most md files have the wrong number of
169      arguments for the call insns (call, call_value, call_pop,
170      call_value_pop) ignoring the extra arguments that are passed for
171      some machines, so by default, turn off the prototype.  */
172
173   obstack_ptr = (name[0] == 'c'
174                  && (!strcmp (name, "call")
175                      || !strcmp (name, "call_value")
176                      || !strcmp (name, "call_pop")
177                      || !strcmp (name, "call_value_pop")))
178     ? &call_obstack : &normal_obstack;
179
180   obstack_grow (obstack_ptr, &insn, sizeof (rtx));
181 }
182 \f
183 char *
184 xmalloc (size)
185      unsigned size;
186 {
187   register char *val = (char *) malloc (size);
188
189   if (val == 0)
190     fatal ("virtual memory exhausted");
191
192   return val;
193 }
194
195 char *
196 xrealloc (ptr, size)
197      char *ptr;
198      unsigned size;
199 {
200   char *result = (char *) realloc (ptr, size);
201   if (!result)
202     fatal ("virtual memory exhausted");
203   return result;
204 }
205
206 static void
207 fatal VPROTO ((char *format, ...))
208 {
209 #ifndef __STDC__
210   char *format;
211 #endif
212   va_list ap;
213
214   VA_START (ap, format);
215
216 #ifndef __STDC__
217   format = va_arg (ap, char *);
218 #endif
219
220   fprintf (stderr, "genflags: ");
221   vfprintf (stderr, format, ap);
222   va_end (ap);
223   fprintf (stderr, "\n");
224   exit (FATAL_EXIT_CODE);
225 }
226
227 /* More 'friendly' abort that prints the line and file.
228    config.h can #define abort fancy_abort if you like that sort of thing.  */
229
230 void
231 fancy_abort ()
232 {
233   fatal ("Internal gcc abort.");
234 }
235 \f
236 int
237 main (argc, argv)
238      int argc;
239      char **argv;
240 {
241   rtx desc;
242   rtx dummy;
243   rtx *call_insns;
244   rtx *normal_insns;
245   rtx *insn_ptr;
246   FILE *infile;
247   register int c;
248
249   obstack_init (rtl_obstack);
250   obstack_init (&call_obstack);
251   obstack_init (&normal_obstack);
252
253   if (argc <= 1)
254     fatal ("No input file name.");
255
256   infile = fopen (argv[1], "r");
257   if (infile == 0)
258     {
259       perror (argv[1]);
260       exit (FATAL_EXIT_CODE);
261     }
262
263   init_rtl ();
264
265   printf ("/* Generated automatically by the program `genflags'\n\
266 from the machine description file `md'.  */\n\n");
267
268   /* Read the machine description.  */
269
270   while (1)
271     {
272       c = read_skip_spaces (infile);
273       if (c == EOF)
274         break;
275       ungetc (c, infile);
276
277       desc = read_rtx (infile);
278       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
279         gen_insn (desc);
280     }
281
282   /* Print out the prototypes now.  */
283   dummy = (rtx) 0;
284   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
285   call_insns = (rtx *) obstack_finish (&call_obstack);
286
287   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
288   normal_insns = (rtx *) obstack_finish (&normal_obstack);
289
290   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
291   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
292     gen_proto (*insn_ptr);
293
294   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
295   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
296     gen_proto (*insn_ptr);
297
298   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
299   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
300     gen_nonproto (*insn_ptr);
301
302   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
303   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
304   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
305     gen_nonproto (*insn_ptr);
306
307   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
308     gen_nonproto (*insn_ptr);
309
310   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
311
312   fflush (stdout);
313   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
314   /* NOTREACHED */
315   return 0;
316 }