]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genopinit.c
c-common.c: Include <stdlib.h> and <string.h>/<strings.h>.
[thirdparty/gcc.git] / gcc / genopinit.c
CommitLineData
af9e4a0c 1/* Generate code to initialize optabs from machine description.
ccd043a9 2 Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
af9e4a0c
RK
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
a35311b0
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
af9e4a0c
RK
20
21
22#include <stdio.h>
23#include "hconfig.h"
24#include "rtl.h"
25#include "obstack.h"
26#include <ctype.h>
27
ccd043a9
RL
28#ifdef HAVE_STDLIB_H
29#include <stdlib.h>
30#endif
31
32
af9e4a0c
RK
33static struct obstack obstack;
34struct obstack *rtl_obstack = &obstack;
35
36#define obstack_chunk_alloc xmalloc
37#define obstack_chunk_free free
38
39extern void free ();
40extern rtx read_rtx ();
41
42char *xmalloc ();
43static void fatal ();
44void fancy_abort ();
45
46/* Many parts of GCC use arrays that are indexed by machine mode and
47 contain the insn codes for pattern in the MD file that perform a given
48 operation on operands of that mode.
49
50 These patterns are present in the MD file with names that contain
51 the mode(s) used and the name of the operation. This program
52 writes a function `init_all_optabs' that initializes the optabs with
53 all the insn codes of the relevant patterns present in the MD file.
54
55 This array contains a list of optabs that need to be initialized. Within
56 each string, the name of the pattern to be matched against is delimited
57 with %( and %). In the string, %a and %b are used to match a short mode
58 name (the part of the mode name not including `mode' and converted to
59 lower-case). When writing out the initializer, the entire string is
60 used. %A and %B are replaced with the full name of the mode; %a and %b
61 are replaced with the short form of the name, as above.
62
63 If %N is present in the pattern, it means the two modes must be consecutive
64 widths in the same mode class (e.g, QImode and HImode). %I means that
65 only integer modes should be considered for the next mode, and %F means
66 that only float modes should be considered.
67
68 For some optabs, we store the operation by RTL codes. These are only
69 used for comparisons. In that case, %c and %C are the lower-case and
70 upper-case forms of the comparison, respectively. */
71
8c9881d1
RS
72/* The reason we use \% is to avoid sequences of the form %-capletter-%
73 which SCCS treats as magic. This gets warnings which you should ignore. */
74
af9e4a0c 75char *optabs[] =
8c9881d1
RS
76{ "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)",
77 "extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)",
78 "fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)",
79 "fixtab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns%F\%a%b2%)",
80 "fixtrunctab[(int) %A][(int) %B][0] = CODE_FOR_%(fix_trunc%F\%a%I\%b2%)",
81 "fixtrunctab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns_trunc%F\%a%I\%b2%)",
82 "floattab[(int) %B][(int) %A][0] = CODE_FOR_%(float%I\%a%F\%b2%)",
53f26922 83 "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)",
af9e4a0c
RK
84 "add_optab->handlers[(int) %A].insn_code = CODE_FOR_%(add%a3%)",
85 "sub_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sub%a3%)",
86 "smul_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mul%a3%)",
af309004
TG
87 "umul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umul%a3_highpart%)",
88 "smul_highpart_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smul%a3_highpart%)",
af9e4a0c
RK
89 "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N",
90 "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N",
8c9881d1
RS
91 "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)",
92 "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)",
af9e4a0c
RK
93 "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)",
94 "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)",
95 "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)",
96 "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)",
8c9881d1
RS
97 "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)",
98 "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)",
af9e4a0c
RK
99 "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)",
100 "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)",
101 "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)",
102 "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)",
103 "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)",
af9e4a0c
RK
104 "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)",
105 "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)",
106 "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)",
8c9881d1
RS
107 "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)",
108 "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)",
109 "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)",
110 "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)",
111 "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)",
112 "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)",
af9e4a0c
RK
113 "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)",
114 "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)",
115 "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)",
116 "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)",
117 "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)",
ed58a128 118 "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)",
af9e4a0c
RK
119 "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)",
120 "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)",
121 "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)",
122 "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)",
123 "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)",
124 "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)",
125 "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
126 "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
3c9958cd 127 "movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)",
af9e4a0c
RK
128 "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
129 "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
fd18db65
RK
130 "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)",
131 "clrstr_optab[(int) %A] = CODE_FOR_%(clrstr%a%)" };
af9e4a0c 132
53f26922
RS
133/* Allow linking with print-rtl.c. */
134char **insn_name_ptr;
135
af9e4a0c
RK
136static void
137gen_insn (insn)
138 rtx insn;
139{
140 char *name = XSTR (insn, 0);
141 int m1, m2, op;
142 int pindex;
143 int i;
144 char *np, *pp, *p, *q;
145 struct obstack *obstack_ptr;
146
147 /* Don't mention instructions whose names are the null string.
148 They are in the machine description just to be recognized. */
149 if (*name == 0)
150 return;
151
152 /* See if NAME matches one of the patterns we have for the optabs we know
153 about. */
154
155 for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++)
156 {
157 int force_float = 0, force_int = 0;
158 int force_consec = 0;
159 int matches = 1;
160
161 for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++)
162 ;
163
164 for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')');
165 pp++)
166 {
167 if (*pp != '%')
168 {
169 if (*pp != *np++)
170 break;
171 }
172 else
173 switch (*++pp)
174 {
175 case 'N':
176 force_consec = 1;
177 break;
178 case 'I':
179 force_int = 1;
180 break;
181 case 'F':
182 force_float = 1;
183 break;
184 case 'c':
185 for (op = 0; op < NUM_RTX_CODE; op++)
186 {
187 for (p = rtx_name[op], q = np; *p; p++, q++)
188 if (*p != *q)
189 break;
190
191 /* We have to be concerned about matching "gt" and
192 missing "gtu", e.g., so verify we have reached the
4639555c 193 end of thing we are to match. */
af9e4a0c
RK
194 if (*p == 0 && *q == 0 && rtx_class[op] == '<')
195 break;
196 }
197
198 if (op == NUM_RTX_CODE)
199 matches = 0;
200 else
201 np += strlen (rtx_name[op]);
202 break;
203 case 'a':
204 case 'b':
4639555c
ILT
205 /* This loop will stop at the first prefix match, so
206 look through the modes in reverse order, in case
207 EXTRA_CC_MODES was used and CC is a prefix of the
208 CC modes (as it should be). */
209 for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
af9e4a0c
RK
210 {
211 for (p = mode_name[i], q = np; *p; p++, q++)
212 if (tolower (*p) != *q)
213 break;
214
215 if (*p == 0
216 && (! force_int || mode_class[i] == MODE_INT)
217 && (! force_float || mode_class[i] == MODE_FLOAT))
218 break;
219 }
220
4639555c 221 if (i < 0)
af9e4a0c
RK
222 matches = 0;
223 else if (*pp == 'a')
224 m1 = i, np += strlen (mode_name[i]);
225 else
226 m2 = i, np += strlen (mode_name[i]);
227
228 force_int = force_float = 0;
229 break;
230
231 default:
232 abort ();
233 }
234 }
235
236 if (matches && pp[0] == '%' && pp[1] == ')'
237 && *np == 0
88a5e9da 238 && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
af9e4a0c
RK
239 break;
240 }
241
242 if (pindex == sizeof optabs / sizeof optabs[0])
243 return;
244
245 /* We found a match. If this pattern is only conditionally present,
246 write out the "if" and two extra blanks. */
247
248 if (*XSTR (insn, 2) != 0)
249 printf (" if (HAVE_%s)\n ", name);
250
251 printf (" ");
252
253 /* Now write out the initialization, making all required substitutions. */
254 for (pp = optabs[pindex]; *pp; pp++)
255 {
256 if (*pp != '%')
257 printf ("%c", *pp);
258 else
259 switch (*++pp)
260 {
261 case '(': case ')':
262 case 'I': case 'F': case 'N':
263 break;
264 case 'a':
265 for (np = mode_name[m1]; *np; np++)
266 printf ("%c", tolower (*np));
267 break;
268 case 'b':
269 for (np = mode_name[m2]; *np; np++)
270 printf ("%c", tolower (*np));
271 break;
272 case 'A':
273 printf ("%smode", mode_name[m1]);
274 break;
275 case 'B':
276 printf ("%smode", mode_name[m2]);
277 break;
278 case 'c':
279 printf ("%s", rtx_name[op]);
280 break;
281 case 'C':
282 for (np = rtx_name[op]; *np; np++)
283 printf ("%c", toupper (*np));
284 break;
285 }
286 }
287
288 printf (";\n");
289}
290\f
291char *
292xmalloc (size)
293 unsigned size;
294{
295 register char *val = (char *) malloc (size);
296
297 if (val == 0)
298 fatal ("virtual memory exhausted");
299
300 return val;
301}
302
303char *
304xrealloc (ptr, size)
305 char *ptr;
306 unsigned size;
307{
308 char *result = (char *) realloc (ptr, size);
309 if (!result)
310 fatal ("virtual memory exhausted");
311 return result;
312}
313
314static void
315fatal (s, a1, a2)
316 char *s;
317{
318 fprintf (stderr, "genopinit: ");
319 fprintf (stderr, s, a1, a2);
320 fprintf (stderr, "\n");
321 exit (FATAL_EXIT_CODE);
322}
323
324/* More 'friendly' abort that prints the line and file.
325 config.h can #define abort fancy_abort if you like that sort of thing. */
326
327void
328fancy_abort ()
329{
330 fatal ("Internal gcc abort.");
331}
332\f
333int
334main (argc, argv)
335 int argc;
336 char **argv;
337{
338 rtx desc;
339 rtx dummy;
340 rtx *insn_ptr;
341 FILE *infile;
342 register int c;
343
344 obstack_init (rtl_obstack);
345
346 if (argc <= 1)
347 fatal ("No input file name.");
348
349 infile = fopen (argv[1], "r");
350 if (infile == 0)
351 {
352 perror (argv[1]);
353 exit (FATAL_EXIT_CODE);
354 }
355
356 init_rtl ();
357
358 printf ("/* Generated automatically by the program `genopinit'\n\
359from the machine description file `md'. */\n\n");
360
361 printf ("#include \"config.h\"\n");
ccd043a9 362 printf ("#include <stdio.h>\n");
af9e4a0c
RK
363 printf ("#include \"rtl.h\"\n");
364 printf ("#include \"flags.h\"\n");
365 printf ("#include \"insn-flags.h\"\n");
366 printf ("#include \"insn-codes.h\"\n");
367 printf ("#include \"insn-config.h\"\n");
368 printf ("#include \"recog.h\"\n");
369 printf ("#include \"expr.h\"\n");
370 printf ("#include \"reload.h\"\n\n");
371
372 printf ("void\ninit_all_optabs ()\n{\n");
373
374 /* Read the machine description. */
375
376 while (1)
377 {
378 c = read_skip_spaces (infile);
379 if (c == EOF)
380 break;
381 ungetc (c, infile);
382
383 desc = read_rtx (infile);
384 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
385 gen_insn (desc);
386 }
387
388 printf ("}\n");
389
390 fflush (stdout);
391 exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
392 /* NOTREACHED */
393 return 0;
394}