source: trunk/third/gcc/genconfig.c @ 11288

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