OSDN Git Service

Merge in gcc2-ss-010999
[pf3gnuchains/gcc-fork.git] / gcc / genflags.c
1 /* Generate from machine description:
2    - some flags HAVE_... saying which simple standard instructions are
3    available for this machine.
4    Copyright (C) 1987, 1991, 1995, 1998, 1999 Free Software Foundation, Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23
24 #include "hconfig.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "obstack.h"
28 #include "errors.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 /* Names for patterns.  Need to allow linking with print-rtl.  */
37 char **insn_name_ptr;
38
39 /* Obstacks to remember normal, and call insns.  */
40 static struct obstack call_obstack, normal_obstack;
41
42 /* Max size of names encountered.  */
43 static int max_id_len;
44
45 static int num_operands PROTO((rtx));
46 static void gen_proto PROTO((rtx));
47 static void gen_nonproto PROTO((rtx));
48 static void gen_insn PROTO((rtx));
49
50
51 /* Count the number of match_operand's found.  */
52
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   const 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
91 static void
92 gen_proto (insn)
93      rtx insn;
94 {
95   int num = num_operands (insn);
96   printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
97
98   if (num == 0)
99     printf ("void");
100   else
101     {
102       while (num-- > 1)
103         printf ("rtx, ");
104
105       printf ("rtx");
106     }
107
108   printf ("));\n");
109 }
110
111 /* Print out a function declaration without a prototype.  */
112
113 static void
114 gen_nonproto (insn)
115      rtx insn;
116 {
117   printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
118 }
119
120 static void
121 gen_insn (insn)
122      rtx insn;
123 {
124   char *name = XSTR (insn, 0);
125   char *p;
126   struct obstack *obstack_ptr;
127   int len;
128
129   /* Don't mention instructions whose names are the null string
130      or begin with '*'.  They are in the machine description just
131      to be recognized.  */
132   if (name[0] == 0 || name[0] == '*')
133     return;
134
135   len = strlen (name);
136
137   if (len > max_id_len)
138     max_id_len = len;
139
140   printf ("#define HAVE_%s ", name);
141   if (strlen (XSTR (insn, 2)) == 0)
142     printf ("1\n");
143   else
144     {
145       /* Write the macro definition, putting \'s at the end of each line,
146          if more than one.  */
147       printf ("(");
148       for (p = XSTR (insn, 2); *p; p++)
149         {
150           if (*p == '\n')
151             printf (" \\\n");
152           else
153             printf ("%c", *p);
154         }
155       printf (")\n");
156     }
157
158   /* Save the current insn, so that we can later put out appropriate
159      prototypes.  At present, most md files have the wrong number of
160      arguments for the call insns (call, call_value, call_pop,
161      call_value_pop) ignoring the extra arguments that are passed for
162      some machines, so by default, turn off the prototype.  */
163
164   obstack_ptr = (name[0] == 'c'
165                  && (!strcmp (name, "call")
166                      || !strcmp (name, "call_value")
167                      || !strcmp (name, "call_pop")
168                      || !strcmp (name, "call_value_pop")))
169     ? &call_obstack : &normal_obstack;
170
171   obstack_grow (obstack_ptr, &insn, sizeof (rtx));
172 }
173 \f
174 PTR
175 xmalloc (size)
176   size_t size;
177 {
178   register PTR val = (PTR) malloc (size);
179
180   if (val == 0)
181     fatal ("virtual memory exhausted");
182
183   return val;
184 }
185
186 PTR
187 xrealloc (old, size)
188   PTR old;
189   size_t size;
190 {
191   register PTR ptr;
192   if (old)
193     ptr = (PTR) realloc (old, size);
194   else
195     ptr = (PTR) malloc (size);
196   if (!ptr)
197     fatal ("virtual memory exhausted");
198   return ptr;
199 }
200
201 int
202 main (argc, argv)
203      int argc;
204      char **argv;
205 {
206   rtx desc;
207   rtx dummy;
208   rtx *call_insns;
209   rtx *normal_insns;
210   rtx *insn_ptr;
211   FILE *infile;
212   register int c;
213
214   progname = "genflags";
215   obstack_init (rtl_obstack);
216   obstack_init (&call_obstack);
217   obstack_init (&normal_obstack);
218
219   if (argc <= 1)
220     fatal ("No input file name.");
221
222   infile = fopen (argv[1], "r");
223   if (infile == 0)
224     {
225       perror (argv[1]);
226       exit (FATAL_EXIT_CODE);
227     }
228
229   printf ("/* Generated automatically by the program `genflags'\n\
230 from the machine description file `md'.  */\n\n");
231
232   /* Read the machine description.  */
233
234   while (1)
235     {
236       c = read_skip_spaces (infile);
237       if (c == EOF)
238         break;
239       ungetc (c, infile);
240
241       desc = read_rtx (infile);
242       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
243         gen_insn (desc);
244     }
245
246   /* Print out the prototypes now.  */
247   dummy = (rtx) 0;
248   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
249   call_insns = (rtx *) obstack_finish (&call_obstack);
250
251   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
252   normal_insns = (rtx *) obstack_finish (&normal_obstack);
253
254   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
255   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
256     gen_proto (*insn_ptr);
257
258   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
259   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
260     gen_proto (*insn_ptr);
261
262   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
263   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
264     gen_nonproto (*insn_ptr);
265
266   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
267   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
268   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
269     gen_nonproto (*insn_ptr);
270
271   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
272     gen_nonproto (*insn_ptr);
273
274   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
275
276   fflush (stdout);
277   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
278   /* NOTREACHED */
279   return 0;
280 }