genflags.c revision 18334
12061Sjkh/* Generate from machine description:
250479Speter
32061Sjkh   - some flags HAVE_... saying which simple standard instructions are
438666Sjb   available for this machine.
532427Sjb   Copyright (C) 1987, 1991, 1995 Free Software Foundation, Inc.
638666Sjb
738666SjbThis file is part of GNU CC.
838666Sjb
938666SjbGNU CC is free software; you can redistribute it and/or modify
1064049Salexit under the terms of the GNU General Public License as published by
1164049Salexthe Free Software Foundation; either version 2, or (at your option)
1266071Smarkmany later version.
1373504Sobrien
1438666SjbGNU CC is distributed in the hope that it will be useful,
1544918Sjkhbut WITHOUT ANY WARRANTY; without even the implied warranty of
1638666SjbMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1738666SjbGNU General Public License for more details.
1838666Sjb
1938666SjbYou should have received a copy of the GNU General Public License
2038666Sjbalong with GNU CC; see the file COPYING.  If not, write to
2138666Sjbthe Free Software Foundation, 59 Temple Place - Suite 330,
2238666SjbBoston, MA 02111-1307, USA.  */
2338978Sjb
2438978Sjb
2532427Sjb#include <stdio.h>
2638666Sjb#include "hconfig.h"
2738666Sjb#include "rtl.h"
2838666Sjb#include "obstack.h"
2938666Sjb
3038666Sjbstatic struct obstack obstack;
3138666Sjbstruct obstack *rtl_obstack = &obstack;
3217308Speter
3338666Sjb#define obstack_chunk_alloc xmalloc
3438666Sjb#define obstack_chunk_free free
3538666Sjb
3619175Sbdeextern void free ();
3738666Sjbextern rtx read_rtx ();
3838666Sjb
3938042Sbdechar *xmalloc ();
4039726Sjbstatic void fatal ();
4138666Sjbvoid fancy_abort ();
4238666Sjb
4338042Sbde/* Names for patterns.  Need to allow linking with print-rtl.  */
4438666Sjbchar **insn_name_ptr;
4549315Shoek
4617308Speter/* Obstacks to remember normal, and call insns.  */
4738666Sjbstatic struct obstack call_obstack, normal_obstack;
4838666Sjb
4938666Sjb/* Max size of names encountered.  */
5038666Sjbstatic int max_id_len;
5117308Speter
5245108Sobrien/* Count the number of match_operand's found.  */
5342128Speterstatic int
5442128Speternum_operands (x)
5538666Sjb     rtx x;
5651361Sjb{
5738666Sjb  int count = 0;
5817308Speter  int i, j;
5938666Sjb  enum rtx_code code = GET_CODE (x);
6017308Speter  char *format_ptr = GET_RTX_FORMAT (code);
6138666Sjb
6217308Speter  if (code == MATCH_OPERAND)
6327910Sasami    return 1;
6443226Sjkh
6543226Sjkh  if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
6643226Sjkh    count++;
6738666Sjb
6827910Sasami  for (i = 0; i < GET_RTX_LENGTH (code); i++)
6938666Sjb    {
7038666Sjb      switch (*format_ptr++)
7138666Sjb	{
7227910Sasami	case 'u':
7338666Sjb	case 'e':
7438666Sjb	  count += num_operands (XEXP (x, i));
7543226Sjkh	  break;
7643226Sjkh
7727910Sasami	case 'E':
7838666Sjb	  if (XVEC (x, i) != NULL)
7938666Sjb	    for (j = 0; j < XVECLEN (x, i); j++)
8027910Sasami	      count += num_operands (XVECEXP (x, i, j));
8138666Sjb
8227910Sasami	  break;
8317308Speter	}
8438666Sjb    }
8538666Sjb
8617308Speter  return count;
8774842Sru}
8868987Smarcel
8969496Sjkh/* Print out prototype information for a function.  */
9069496Sjkhstatic void
9169496Sjkhgen_proto (insn)
922061Sjkh     rtx insn;
9355026Smarcel{
9455026Smarcel  int num = num_operands (insn);
9554324Smarcel  printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
9617308Speter
9738666Sjb  if (num == 0)
9817308Speter    printf ("void");
9955678Smarcel  else
10038666Sjb    {
10154324Smarcel      while (num-- > 1)
1022302Spaul	printf ("rtx, ");
10339206Sjkh
10439206Sjkh      printf ("rtx");
10539206Sjkh    }
10673349Sru
10717308Speter  printf ("));\n");
10854324Smarcel}
10954324Smarcel
11054324Smarcel/* Print out a function declaration without a prototype.  */
11154324Smarcelstatic void
11254324Smarcelgen_nonproto (insn)
11354324Smarcel     rtx insn;
11454324Smarcel{
11569659Sobrien  printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
11654324Smarcel}
11754324Smarcel
11854324Smarcelstatic void
11954324Smarcelgen_insn (insn)
12054324Smarcel     rtx insn;
12154324Smarcel{
12254324Smarcel  char *name = XSTR (insn, 0);
12354324Smarcel  char *p;
12454324Smarcel  struct obstack *obstack_ptr;
12554324Smarcel  int len;
12654324Smarcel
12754324Smarcel  /* Don't mention instructions whose names are the null string
12854324Smarcel     or begin with '*'.  They are in the machine description just
12954324Smarcel     to be recognized.  */
13054324Smarcel  if (name[0] == 0 || name[0] == '*')
13154324Smarcel    return;
13254324Smarcel
13354324Smarcel  len = strlen (name);
13454324Smarcel
13573504Sobrien  if (len > max_id_len)
13654324Smarcel    max_id_len = len;
13754324Smarcel
13854324Smarcel  printf ("#define HAVE_%s ", name);
13938666Sjb  if (strlen (XSTR (insn, 2)) == 0)
14038666Sjb    printf ("1\n");
14117308Speter  else
14238666Sjb    {
14338666Sjb      /* Write the macro definition, putting \'s at the end of each line,
14438666Sjb	 if more than one.  */
14517308Speter      printf ("(");
14655678Smarcel      for (p = XSTR (insn, 2); *p; p++)
14755678Smarcel	{
14855678Smarcel	  if (*p == '\n')
14955678Smarcel	    printf (" \\\n");
15055678Smarcel	  else
1512061Sjkh	    printf ("%c", *p);
15217308Speter	}
15338666Sjb      printf (")\n");
15438666Sjb    }
15517308Speter
15655678Smarcel  /* Save the current insn, so that we can later put out appropriate
1573626Swollman     prototypes.  At present, most md files have the wrong number of
15817308Speter     arguments for the call insns (call, call_value, call_pop,
15955678Smarcel     call_value_pop) ignoring the extra arguments that are passed for
16055678Smarcel     some machines, so by default, turn off the prototype.  */
16155678Smarcel
16255678Smarcel  obstack_ptr = (name[0] == 'c'
16355678Smarcel		 && (!strcmp (name, "call")
16455678Smarcel		     || !strcmp (name, "call_value")
16555678Smarcel		     || !strcmp (name, "call_pop")
16655678Smarcel		     || !strcmp (name, "call_value_pop")))
16755678Smarcel    ? &call_obstack : &normal_obstack;
16855678Smarcel
16955678Smarcel  obstack_grow (obstack_ptr, &insn, sizeof (rtx));
17055678Smarcel}
17155678Smarcel
17238666Sjbchar *
17338666Sjbxmalloc (size)
17417308Speter     unsigned size;
17555678Smarcel{
17638978Sjb  register char *val = (char *) malloc (size);
1773626Swollman
17817308Speter  if (val == 0)
17938666Sjb    fatal ("virtual memory exhausted");
18017308Speter
18143226Sjkh  return val;
18243226Sjkh}
18343226Sjkh
18438666Sjbchar *
18538666Sjbxrealloc (ptr, size)
18644103Smsmith     char *ptr;
187     unsigned size;
188{
189  char *result = (char *) realloc (ptr, size);
190  if (!result)
191    fatal ("virtual memory exhausted");
192  return result;
193}
194
195static void
196fatal (s, a1, a2)
197     char *s;
198{
199  fprintf (stderr, "genflags: ");
200  fprintf (stderr, s, a1, a2);
201  fprintf (stderr, "\n");
202  exit (FATAL_EXIT_CODE);
203}
204
205/* More 'friendly' abort that prints the line and file.
206   config.h can #define abort fancy_abort if you like that sort of thing.  */
207
208void
209fancy_abort ()
210{
211  fatal ("Internal gcc abort.");
212}
213
214int
215main (argc, argv)
216     int argc;
217     char **argv;
218{
219  rtx desc;
220  rtx dummy;
221  rtx *call_insns;
222  rtx *normal_insns;
223  rtx *insn_ptr;
224  FILE *infile;
225  register int c;
226
227  obstack_init (rtl_obstack);
228  obstack_init (&call_obstack);
229  obstack_init (&normal_obstack);
230
231  if (argc <= 1)
232    fatal ("No input file name.");
233
234  infile = fopen (argv[1], "r");
235  if (infile == 0)
236    {
237      perror (argv[1]);
238      exit (FATAL_EXIT_CODE);
239    }
240
241  init_rtl ();
242
243  printf ("/* Generated automatically by the program `genflags'\n\
244from the machine description file `md'.  */\n\n");
245
246  /* Read the machine description.  */
247
248  while (1)
249    {
250      c = read_skip_spaces (infile);
251      if (c == EOF)
252	break;
253      ungetc (c, infile);
254
255      desc = read_rtx (infile);
256      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
257	gen_insn (desc);
258    }
259
260  /* Print out the prototypes now.  */
261  dummy = (rtx)0;
262  obstack_grow (&call_obstack, &dummy, sizeof (rtx));
263  call_insns = (rtx *) obstack_finish (&call_obstack);
264
265  obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
266  normal_insns = (rtx *) obstack_finish (&normal_obstack);
267
268  printf ("\n#ifndef NO_MD_PROTOTYPES\n");
269  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
270    gen_proto (*insn_ptr);
271
272  printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
273  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
274    gen_proto (*insn_ptr);
275
276  printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
277  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
278    gen_nonproto (*insn_ptr);
279
280  printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
281  printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
282  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
283    gen_nonproto (*insn_ptr);
284
285  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
286    gen_nonproto (*insn_ptr);
287
288  printf ("#endif  /* NO_MD_PROTOTYPES */\n");
289
290  fflush (stdout);
291  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
292  /* NOTREACHED */
293  return 0;
294}
295