OSDN Git Service

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