genflags.c revision 132718
118334Speter/* Generate from machine description:
218334Speter   - some flags HAVE_... saying which simple standard instructions are
318334Speter   available for this machine.
490075Sobrien   Copyright (C) 1987, 1991, 1995, 1998,
5132718Skan   1999, 2000, 2003, 2004 Free Software Foundation, Inc.
618334Speter
790075SobrienThis file is part of GCC.
818334Speter
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1318334Speter
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1818334Speter
1918334SpeterYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
2190075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2290075Sobrien02111-1307, USA.  */
2318334Speter
2418334Speter
25132718Skan#include "bconfig.h"
2650397Sobrien#include "system.h"
27132718Skan#include "coretypes.h"
28132718Skan#include "tm.h"
2918334Speter#include "rtl.h"
3018334Speter#include "obstack.h"
3190075Sobrien#include "errors.h"
3290075Sobrien#include "gensupport.h"
3318334Speter
3490075Sobrien/* Obstack to remember insns with.  */
3590075Sobrienstatic struct obstack obstack;
3618334Speter
3718334Speter/* Max size of names encountered.  */
3818334Speterstatic int max_id_len;
3918334Speter
4090075Sobrien/* Max operand encountered in a scan over some insn.  */
4190075Sobrienstatic int max_opno;
4250397Sobrien
43132718Skanstatic void max_operand_1 (rtx);
44132718Skanstatic int num_operands (rtx);
45132718Skanstatic void gen_proto (rtx);
46132718Skanstatic void gen_macro (const char *, int, int);
47132718Skanstatic void gen_insn (rtx);
4850397Sobrien
4918334Speter/* Count the number of match_operand's found.  */
5050397Sobrien
5190075Sobrienstatic void
52132718Skanmax_operand_1 (rtx x)
5318334Speter{
5490075Sobrien  RTX_CODE code;
5590075Sobrien  int i;
5690075Sobrien  int len;
5790075Sobrien  const char *fmt;
5818334Speter
5990075Sobrien  if (x == 0)
6090075Sobrien    return;
6118334Speter
6290075Sobrien  code = GET_CODE (x);
6318334Speter
6490075Sobrien  if (code == MATCH_OPERAND || code == MATCH_OPERATOR
6590075Sobrien      || code == MATCH_PARALLEL)
6690075Sobrien    max_opno = MAX (max_opno, XINT (x, 0));
6790075Sobrien
6890075Sobrien  fmt = GET_RTX_FORMAT (code);
6990075Sobrien  len = GET_RTX_LENGTH (code);
7090075Sobrien  for (i = 0; i < len; i++)
7118334Speter    {
7290075Sobrien      if (fmt[i] == 'e' || fmt[i] == 'u')
7390075Sobrien	max_operand_1 (XEXP (x, i));
7490075Sobrien      else if (fmt[i] == 'E')
7518334Speter	{
7690075Sobrien	  int j;
7790075Sobrien	  for (j = 0; j < XVECLEN (x, i); j++)
7890075Sobrien	    max_operand_1 (XVECEXP (x, i, j));
7918334Speter	}
8018334Speter    }
8190075Sobrien}
8218334Speter
8390075Sobrienstatic int
84132718Skannum_operands (rtx insn)
8590075Sobrien{
8690075Sobrien  int len = XVECLEN (insn, 1);
8790075Sobrien  int i;
8890075Sobrien
8990075Sobrien  max_opno = -1;
9090075Sobrien
9190075Sobrien  for (i = 0; i < len; i++)
9290075Sobrien    max_operand_1 (XVECEXP (insn, 1, i));
9390075Sobrien
9490075Sobrien  return max_opno + 1;
9518334Speter}
9618334Speter
9790075Sobrien/* Print out a wrapper macro for a function which corrects the number
9890075Sobrien   of arguments it takes.  Any missing arguments are assumed to be at
9990075Sobrien   the end.  */
10090075Sobrienstatic void
101132718Skangen_macro (const char *name, int real, int expect)
10290075Sobrien{
10390075Sobrien  int i;
10490075Sobrien
10590075Sobrien  if (real > expect)
10690075Sobrien    abort ();
10790075Sobrien  if (real == 0)
10890075Sobrien    abort ();
10990075Sobrien
11090075Sobrien  /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
11190075Sobrien  fputs ("#define GEN_", stdout);
11290075Sobrien  for (i = 0; name[i]; i++)
11390075Sobrien    putchar (TOUPPER (name[i]));
11490075Sobrien
11590075Sobrien  putchar('(');
11690075Sobrien  for (i = 0; i < expect - 1; i++)
11790075Sobrien    printf ("%c, ", i + 'A');
11890075Sobrien  printf ("%c) gen_%s (", i + 'A', name);
11990075Sobrien
12090075Sobrien  for (i = 0; i < real - 1; i++)
12190075Sobrien    printf ("(%c), ", i + 'A');
12290075Sobrien  printf ("(%c))\n", i + 'A');
12390075Sobrien}
12490075Sobrien
125117395Skan/* Print out prototype information for a generator function.  If the
126117395Skan   insn pattern has been elided, print out a dummy generator that
127117395Skan   does nothing.  */
12850397Sobrien
12918334Speterstatic void
130132718Skangen_proto (rtx insn)
13118334Speter{
13218334Speter  int num = num_operands (insn);
133117395Skan  int i;
13490075Sobrien  const char *name = XSTR (insn, 0);
135117395Skan  int truth = maybe_eval_c_test (XSTR (insn, 2));
13618334Speter
13790075Sobrien  /* Many md files don't refer to the last two operands passed to the
13890075Sobrien     call patterns.  This means their generator functions will be two
13990075Sobrien     arguments too short.  Instead of changing every md file to touch
14090075Sobrien     those operands, we wrap the prototypes in macros that take the
14190075Sobrien     correct number of arguments.  */
14290075Sobrien  if (name[0] == 'c' || name[0] == 's')
14390075Sobrien    {
14490075Sobrien      if (!strcmp (name, "call")
14590075Sobrien	  || !strcmp (name, "call_pop")
14690075Sobrien	  || !strcmp (name, "sibcall")
14790075Sobrien	  || !strcmp (name, "sibcall_pop"))
14890075Sobrien	gen_macro (name, num, 4);
14990075Sobrien      else if (!strcmp (name, "call_value")
15090075Sobrien	       || !strcmp (name, "call_value_pop")
15190075Sobrien	       || !strcmp (name, "sibcall_value")
15290075Sobrien	       || !strcmp (name, "sibcall_value_pop"))
15390075Sobrien	gen_macro (name, num, 5);
15490075Sobrien    }
15590075Sobrien
156117395Skan  if (truth != 0)
157132718Skan    printf ("extern rtx        gen_%-*s (", max_id_len, name);
158117395Skan  else
159132718Skan    printf ("static inline rtx gen_%-*s (", max_id_len, name);
16090075Sobrien
16118334Speter  if (num == 0)
162117395Skan    fputs ("void", stdout);
16318334Speter  else
16418334Speter    {
165117395Skan      for (i = 1; i < num; i++)
166117395Skan	fputs ("rtx, ", stdout);
167132718Skan
168117395Skan      fputs ("rtx", stdout);
169117395Skan    }
17018334Speter
171132718Skan  puts (");");
172117395Skan
173117395Skan  /* Some back ends want to take the address of generator functions,
174117395Skan     so we cannot simply use #define for these dummy definitions.  */
175117395Skan  if (truth == 0)
176117395Skan    {
177117395Skan      printf ("static inline rtx\ngen_%s", name);
178117395Skan      if (num > 0)
179117395Skan	{
180117395Skan	  putchar ('(');
181117395Skan	  for (i = 0; i < num-1; i++)
182132718Skan	    printf ("rtx %c ATTRIBUTE_UNUSED, ", 'a' + i);
183132718Skan	  printf ("rtx %c ATTRIBUTE_UNUSED)\n", 'a' + i);
184117395Skan	}
185117395Skan      else
186132718Skan	puts ("(void)");
187117395Skan      puts ("{\n  return 0;\n}");
18818334Speter    }
18918334Speter
19018334Speter}
19118334Speter
19218334Speterstatic void
193132718Skangen_insn (rtx insn)
19418334Speter{
19590075Sobrien  const char *name = XSTR (insn, 0);
19690075Sobrien  const char *p;
19718334Speter  int len;
198117395Skan  int truth = maybe_eval_c_test (XSTR (insn, 2));
19918334Speter
20018334Speter  /* Don't mention instructions whose names are the null string
20118334Speter     or begin with '*'.  They are in the machine description just
20218334Speter     to be recognized.  */
20318334Speter  if (name[0] == 0 || name[0] == '*')
20418334Speter    return;
20518334Speter
20618334Speter  len = strlen (name);
20718334Speter
20818334Speter  if (len > max_id_len)
20918334Speter    max_id_len = len;
21018334Speter
211117395Skan  if (truth == 0)
212132718Skan    /* Emit nothing.  */;
213117395Skan  else if (truth == 1)
214117395Skan    printf ("#define HAVE_%s 1\n", name);
21518334Speter  else
21618334Speter    {
21718334Speter      /* Write the macro definition, putting \'s at the end of each line,
21818334Speter	 if more than one.  */
219117395Skan      printf ("#define HAVE_%s (", name);
22018334Speter      for (p = XSTR (insn, 2); *p; p++)
22118334Speter	{
22296263Sobrien	  if (IS_VSPACE (*p))
223117395Skan	    fputs (" \\\n", stdout);
22418334Speter	  else
225117395Skan	    putchar (*p);
22618334Speter	}
227117395Skan      fputs (")\n", stdout);
22818334Speter    }
22918334Speter
23090075Sobrien  obstack_grow (&obstack, &insn, sizeof (rtx));
23118334Speter}
23218334Speter
23318334Speterint
234132718Skanmain (int argc, char **argv)
23518334Speter{
23618334Speter  rtx desc;
23718334Speter  rtx dummy;
23890075Sobrien  rtx *insns;
23918334Speter  rtx *insn_ptr;
24018334Speter
24190075Sobrien  progname = "genflags";
24290075Sobrien  obstack_init (&obstack);
24318334Speter
244117395Skan  /* We need to see all the possibilities.  Elided insns may have
245117395Skan     direct calls to their generators in C code.  */
246117395Skan  insn_elision = 0;
247117395Skan
24818334Speter  if (argc <= 1)
24990075Sobrien    fatal ("no input file name");
25018334Speter
25190075Sobrien  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
25290075Sobrien    return (FATAL_EXIT_CODE);
253132718Skan
25490075Sobrien  puts ("/* Generated automatically by the program `genflags'");
25590075Sobrien  puts ("   from the machine description file `md'.  */\n");
25690075Sobrien  puts ("#ifndef GCC_INSN_FLAGS_H");
25790075Sobrien  puts ("#define GCC_INSN_FLAGS_H\n");
25818334Speter
25918334Speter  /* Read the machine description.  */
26018334Speter
26118334Speter  while (1)
26218334Speter    {
26390075Sobrien      int line_no, insn_code_number = 0;
26490075Sobrien
26590075Sobrien      desc = read_md_rtx (&line_no, &insn_code_number);
26690075Sobrien      if (desc == NULL)
26718334Speter	break;
26818334Speter      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
26918334Speter	gen_insn (desc);
27018334Speter    }
27118334Speter
27218334Speter  /* Print out the prototypes now.  */
27350397Sobrien  dummy = (rtx) 0;
27490075Sobrien  obstack_grow (&obstack, &dummy, sizeof (rtx));
27590075Sobrien  insns = (rtx *) obstack_finish (&obstack);
27618334Speter
27790075Sobrien  for (insn_ptr = insns; *insn_ptr; insn_ptr++)
27818334Speter    gen_proto (*insn_ptr);
27918334Speter
28090075Sobrien  puts("\n#endif /* GCC_INSN_FLAGS_H */");
28118334Speter
28290075Sobrien  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
28390075Sobrien    return FATAL_EXIT_CODE;
28418334Speter
28590075Sobrien  return SUCCESS_EXIT_CODE;
28690075Sobrien}
28718334Speter
28890075Sobrien/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
28990075Sobrienconst char *
290132718Skanget_insn_name (int code ATTRIBUTE_UNUSED)
29190075Sobrien{
29290075Sobrien  return NULL;
29318334Speter}
294