Initial revision
[official-gcc.git] / gcc / genflags.c
blobcd784e269af7627f53389b19efb775b976aa798e
1 /* Generate from machine description:
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.
7 This file is part of GNU CC.
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.
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.
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. */
24 #include <stdio.h>
25 #include "hconfig.h"
26 #include "rtl.h"
27 #include "obstack.h"
29 static struct obstack obstack;
30 struct obstack *rtl_obstack = &obstack;
32 #define obstack_chunk_alloc xmalloc
33 #define obstack_chunk_free free
35 extern void free ();
36 extern rtx read_rtx ();
38 char *xmalloc ();
39 static void fatal ();
40 void fancy_abort ();
42 /* Names for patterns. Need to allow linking with print-rtl. */
43 char **insn_name_ptr;
45 /* Obstacks to remember normal, and call insns. */
46 static struct obstack call_obstack, normal_obstack;
48 /* Max size of names encountered. */
49 static int max_id_len;
51 /* Count the number of match_operand's found. */
52 static int
53 num_operands (x)
54 rtx x;
56 int count = 0;
57 int i, j;
58 enum rtx_code code = GET_CODE (x);
59 char *format_ptr = GET_RTX_FORMAT (code);
61 if (code == MATCH_OPERAND)
62 return 1;
64 if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
65 count++;
67 for (i = 0; i < GET_RTX_LENGTH (code); i++)
69 switch (*format_ptr++)
71 case 'u':
72 case 'e':
73 count += num_operands (XEXP (x, i));
74 break;
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));
81 break;
85 return count;
88 /* Print out prototype information for a function. */
89 static void
90 gen_proto (insn)
91 rtx insn;
93 int num = num_operands (insn);
94 printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
96 if (num == 0)
97 printf ("void");
98 else
100 while (num-- > 1)
101 printf ("rtx, ");
103 printf ("rtx");
106 printf ("));\n");
109 /* Print out a function declaration without a prototype. */
110 static void
111 gen_nonproto (insn)
112 rtx insn;
114 printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
117 static void
118 gen_insn (insn)
119 rtx insn;
121 char *name = XSTR (insn, 0);
122 char *p;
123 struct obstack *obstack_ptr;
124 int len;
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;
132 len = strlen (name);
134 if (len > max_id_len)
135 max_id_len = len;
137 printf ("#define HAVE_%s ", name);
138 if (strlen (XSTR (insn, 2)) == 0)
139 printf ("1\n");
140 else
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++)
147 if (*p == '\n')
148 printf (" \\\n");
149 else
150 printf ("%c", *p);
152 printf (")\n");
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. */
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;
168 obstack_grow (obstack_ptr, &insn, sizeof (rtx));
171 char *
172 xmalloc (size)
173 unsigned size;
175 register char *val = (char *) malloc (size);
177 if (val == 0)
178 fatal ("virtual memory exhausted");
180 return val;
183 char *
184 xrealloc (ptr, size)
185 char *ptr;
186 unsigned size;
188 char *result = (char *) realloc (ptr, size);
189 if (!result)
190 fatal ("virtual memory exhausted");
191 return result;
194 static void
195 fatal (s, a1, a2)
196 char *s;
198 fprintf (stderr, "genflags: ");
199 fprintf (stderr, s, a1, a2);
200 fprintf (stderr, "\n");
201 exit (FATAL_EXIT_CODE);
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. */
207 void
208 fancy_abort ()
210 fatal ("Internal gcc abort.");
214 main (argc, argv)
215 int argc;
216 char **argv;
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;
226 obstack_init (rtl_obstack);
227 obstack_init (&call_obstack);
228 obstack_init (&normal_obstack);
230 if (argc <= 1)
231 fatal ("No input file name.");
233 infile = fopen (argv[1], "r");
234 if (infile == 0)
236 perror (argv[1]);
237 exit (FATAL_EXIT_CODE);
240 init_rtl ();
242 printf ("/* Generated automatically by the program `genflags'\n\
243 from the machine description file `md'. */\n\n");
245 /* Read the machine description. */
247 while (1)
249 c = read_skip_spaces (infile);
250 if (c == EOF)
251 break;
252 ungetc (c, infile);
254 desc = read_rtx (infile);
255 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
256 gen_insn (desc);
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);
264 obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
265 normal_insns = (rtx *) obstack_finish (&normal_obstack);
267 printf ("\n#ifndef NO_MD_PROTOTYPES\n");
268 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
269 gen_proto (*insn_ptr);
271 printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
272 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
273 gen_proto (*insn_ptr);
275 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
276 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
277 gen_nonproto (*insn_ptr);
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);
284 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
285 gen_nonproto (*insn_ptr);
287 printf ("#endif /* NO_MD_PROTOTYPES */\n");
289 fflush (stdout);
290 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
291 /* NOTREACHED */
292 return 0;