OSDN Git Service

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