OSDN Git Service

* c-common.c: Include <stdlib.h> and <string.h>/<strings.h>.
[pf3gnuchains/gcc-fork.git] / gcc / genconfig.c
1 /* Generate from machine description:
2    - some #define configuration flags.
3    Copyright (C) 1987, 1991, 1997 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22
23 #include <stdio.h>
24 #include "hconfig.h"
25 #include "rtl.h"
26 #include "obstack.h"
27
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31
32 static struct obstack obstack;
33 struct obstack *rtl_obstack = &obstack;
34
35 #define obstack_chunk_alloc xmalloc
36 #define obstack_chunk_free free
37
38 extern void free ();
39 extern rtx read_rtx ();
40
41 /* flags to determine output of machine description dependent #define's.  */
42 static int max_recog_operands;  /* Largest operand number seen.  */
43 static int max_dup_operands;    /* Largest number of match_dup in any insn.  */
44 static int max_clobbers_per_insn;
45 static int register_constraint_flag;
46 static int have_cc0_flag;
47 static int have_cmove_flag;
48 static int have_lo_sum_flag;
49
50 /* Maximum number of insns seen in a split.  */
51 static int max_insns_per_split = 1;
52
53 static int clobbers_seen_this_insn;
54 static int dup_operands_seen_this_insn;
55
56 char *xmalloc ();
57 static void fatal ();
58 void fancy_abort ();
59
60 /* RECOG_P will be non-zero if this pattern was seen in a context where it will
61    be used to recognize, rather than just generate an insn. 
62
63    NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
64    of a SET whose destination is not (pc).  */
65
66 static void
67 walk_insn_part (part, recog_p, non_pc_set_src)
68      rtx part;
69      int recog_p;
70      int non_pc_set_src;
71 {
72   register int i, j;
73   register RTX_CODE code;
74   register char *format_ptr;
75
76   if (part == 0)
77     return;
78
79   code = GET_CODE (part);
80   switch (code)
81     {
82     case CLOBBER:
83       clobbers_seen_this_insn++;
84       break;
85
86     case MATCH_OPERAND:
87       if (XINT (part, 0) > max_recog_operands)
88         max_recog_operands = XINT (part, 0);
89       if (XSTR (part, 2) && *XSTR (part, 2))
90         register_constraint_flag = 1;
91       return;
92
93     case MATCH_OP_DUP:
94     case MATCH_PAR_DUP:
95       ++dup_operands_seen_this_insn;
96     case MATCH_SCRATCH:
97     case MATCH_PARALLEL:
98     case MATCH_OPERATOR:
99       if (XINT (part, 0) > max_recog_operands)
100         max_recog_operands = XINT (part, 0);
101       /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
102          MATCH_PARALLEL.  */
103       break;
104
105     case LABEL_REF:
106       if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
107         break;
108       return;
109
110     case MATCH_DUP:
111       ++dup_operands_seen_this_insn;
112       if (XINT (part, 0) > max_recog_operands)
113         max_recog_operands = XINT (part, 0);
114       return;
115
116     case CC0:
117       if (recog_p)
118         have_cc0_flag = 1;
119       return;
120
121     case LO_SUM:
122       if (recog_p)
123         have_lo_sum_flag = 1;
124       return;
125
126     case SET:
127       walk_insn_part (SET_DEST (part), 0, recog_p);
128       walk_insn_part (SET_SRC (part), recog_p,
129                       GET_CODE (SET_DEST (part)) != PC);
130       return;
131
132     case IF_THEN_ELSE:
133       /* Only consider this machine as having a conditional move if the
134          two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
135          we have some specific IF_THEN_ELSE construct (like the doz
136          instruction on the RS/6000) that can't be used in the general
137          context we want it for.  */
138
139       if (recog_p && non_pc_set_src
140           && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
141           && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
142         have_cmove_flag = 1;
143       break;
144
145     case REG: case CONST_INT: case SYMBOL_REF:
146     case PC:
147       return;
148
149     default:
150       break;
151     }
152
153   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
154
155   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
156     switch (*format_ptr++)
157       {
158       case 'e':
159       case 'u':
160         walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
161         break;
162       case 'E':
163         if (XVEC (part, i) != NULL)
164           for (j = 0; j < XVECLEN (part, i); j++)
165             walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
166         break;
167       }
168 }
169
170 static void
171 gen_insn (insn)
172      rtx insn;
173 {
174   int i;
175
176   /* Walk the insn pattern to gather the #define's status.  */
177   clobbers_seen_this_insn = 0;
178   dup_operands_seen_this_insn = 0;
179   if (XVEC (insn, 1) != 0)
180     for (i = 0; i < XVECLEN (insn, 1); i++)
181       walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
182
183   if (clobbers_seen_this_insn > max_clobbers_per_insn)
184     max_clobbers_per_insn = clobbers_seen_this_insn;
185   if (dup_operands_seen_this_insn > max_dup_operands)
186     max_dup_operands = dup_operands_seen_this_insn;
187 }
188
189 /* Similar but scan a define_expand.  */
190
191 static void
192 gen_expand (insn)
193      rtx insn;
194 {
195   int i;
196
197   /* Walk the insn pattern to gather the #define's status.  */
198
199   /* Note that we don't bother recording the number of MATCH_DUPs
200      that occur in a gen_expand, because only reload cares about that.  */
201   if (XVEC (insn, 1) != 0)
202     for (i = 0; i < XVECLEN (insn, 1); i++)
203       {
204         /* Compute the maximum SETs and CLOBBERS
205            in any one of the sub-insns;
206            don't sum across all of them.  */
207         clobbers_seen_this_insn = 0;
208
209         walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
210
211         if (clobbers_seen_this_insn > max_clobbers_per_insn)
212           max_clobbers_per_insn = clobbers_seen_this_insn;
213       }
214 }
215
216 /* Similar but scan a define_split.  */
217
218 static void
219 gen_split (split)
220      rtx split;
221 {
222   int i;
223
224   /* Look through the patterns that are matched
225      to compute the maximum operand number.  */
226   for (i = 0; i < XVECLEN (split, 0); i++)
227     walk_insn_part (XVECEXP (split, 0, i), 1, 0);
228   /* Look at the number of insns this insn could split into.  */
229   if (XVECLEN (split, 2) > max_insns_per_split)
230     max_insns_per_split = XVECLEN (split, 2);
231 }
232
233 static void
234 gen_peephole (peep)
235      rtx peep;
236 {
237   int i;
238
239   /* Look through the patterns that are matched
240      to compute the maximum operand number.  */
241   for (i = 0; i < XVECLEN (peep, 0); i++)
242     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
243 }
244 \f
245 char *
246 xmalloc (size)
247      unsigned size;
248 {
249   register char *val = (char *) malloc (size);
250
251   if (val == 0)
252     fatal ("virtual memory exhausted");
253
254   return val;
255 }
256
257 char *
258 xrealloc (ptr, size)
259      char *ptr;
260      unsigned size;
261 {
262   char *result = (char *) realloc (ptr, size);
263   if (!result)
264     fatal ("virtual memory exhausted");
265   return result;
266 }
267
268 static void
269 fatal (s, a1, a2)
270      char *s;
271 {
272   fprintf (stderr, "genconfig: ");
273   fprintf (stderr, s, a1, a2);
274   fprintf (stderr, "\n");
275   exit (FATAL_EXIT_CODE);
276 }
277
278 /* More 'friendly' abort that prints the line and file.
279    config.h can #define abort fancy_abort if you like that sort of thing.  */
280
281 void
282 fancy_abort ()
283 {
284   fatal ("Internal gcc abort.");
285 }
286 \f
287 int
288 main (argc, argv)
289      int argc;
290      char **argv;
291 {
292   rtx desc;
293   FILE *infile;
294   register int c;
295
296   obstack_init (rtl_obstack);
297
298   if (argc <= 1)
299     fatal ("No input file name.");
300
301   infile = fopen (argv[1], "r");
302   if (infile == 0)
303     {
304       perror (argv[1]);
305       exit (FATAL_EXIT_CODE);
306     }
307
308   init_rtl ();
309
310   printf ("/* Generated automatically by the program `genconfig'\n\
311 from the machine description file `md'.  */\n\n");
312
313   /* Allow at least 10 operands for the sake of asm constructs.  */
314   max_recog_operands = 9;  /* We will add 1 later.  */
315   max_dup_operands = 1;
316
317   /* Read the machine description.  */
318
319   while (1)
320     {
321       c = read_skip_spaces (infile);
322       if (c == EOF)
323         break;
324       ungetc (c, infile);
325
326       desc = read_rtx (infile);
327       if (GET_CODE (desc) == DEFINE_INSN)
328         gen_insn (desc);
329       if (GET_CODE (desc) == DEFINE_EXPAND)
330         gen_expand (desc);
331       if (GET_CODE (desc) == DEFINE_SPLIT)
332         gen_split (desc);
333       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
334         gen_peephole (desc);
335     }
336
337   printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
338
339   printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
340
341   /* This is conditionally defined, in case the user writes code which emits
342      more splits than we can readily see (and knows s/he does it).  */
343   printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n",
344           max_insns_per_split);
345
346   if (register_constraint_flag)
347     printf ("#define REGISTER_CONSTRAINTS\n");
348
349   if (have_cc0_flag)
350     printf ("#define HAVE_cc0\n");
351
352   if (have_cmove_flag)
353     printf ("#define HAVE_conditional_move\n");
354
355   if (have_lo_sum_flag)
356     printf ("#define HAVE_lo_sum\n");
357
358   fflush (stdout);
359   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
360   /* NOTREACHED */
361   return 0;
362 }