genflags.c revision 50397
1214501Srpaulo/* Generate from machine description:
2214501Srpaulo
3214501Srpaulo   - some flags HAVE_... saying which simple standard instructions are
4214501Srpaulo   available for this machine.
5214501Srpaulo   Copyright (C) 1987, 1991, 1995, 1998 Free Software Foundation, Inc.
6252190Srpaulo
7252190SrpauloThis file is part of GNU CC.
8214501Srpaulo
9214501SrpauloGNU CC is free software; you can redistribute it and/or modify
10214501Srpauloit under the terms of the GNU General Public License as published by
11214501Srpaulothe Free Software Foundation; either version 2, or (at your option)
12214501Srpauloany later version.
13214501Srpaulo
14214501SrpauloGNU CC is distributed in the hope that it will be useful,
15214501Srpaulobut WITHOUT ANY WARRANTY; without even the implied warranty of
16214501SrpauloMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17214501SrpauloGNU General Public License for more details.
18214501Srpaulo
19214501SrpauloYou should have received a copy of the GNU General Public License
20214501Srpauloalong with GNU CC; see the file COPYING.  If not, write to
21214501Srpaulothe Free Software Foundation, 59 Temple Place - Suite 330,
22214501SrpauloBoston, MA 02111-1307, USA.  */
23252190Srpaulo
24252190Srpaulo
25252190Srpaulo#include "hconfig.h"
26252190Srpaulo#ifdef __STDC__
27214501Srpaulo#include <stdarg.h>
28252190Srpaulo#else
29252190Srpaulo#include <varargs.h>
30252190Srpaulo#endif
31214501Srpaulo#include "system.h"
32252190Srpaulo#include "rtl.h"
33252190Srpaulo#include "obstack.h"
34252190Srpaulo
35252190Srpaulostatic struct obstack obstack;
36252190Srpaulostruct obstack *rtl_obstack = &obstack;
37214501Srpaulo
38252190Srpaulo#define obstack_chunk_alloc xmalloc
39252190Srpaulo#define obstack_chunk_free free
40252190Srpaulo
41252190Srpaulochar *xmalloc PROTO((unsigned));
42252190Srpaulostatic void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
43252190Srpaulovoid fancy_abort PROTO((void));
44214501Srpaulo
45214501Srpaulo/* Names for patterns.  Need to allow linking with print-rtl.  */
46214501Srpaulochar **insn_name_ptr;
47214501Srpaulo
48214501Srpaulo/* Obstacks to remember normal, and call insns.  */
49214501Srpaulostatic struct obstack call_obstack, normal_obstack;
50214501Srpaulo
51214501Srpaulo/* Max size of names encountered.  */
52214501Srpaulostatic int max_id_len;
53252190Srpaulo
54252190Srpaulostatic int num_operands PROTO((rtx));
55252190Srpaulostatic void gen_proto PROTO((rtx));
56214501Srpaulostatic void gen_nonproto PROTO((rtx));
57252190Srpaulostatic void gen_insn PROTO((rtx));
58281806Srpaulo
59281806Srpaulo
60214501Srpaulo/* Count the number of match_operand's found.  */
61252190Srpaulo
62252190Srpaulostatic int
63252190Srpaulonum_operands (x)
64214501Srpaulo     rtx x;
65252190Srpaulo{
66252190Srpaulo  int count = 0;
67214501Srpaulo  int i, j;
68252190Srpaulo  enum rtx_code code = GET_CODE (x);
69252190Srpaulo  char *format_ptr = GET_RTX_FORMAT (code);
70252190Srpaulo
71214501Srpaulo  if (code == MATCH_OPERAND)
72252190Srpaulo    return 1;
73252190Srpaulo
74252190Srpaulo  if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
75214501Srpaulo    count++;
76252190Srpaulo
77252190Srpaulo  for (i = 0; i < GET_RTX_LENGTH (code); i++)
78252190Srpaulo    {
79214501Srpaulo      switch (*format_ptr++)
80252190Srpaulo	{
81252190Srpaulo	case 'u':
82214501Srpaulo	case 'e':
83252190Srpaulo	  count += num_operands (XEXP (x, i));
84252190Srpaulo	  break;
85252190Srpaulo
86252190Srpaulo	case 'E':
87214501Srpaulo	  if (XVEC (x, i) != NULL)
88214501Srpaulo	    for (j = 0; j < XVECLEN (x, i); j++)
89214501Srpaulo	      count += num_operands (XVECEXP (x, i, j));
90281806Srpaulo
91281806Srpaulo	  break;
92281806Srpaulo	}
93214501Srpaulo    }
94214501Srpaulo
95214501Srpaulo  return count;
96252190Srpaulo}
97252190Srpaulo
98252190Srpaulo/* Print out prototype information for a function.  */
99252190Srpaulo
100252190Srpaulostatic void
101214501Srpaulogen_proto (insn)
102214501Srpaulo     rtx insn;
103214501Srpaulo{
104252190Srpaulo  int num = num_operands (insn);
105252190Srpaulo  printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
106252190Srpaulo
107281806Srpaulo  if (num == 0)
108281806Srpaulo    printf ("void");
109281806Srpaulo  else
110214501Srpaulo    {
111214501Srpaulo      while (num-- > 1)
112214501Srpaulo	printf ("rtx, ");
113252190Srpaulo
114252190Srpaulo      printf ("rtx");
115252190Srpaulo    }
116214501Srpaulo
117214501Srpaulo  printf ("));\n");
118214501Srpaulo}
119252190Srpaulo
120252190Srpaulo/* Print out a function declaration without a prototype.  */
121252190Srpaulo
122214501Srpaulostatic void
123214501Srpaulogen_nonproto (insn)
124214501Srpaulo     rtx insn;
125214501Srpaulo{
126214501Srpaulo  printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
127214501Srpaulo}
128214501Srpaulo
129214501Srpaulostatic void
130214501Srpaulogen_insn (insn)
131281806Srpaulo     rtx insn;
132281806Srpaulo{
133281806Srpaulo  char *name = XSTR (insn, 0);
134252190Srpaulo  char *p;
135252190Srpaulo  struct obstack *obstack_ptr;
136214501Srpaulo  int len;
137252190Srpaulo
138252190Srpaulo  /* Don't mention instructions whose names are the null string
139214501Srpaulo     or begin with '*'.  They are in the machine description just
140281806Srpaulo     to be recognized.  */
141281806Srpaulo  if (name[0] == 0 || name[0] == '*')
142281806Srpaulo    return;
143281806Srpaulo
144281806Srpaulo  len = strlen (name);
145281806Srpaulo
146252190Srpaulo  if (len > max_id_len)
147252190Srpaulo    max_id_len = len;
148214501Srpaulo
149252190Srpaulo  printf ("#define HAVE_%s ", name);
150252190Srpaulo  if (strlen (XSTR (insn, 2)) == 0)
151214501Srpaulo    printf ("1\n");
152252190Srpaulo  else
153252190Srpaulo    {
154214501Srpaulo      /* Write the macro definition, putting \'s at the end of each line,
155252190Srpaulo	 if more than one.  */
156252190Srpaulo      printf ("(");
157214501Srpaulo      for (p = XSTR (insn, 2); *p; p++)
158252190Srpaulo	{
159252190Srpaulo	  if (*p == '\n')
160214501Srpaulo	    printf (" \\\n");
161252190Srpaulo	  else
162252190Srpaulo	    printf ("%c", *p);
163252190Srpaulo	}
164214501Srpaulo      printf (")\n");
165252190Srpaulo    }
166252190Srpaulo
167252190Srpaulo  /* Save the current insn, so that we can later put out appropriate
168214501Srpaulo     prototypes.  At present, most md files have the wrong number of
169252190Srpaulo     arguments for the call insns (call, call_value, call_pop,
170252190Srpaulo     call_value_pop) ignoring the extra arguments that are passed for
171252190Srpaulo     some machines, so by default, turn off the prototype.  */
172214501Srpaulo
173252190Srpaulo  obstack_ptr = (name[0] == 'c'
174252190Srpaulo		 && (!strcmp (name, "call")
175214501Srpaulo		     || !strcmp (name, "call_value")
176252190Srpaulo		     || !strcmp (name, "call_pop")
177252190Srpaulo		     || !strcmp (name, "call_value_pop")))
178252190Srpaulo    ? &call_obstack : &normal_obstack;
179214501Srpaulo
180252190Srpaulo  obstack_grow (obstack_ptr, &insn, sizeof (rtx));
181252190Srpaulo}
182252190Srpaulo
183214501Srpaulochar *
184252190Srpauloxmalloc (size)
185252190Srpaulo     unsigned size;
186252190Srpaulo{
187214501Srpaulo  register char *val = (char *) malloc (size);
188252190Srpaulo
189252190Srpaulo  if (val == 0)
190214501Srpaulo    fatal ("virtual memory exhausted");
191252190Srpaulo
192252190Srpaulo  return val;
193214501Srpaulo}
194252190Srpaulo
195252190Srpaulochar *
196252190Srpauloxrealloc (ptr, size)
197214501Srpaulo     char *ptr;
198252190Srpaulo     unsigned size;
199252190Srpaulo{
200252190Srpaulo  char *result = (char *) realloc (ptr, size);
201214501Srpaulo  if (!result)
202252190Srpaulo    fatal ("virtual memory exhausted");
203252190Srpaulo  return result;
204214501Srpaulo}
205252190Srpaulo
206252190Srpaulostatic void
207214501Srpaulofatal VPROTO ((char *format, ...))
208252190Srpaulo{
209252190Srpaulo#ifndef __STDC__
210252190Srpaulo  char *format;
211214501Srpaulo#endif
212252190Srpaulo  va_list ap;
213252190Srpaulo
214252190Srpaulo  VA_START (ap, format);
215214501Srpaulo
216252190Srpaulo#ifndef __STDC__
217252190Srpaulo  format = va_arg (ap, char *);
218252190Srpaulo#endif
219214501Srpaulo
220252190Srpaulo  fprintf (stderr, "genflags: ");
221252190Srpaulo  vfprintf (stderr, format, ap);
222252190Srpaulo  va_end (ap);
223214501Srpaulo  fprintf (stderr, "\n");
224252190Srpaulo  exit (FATAL_EXIT_CODE);
225252190Srpaulo}
226214501Srpaulo
227252190Srpaulo/* More 'friendly' abort that prints the line and file.
228252190Srpaulo   config.h can #define abort fancy_abort if you like that sort of thing.  */
229214501Srpaulo
230281806Srpaulovoid
231281806Srpaulofancy_abort ()
232281806Srpaulo{
233281806Srpaulo  fatal ("Internal gcc abort.");
234281806Srpaulo}
235281806Srpaulo
236281806Srpauloint
237281806Srpaulomain (argc, argv)
238252190Srpaulo     int argc;
239252190Srpaulo     char **argv;
240214501Srpaulo{
241252190Srpaulo  rtx desc;
242252190Srpaulo  rtx dummy;
243252190Srpaulo  rtx *call_insns;
244252190Srpaulo  rtx *normal_insns;
245252190Srpaulo  rtx *insn_ptr;
246252190Srpaulo  FILE *infile;
247252190Srpaulo  register int c;
248252190Srpaulo
249252190Srpaulo  obstack_init (rtl_obstack);
250252190Srpaulo  obstack_init (&call_obstack);
251252190Srpaulo  obstack_init (&normal_obstack);
252252190Srpaulo
253252190Srpaulo  if (argc <= 1)
254252190Srpaulo    fatal ("No input file name.");
255252190Srpaulo
256252190Srpaulo  infile = fopen (argv[1], "r");
257252190Srpaulo  if (infile == 0)
258252190Srpaulo    {
259252190Srpaulo      perror (argv[1]);
260252190Srpaulo      exit (FATAL_EXIT_CODE);
261252190Srpaulo    }
262252190Srpaulo
263252190Srpaulo  init_rtl ();
264252190Srpaulo
265252190Srpaulo  printf ("/* Generated automatically by the program `genflags'\n\
266252190Srpaulofrom the machine description file `md'.  */\n\n");
267252190Srpaulo
268252190Srpaulo  /* Read the machine description.  */
269252190Srpaulo
270252190Srpaulo  while (1)
271252190Srpaulo    {
272252190Srpaulo      c = read_skip_spaces (infile);
273252190Srpaulo      if (c == EOF)
274281806Srpaulo	break;
275281806Srpaulo      ungetc (c, infile);
276281806Srpaulo
277252190Srpaulo      desc = read_rtx (infile);
278252190Srpaulo      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
279252190Srpaulo	gen_insn (desc);
280252190Srpaulo    }
281252190Srpaulo
282252190Srpaulo  /* Print out the prototypes now.  */
283252190Srpaulo  dummy = (rtx) 0;
284252190Srpaulo  obstack_grow (&call_obstack, &dummy, sizeof (rtx));
285252190Srpaulo  call_insns = (rtx *) obstack_finish (&call_obstack);
286252190Srpaulo
287252190Srpaulo  obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
288252190Srpaulo  normal_insns = (rtx *) obstack_finish (&normal_obstack);
289252190Srpaulo
290252190Srpaulo  printf ("\n#ifndef NO_MD_PROTOTYPES\n");
291214501Srpaulo  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
292214501Srpaulo    gen_proto (*insn_ptr);
293214501Srpaulo
294252190Srpaulo  printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
295252190Srpaulo  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
296214501Srpaulo    gen_proto (*insn_ptr);
297252190Srpaulo
298252190Srpaulo  printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
299252190Srpaulo  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
300214501Srpaulo    gen_nonproto (*insn_ptr);
301281806Srpaulo
302281806Srpaulo  printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
303281806Srpaulo  printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
304281806Srpaulo  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
305281806Srpaulo    gen_nonproto (*insn_ptr);
306281806Srpaulo
307281806Srpaulo  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
308281806Srpaulo    gen_nonproto (*insn_ptr);
309281806Srpaulo
310281806Srpaulo  printf ("#endif  /* NO_MD_PROTOTYPES */\n");
311281806Srpaulo
312281806Srpaulo  fflush (stdout);
313281806Srpaulo  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
314281806Srpaulo  /* NOTREACHED */
315281806Srpaulo  return 0;
316281806Srpaulo}
317281806Srpaulo