OSDN Git Service

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