Comment PFIL_HOOKS since it should not be needed in GENERIC.
[dragonfly.git] / contrib / 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, 1999 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 void fatal PVPROTO ((const char *, ...))
37   ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
38 void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
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 PTR
179 xmalloc (size)
180   size_t size;
181 {
182   register PTR val = (PTR) malloc (size);
183
184   if (val == 0)
185     fatal ("virtual memory exhausted");
186
187   return val;
188 }
189
190 PTR
191 xrealloc (old, size)
192   PTR old;
193   size_t size;
194 {
195   register PTR ptr;
196   if (old)
197     ptr = (PTR) realloc (old, size);
198   else
199     ptr = (PTR) malloc (size);
200   if (!ptr)
201     fatal ("virtual memory exhausted");
202   return ptr;
203 }
204
205 void
206 fatal VPROTO ((const char *format, ...))
207 {
208 #ifndef ANSI_PROTOTYPES
209   const char *format;
210 #endif
211   va_list ap;
212
213   VA_START (ap, format);
214
215 #ifndef ANSI_PROTOTYPES
216   format = va_arg (ap, const char *);
217 #endif
218
219   fprintf (stderr, "genflags: ");
220   vfprintf (stderr, format, ap);
221   va_end (ap);
222   fprintf (stderr, "\n");
223   exit (FATAL_EXIT_CODE);
224 }
225
226 /* More 'friendly' abort that prints the line and file.
227    config.h can #define abort fancy_abort if you like that sort of thing.  */
228
229 void
230 fancy_abort ()
231 {
232   fatal ("Internal gcc abort.");
233 }
234 \f
235 int
236 main (argc, argv)
237      int argc;
238      char **argv;
239 {
240   rtx desc;
241   rtx dummy;
242   rtx *call_insns;
243   rtx *normal_insns;
244   rtx *insn_ptr;
245   FILE *infile;
246   register int c;
247
248   obstack_init (rtl_obstack);
249   obstack_init (&call_obstack);
250   obstack_init (&normal_obstack);
251
252   if (argc <= 1)
253     fatal ("No input file name.");
254
255   infile = fopen (argv[1], "r");
256   if (infile == 0)
257     {
258       perror (argv[1]);
259       exit (FATAL_EXIT_CODE);
260     }
261
262   init_rtl ();
263
264   printf ("/* Generated automatically by the program `genflags'\n\
265 from the machine description file `md'.  */\n\n");
266
267   /* Read the machine description.  */
268
269   while (1)
270     {
271       c = read_skip_spaces (infile);
272       if (c == EOF)
273         break;
274       ungetc (c, infile);
275
276       desc = read_rtx (infile);
277       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
278         gen_insn (desc);
279     }
280
281   /* Print out the prototypes now.  */
282   dummy = (rtx) 0;
283   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
284   call_insns = (rtx *) obstack_finish (&call_obstack);
285
286   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
287   normal_insns = (rtx *) obstack_finish (&normal_obstack);
288
289   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
290   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
291     gen_proto (*insn_ptr);
292
293   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
294   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
295     gen_proto (*insn_ptr);
296
297   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
298   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
299     gen_nonproto (*insn_ptr);
300
301   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
302   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
303   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
304     gen_nonproto (*insn_ptr);
305
306   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
307     gen_nonproto (*insn_ptr);
308
309   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
310
311   fflush (stdout);
312   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
313   /* NOTREACHED */
314   return 0;
315 }