genflags.c revision 18334
117680Spst/* Generate from machine description:
217680Spst
317680Spst   - some flags HAVE_... saying which simple standard instructions are
417680Spst   available for this machine.
517680Spst   Copyright (C) 1987, 1991, 1995 Free Software Foundation, Inc.
617680Spst
717680SpstThis file is part of GNU CC.
817680Spst
917680SpstGNU CC is free software; you can redistribute it and/or modify
1017680Spstit under the terms of the GNU General Public License as published by
1117680Spstthe Free Software Foundation; either version 2, or (at your option)
1217680Spstany later version.
1317680Spst
1417680SpstGNU CC is distributed in the hope that it will be useful,
1517680Spstbut WITHOUT ANY WARRANTY; without even the implied warranty of
1617680SpstMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1717680SpstGNU General Public License for more details.
1817680Spst
1917680SpstYou should have received a copy of the GNU General Public License
2017680Spstalong with GNU CC; see the file COPYING.  If not, write to
2117680Spstthe Free Software Foundation, 59 Temple Place - Suite 330,
2217680SpstBoston, MA 02111-1307, USA.  */
2317680Spst
2417680Spst
2517680Spst#include <stdio.h>
2617680Spst#include "hconfig.h"
2717680Spst#include "rtl.h"
2817680Spst#include "obstack.h"
2917680Spst
3017680Spststatic struct obstack obstack;
3117680Spststruct obstack *rtl_obstack = &obstack;
3217680Spst
3317680Spst#define obstack_chunk_alloc xmalloc
3417680Spst#define obstack_chunk_free free
3517680Spst
3617680Spstextern void free ();
3717680Spstextern rtx read_rtx ();
3821262Swollman
3917680Spstchar *xmalloc ();
4017680Spststatic void fatal ();
4117680Spstvoid fancy_abort ();
4217680Spst
4317680Spst/* Names for patterns.  Need to allow linking with print-rtl.  */
4417680Spstchar **insn_name_ptr;
4517680Spst
4617680Spst/* Obstacks to remember normal, and call insns.  */
4717680Spststatic struct obstack call_obstack, normal_obstack;
4817680Spst
4917680Spst/* Max size of names encountered.  */
5017680Spststatic int max_id_len;
5117680Spst
5217680Spst/* Count the number of match_operand's found.  */
5317680Spststatic int
5417680Spstnum_operands (x)
5517680Spst     rtx x;
5617680Spst{
5717680Spst  int count = 0;
5817680Spst  int i, j;
5917680Spst  enum rtx_code code = GET_CODE (x);
6017680Spst  char *format_ptr = GET_RTX_FORMAT (code);
6117680Spst
6217680Spst  if (code == MATCH_OPERAND)
6317680Spst    return 1;
6417680Spst
6517680Spst  if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
6617680Spst    count++;
6717680Spst
6817680Spst  for (i = 0; i < GET_RTX_LENGTH (code); i++)
6917680Spst    {
7017680Spst      switch (*format_ptr++)
7117680Spst	{
7217680Spst	case 'u':
7317680Spst	case 'e':
7417680Spst	  count += num_operands (XEXP (x, i));
7517680Spst	  break;
7617680Spst
7717680Spst	case 'E':
7817680Spst	  if (XVEC (x, i) != NULL)
7917680Spst	    for (j = 0; j < XVECLEN (x, i); j++)
8017680Spst	      count += num_operands (XVECEXP (x, i, j));
8117680Spst
8217680Spst	  break;
8317680Spst	}
8417680Spst    }
8517680Spst
8617680Spst  return count;
8717680Spst}
8817680Spst
8917680Spst/* Print out prototype information for a function.  */
9017680Spststatic void
9117680Spstgen_proto (insn)
9217680Spst     rtx insn;
9317680Spst{
9417680Spst  int num = num_operands (insn);
9517680Spst  printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0));
9617680Spst
9717680Spst  if (num == 0)
9817680Spst    printf ("void");
9917680Spst  else
10017680Spst    {
10117680Spst      while (num-- > 1)
10217680Spst	printf ("rtx, ");
10317680Spst
10417680Spst      printf ("rtx");
10517680Spst    }
10617680Spst
10717680Spst  printf ("));\n");
10817680Spst}
10917680Spst
11017680Spst/* Print out a function declaration without a prototype.  */
11117680Spststatic void
11217680Spstgen_nonproto (insn)
11317680Spst     rtx insn;
11417680Spst{
11517680Spst  printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
11617680Spst}
11717680Spst
11817680Spststatic void
11917680Spstgen_insn (insn)
12017680Spst     rtx insn;
12117680Spst{
12217680Spst  char *name = XSTR (insn, 0);
12317680Spst  char *p;
12417680Spst  struct obstack *obstack_ptr;
12517680Spst  int len;
12617680Spst
12717680Spst  /* Don't mention instructions whose names are the null string
12817680Spst     or begin with '*'.  They are in the machine description just
12917680Spst     to be recognized.  */
13017680Spst  if (name[0] == 0 || name[0] == '*')
13117680Spst    return;
13217680Spst
13317680Spst  len = strlen (name);
13417680Spst
13517680Spst  if (len > max_id_len)
13617680Spst    max_id_len = len;
13717680Spst
13817680Spst  printf ("#define HAVE_%s ", name);
13917680Spst  if (strlen (XSTR (insn, 2)) == 0)
14017680Spst    printf ("1\n");
14117680Spst  else
14217680Spst    {
14317680Spst      /* Write the macro definition, putting \'s at the end of each line,
14417680Spst	 if more than one.  */
14517680Spst      printf ("(");
14617680Spst      for (p = XSTR (insn, 2); *p; p++)
14717680Spst	{
14817680Spst	  if (*p == '\n')
14917680Spst	    printf (" \\\n");
15017680Spst	  else
15117680Spst	    printf ("%c", *p);
15217680Spst	}
15317680Spst      printf (")\n");
15417680Spst    }
15517680Spst
15617680Spst  /* Save the current insn, so that we can later put out appropriate
15717680Spst     prototypes.  At present, most md files have the wrong number of
15817680Spst     arguments for the call insns (call, call_value, call_pop,
15917680Spst     call_value_pop) ignoring the extra arguments that are passed for
16017680Spst     some machines, so by default, turn off the prototype.  */
16117680Spst
16217680Spst  obstack_ptr = (name[0] == 'c'
16317680Spst		 && (!strcmp (name, "call")
16417680Spst		     || !strcmp (name, "call_value")
16517680Spst		     || !strcmp (name, "call_pop")
16617680Spst		     || !strcmp (name, "call_value_pop")))
16717680Spst    ? &call_obstack : &normal_obstack;
16817680Spst
16917680Spst  obstack_grow (obstack_ptr, &insn, sizeof (rtx));
17017680Spst}
17117680Spst
17217680Spstchar *
17317680Spstxmalloc (size)
17417680Spst     unsigned size;
17517680Spst{
17617680Spst  register char *val = (char *) malloc (size);
17717680Spst
17817680Spst  if (val == 0)
17917680Spst    fatal ("virtual memory exhausted");
18017680Spst
18117680Spst  return val;
18217680Spst}
18317680Spst
18417680Spstchar *
18517680Spstxrealloc (ptr, size)
18617680Spst     char *ptr;
18717680Spst     unsigned size;
18817680Spst{
18917680Spst  char *result = (char *) realloc (ptr, size);
19017680Spst  if (!result)
19117680Spst    fatal ("virtual memory exhausted");
19217680Spst  return result;
19317680Spst}
19417680Spst
19517680Spststatic void
19617680Spstfatal (s, a1, a2)
19717680Spst     char *s;
19817680Spst{
19917680Spst  fprintf (stderr, "genflags: ");
20017680Spst  fprintf (stderr, s, a1, a2);
20117680Spst  fprintf (stderr, "\n");
20217680Spst  exit (FATAL_EXIT_CODE);
20317680Spst}
20417680Spst
20517680Spst/* More 'friendly' abort that prints the line and file.
20617680Spst   config.h can #define abort fancy_abort if you like that sort of thing.  */
20717680Spst
20817680Spstvoid
20917680Spstfancy_abort ()
21017680Spst{
21117680Spst  fatal ("Internal gcc abort.");
21217680Spst}
21317680Spst
21417680Spstint
21517680Spstmain (argc, argv)
21617680Spst     int argc;
21717680Spst     char **argv;
21817680Spst{
21917680Spst  rtx desc;
22017680Spst  rtx dummy;
22117680Spst  rtx *call_insns;
22217680Spst  rtx *normal_insns;
22317680Spst  rtx *insn_ptr;
22417680Spst  FILE *infile;
22517680Spst  register int c;
22617680Spst
22717680Spst  obstack_init (rtl_obstack);
22817680Spst  obstack_init (&call_obstack);
22917680Spst  obstack_init (&normal_obstack);
23017680Spst
23117680Spst  if (argc <= 1)
23217680Spst    fatal ("No input file name.");
23317680Spst
23417680Spst  infile = fopen (argv[1], "r");
23517680Spst  if (infile == 0)
23617680Spst    {
23717680Spst      perror (argv[1]);
23817680Spst      exit (FATAL_EXIT_CODE);
23917680Spst    }
24017680Spst
24117680Spst  init_rtl ();
24217680Spst
24317680Spst  printf ("/* Generated automatically by the program `genflags'\n\
24417680Spstfrom the machine description file `md'.  */\n\n");
24517680Spst
24617680Spst  /* Read the machine description.  */
24717680Spst
24817680Spst  while (1)
24917680Spst    {
25017680Spst      c = read_skip_spaces (infile);
25117680Spst      if (c == EOF)
25217680Spst	break;
25317680Spst      ungetc (c, infile);
25417680Spst
25517680Spst      desc = read_rtx (infile);
25617680Spst      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
25717680Spst	gen_insn (desc);
25817680Spst    }
25917680Spst
26017680Spst  /* Print out the prototypes now.  */
26117680Spst  dummy = (rtx)0;
26217680Spst  obstack_grow (&call_obstack, &dummy, sizeof (rtx));
26317680Spst  call_insns = (rtx *) obstack_finish (&call_obstack);
26417680Spst
26517680Spst  obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
26617680Spst  normal_insns = (rtx *) obstack_finish (&normal_obstack);
26717680Spst
26817680Spst  printf ("\n#ifndef NO_MD_PROTOTYPES\n");
26917680Spst  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
27017680Spst    gen_proto (*insn_ptr);
27117680Spst
27217680Spst  printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
27317680Spst  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
27417680Spst    gen_proto (*insn_ptr);
27517680Spst
27617680Spst  printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
27717680Spst  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
27817680Spst    gen_nonproto (*insn_ptr);
27917680Spst
28017680Spst  printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
28117680Spst  printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
28217680Spst  for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
28317680Spst    gen_nonproto (*insn_ptr);
28417680Spst
28517680Spst  for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
28617680Spst    gen_nonproto (*insn_ptr);
28717680Spst
28817680Spst  printf ("#endif  /* NO_MD_PROTOTYPES */\n");
28917680Spst
29017680Spst  fflush (stdout);
29117680Spst  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
29217680Spst  /* NOTREACHED */
29317680Spst  return 0;
29417680Spst}
29517680Spst