]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/genflags.c
* genattr.c (main): Add extern prototype. Call return, not exit.
[thirdparty/gcc.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 /* Obstacks to remember normal, and call insns. */
37 static struct obstack call_obstack, normal_obstack;
38
39 /* Max size of names encountered. */
40 static int max_id_len;
41
42 static int num_operands PROTO((rtx));
43 static void gen_proto PROTO((rtx));
44 static void gen_nonproto PROTO((rtx));
45 static void gen_insn PROTO((rtx));
46
47
48 /* Count the number of match_operand's found. */
49
50 static int
51 num_operands (x)
52 rtx x;
53 {
54 int count = 0;
55 int i, j;
56 enum rtx_code code = GET_CODE (x);
57 const char *format_ptr = GET_RTX_FORMAT (code);
58
59 if (code == MATCH_OPERAND)
60 return 1;
61
62 if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
63 count++;
64
65 for (i = 0; i < GET_RTX_LENGTH (code); i++)
66 {
67 switch (*format_ptr++)
68 {
69 case 'u':
70 case 'e':
71 count += num_operands (XEXP (x, i));
72 break;
73
74 case 'E':
75 if (XVEC (x, i) != NULL)
76 for (j = 0; j < XVECLEN (x, i); j++)
77 count += num_operands (XVECEXP (x, i, j));
78
79 break;
80 }
81 }
82
83 return count;
84 }
85
86 /* Print out prototype information for a function. */
87
88 static void
89 gen_proto (insn)
90 rtx insn;
91 {
92 int num = num_operands (insn);
93 printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
94
95 if (num == 0)
96 printf ("void");
97 else
98 {
99 while (num-- > 1)
100 printf ("rtx, ");
101
102 printf ("rtx");
103 }
104
105 printf ("));\n");
106 }
107
108 /* Print out a function declaration without a prototype. */
109
110 static void
111 gen_nonproto (insn)
112 rtx insn;
113 {
114 printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
115 }
116
117 static void
118 gen_insn (insn)
119 rtx insn;
120 {
121 char *name = XSTR (insn, 0);
122 char *p;
123 struct obstack *obstack_ptr;
124 int len;
125
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;
131
132 len = strlen (name);
133
134 if (len > max_id_len)
135 max_id_len = len;
136
137 printf ("#define HAVE_%s ", name);
138 if (strlen (XSTR (insn, 2)) == 0)
139 printf ("1\n");
140 else
141 {
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++)
146 {
147 if (*p == '\n')
148 printf (" \\\n");
149 else
150 printf ("%c", *p);
151 }
152 printf (")\n");
153 }
154
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. */
160
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;
167
168 obstack_grow (obstack_ptr, &insn, sizeof (rtx));
169 }
170 \f
171 PTR
172 xmalloc (size)
173 size_t size;
174 {
175 register PTR val = (PTR) malloc (size);
176
177 if (val == 0)
178 fatal ("virtual memory exhausted");
179
180 return val;
181 }
182
183 PTR
184 xrealloc (old, size)
185 PTR old;
186 size_t size;
187 {
188 register PTR ptr;
189 if (old)
190 ptr = (PTR) realloc (old, size);
191 else
192 ptr = (PTR) malloc (size);
193 if (!ptr)
194 fatal ("virtual memory exhausted");
195 return ptr;
196 }
197
198 extern int main PROTO ((int, char **));
199
200 int
201 main (argc, argv)
202 int argc;
203 char **argv;
204 {
205 rtx desc;
206 rtx dummy;
207 rtx *call_insns;
208 rtx *normal_insns;
209 rtx *insn_ptr;
210 FILE *infile;
211 register int c;
212
213 progname = "genflags";
214 obstack_init (rtl_obstack);
215 obstack_init (&call_obstack);
216 obstack_init (&normal_obstack);
217
218 if (argc <= 1)
219 fatal ("No input file name.");
220
221 infile = fopen (argv[1], "r");
222 if (infile == 0)
223 {
224 perror (argv[1]);
225 return (FATAL_EXIT_CODE);
226 }
227
228 printf ("/* Generated automatically by the program `genflags'\n\
229 from the machine description file `md'. */\n\n");
230
231 /* Read the machine description. */
232
233 while (1)
234 {
235 c = read_skip_spaces (infile);
236 if (c == EOF)
237 break;
238 ungetc (c, infile);
239
240 desc = read_rtx (infile);
241 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
242 gen_insn (desc);
243 }
244
245 /* Print out the prototypes now. */
246 dummy = (rtx) 0;
247 obstack_grow (&call_obstack, &dummy, sizeof (rtx));
248 call_insns = (rtx *) obstack_finish (&call_obstack);
249
250 obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
251 normal_insns = (rtx *) obstack_finish (&normal_obstack);
252
253 printf ("\n#ifndef NO_MD_PROTOTYPES\n");
254 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
255 gen_proto (*insn_ptr);
256
257 printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
258 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
259 gen_proto (*insn_ptr);
260
261 printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
262 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
263 gen_nonproto (*insn_ptr);
264
265 printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
266 printf ("\n#else /* NO_MD_PROTOTYPES */\n");
267 for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
268 gen_nonproto (*insn_ptr);
269
270 for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
271 gen_nonproto (*insn_ptr);
272
273 printf ("#endif /* NO_MD_PROTOTYPES */\n");
274
275 fflush (stdout);
276 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
277 }
278
279 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
280 const char *
281 get_insn_name (code)
282 int code ATTRIBUTE_UNUSED;
283 {
284 return NULL;
285 }