OSDN Git Service

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