OSDN Git Service

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