xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/genflags.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Generate from machine description:
21debfc3dSmrg    - some flags HAVE_... saying which simple standard instructions are
31debfc3dSmrg    available for this machine.
4*8feb0f0bSmrg    Copyright (C) 1987-2020 Free Software Foundation, Inc.
51debfc3dSmrg 
61debfc3dSmrg This file is part of GCC.
71debfc3dSmrg 
81debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
91debfc3dSmrg the terms of the GNU General Public License as published by the Free
101debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
111debfc3dSmrg version.
121debfc3dSmrg 
131debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
141debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
151debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
161debfc3dSmrg for more details.
171debfc3dSmrg 
181debfc3dSmrg You should have received a copy of the GNU General Public License
191debfc3dSmrg along with GCC; see the file COPYING3.  If not see
201debfc3dSmrg <http://www.gnu.org/licenses/>.  */
211debfc3dSmrg 
221debfc3dSmrg 
231debfc3dSmrg #include "bconfig.h"
241debfc3dSmrg #include "system.h"
251debfc3dSmrg #include "coretypes.h"
261debfc3dSmrg #include "tm.h"
271debfc3dSmrg #include "rtl.h"
281debfc3dSmrg #include "obstack.h"
291debfc3dSmrg #include "errors.h"
301debfc3dSmrg #include "read-md.h"
311debfc3dSmrg #include "gensupport.h"
321debfc3dSmrg 
331debfc3dSmrg /* Obstack to remember insns with.  */
341debfc3dSmrg static struct obstack obstack;
351debfc3dSmrg 
361debfc3dSmrg /* Max size of names encountered.  */
371debfc3dSmrg static int max_id_len;
381debfc3dSmrg 
391debfc3dSmrg /* Max operand encountered in a scan over some insn.  */
401debfc3dSmrg static int max_opno;
411debfc3dSmrg 
421debfc3dSmrg static void max_operand_1 (rtx);
431debfc3dSmrg static int num_operands (rtx);
441debfc3dSmrg static void gen_proto (rtx);
451debfc3dSmrg 
461debfc3dSmrg /* Count the number of match_operand's found.  */
471debfc3dSmrg 
481debfc3dSmrg static void
max_operand_1(rtx x)491debfc3dSmrg max_operand_1 (rtx x)
501debfc3dSmrg {
511debfc3dSmrg   RTX_CODE code;
521debfc3dSmrg   int i;
531debfc3dSmrg   int len;
541debfc3dSmrg   const char *fmt;
551debfc3dSmrg 
561debfc3dSmrg   if (x == 0)
571debfc3dSmrg     return;
581debfc3dSmrg 
591debfc3dSmrg   code = GET_CODE (x);
601debfc3dSmrg 
611debfc3dSmrg   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
621debfc3dSmrg       || code == MATCH_PARALLEL)
631debfc3dSmrg     max_opno = MAX (max_opno, XINT (x, 0));
641debfc3dSmrg 
651debfc3dSmrg   fmt = GET_RTX_FORMAT (code);
661debfc3dSmrg   len = GET_RTX_LENGTH (code);
671debfc3dSmrg   for (i = 0; i < len; i++)
681debfc3dSmrg     {
691debfc3dSmrg       if (fmt[i] == 'e' || fmt[i] == 'u')
701debfc3dSmrg 	max_operand_1 (XEXP (x, i));
711debfc3dSmrg       else if (fmt[i] == 'E')
721debfc3dSmrg 	{
731debfc3dSmrg 	  int j;
741debfc3dSmrg 	  for (j = 0; j < XVECLEN (x, i); j++)
751debfc3dSmrg 	    max_operand_1 (XVECEXP (x, i, j));
761debfc3dSmrg 	}
771debfc3dSmrg     }
781debfc3dSmrg }
791debfc3dSmrg 
801debfc3dSmrg static int
num_operands(rtx insn)811debfc3dSmrg num_operands (rtx insn)
821debfc3dSmrg {
831debfc3dSmrg   int len = XVECLEN (insn, 1);
841debfc3dSmrg   int i;
851debfc3dSmrg 
861debfc3dSmrg   max_opno = -1;
871debfc3dSmrg 
881debfc3dSmrg   for (i = 0; i < len; i++)
891debfc3dSmrg     max_operand_1 (XVECEXP (insn, 1, i));
901debfc3dSmrg 
911debfc3dSmrg   return max_opno + 1;
921debfc3dSmrg }
931debfc3dSmrg 
941debfc3dSmrg /* Print out prototype information for a generator function.  If the
951debfc3dSmrg    insn pattern has been elided, print out a dummy generator that
961debfc3dSmrg    does nothing.  */
971debfc3dSmrg 
981debfc3dSmrg static void
gen_proto(rtx insn)991debfc3dSmrg gen_proto (rtx insn)
1001debfc3dSmrg {
1011debfc3dSmrg   int num = num_operands (insn);
1021debfc3dSmrg   int i;
1031debfc3dSmrg   const char *name = XSTR (insn, 0);
1041debfc3dSmrg   int truth = maybe_eval_c_test (XSTR (insn, 2));
1051debfc3dSmrg 
1061debfc3dSmrg   if (truth != 0)
1071debfc3dSmrg     printf ("extern rtx        gen_%-*s (", max_id_len, name);
1081debfc3dSmrg   else
1091debfc3dSmrg     printf ("static inline rtx gen_%-*s (", max_id_len, name);
1101debfc3dSmrg 
1111debfc3dSmrg   if (num == 0)
1121debfc3dSmrg     fputs ("void", stdout);
1131debfc3dSmrg   else
1141debfc3dSmrg     {
1151debfc3dSmrg       for (i = 1; i < num; i++)
1161debfc3dSmrg 	fputs ("rtx, ", stdout);
1171debfc3dSmrg 
1181debfc3dSmrg       fputs ("rtx", stdout);
1191debfc3dSmrg     }
1201debfc3dSmrg 
1211debfc3dSmrg   puts (");");
1221debfc3dSmrg 
1231debfc3dSmrg   /* Some back ends want to take the address of generator functions,
1241debfc3dSmrg      so we cannot simply use #define for these dummy definitions.  */
1251debfc3dSmrg   if (truth == 0)
1261debfc3dSmrg     {
1271debfc3dSmrg       printf ("static inline rtx\ngen_%s", name);
1281debfc3dSmrg       if (num > 0)
1291debfc3dSmrg 	{
1301debfc3dSmrg 	  putchar ('(');
1311debfc3dSmrg 	  for (i = 0; i < num-1; i++)
1321debfc3dSmrg 	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
1331debfc3dSmrg 	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
1341debfc3dSmrg 	}
1351debfc3dSmrg       else
1361debfc3dSmrg 	puts ("(void)");
1371debfc3dSmrg       puts ("{\n  return 0;\n}");
1381debfc3dSmrg     }
1391debfc3dSmrg 
1401debfc3dSmrg }
1411debfc3dSmrg 
1421debfc3dSmrg static void
gen_insn(md_rtx_info * info)1431debfc3dSmrg gen_insn (md_rtx_info *info)
1441debfc3dSmrg {
1451debfc3dSmrg   rtx insn = info->def;
1461debfc3dSmrg   const char *name = XSTR (insn, 0);
1471debfc3dSmrg   const char *p;
1481debfc3dSmrg   const char *lt, *gt;
1491debfc3dSmrg   int len;
1501debfc3dSmrg   int truth = maybe_eval_c_test (XSTR (insn, 2));
1511debfc3dSmrg 
1521debfc3dSmrg   lt = strchr (name, '<');
1531debfc3dSmrg   if (lt && strchr (lt + 1, '>'))
1541debfc3dSmrg     {
1551debfc3dSmrg       error_at (info->loc, "unresolved iterator");
1561debfc3dSmrg       return;
1571debfc3dSmrg     }
1581debfc3dSmrg 
1591debfc3dSmrg   gt = strchr (name, '>');
1601debfc3dSmrg   if (lt || gt)
1611debfc3dSmrg     {
1621debfc3dSmrg       error_at (info->loc, "unmatched angle brackets, likely "
1631debfc3dSmrg 		"an error in iterator syntax");
1641debfc3dSmrg       return;
1651debfc3dSmrg     }
1661debfc3dSmrg 
1671debfc3dSmrg   /* Don't mention instructions whose names are the null string
1681debfc3dSmrg      or begin with '*'.  They are in the machine description just
1691debfc3dSmrg      to be recognized.  */
1701debfc3dSmrg   if (name[0] == 0 || name[0] == '*')
1711debfc3dSmrg     return;
1721debfc3dSmrg 
1731debfc3dSmrg   len = strlen (name);
1741debfc3dSmrg 
1751debfc3dSmrg   if (len > max_id_len)
1761debfc3dSmrg     max_id_len = len;
1771debfc3dSmrg 
1781debfc3dSmrg   if (truth == 0)
1791debfc3dSmrg     /* Emit nothing.  */;
1801debfc3dSmrg   else if (truth == 1)
1811debfc3dSmrg     printf ("#define HAVE_%s 1\n", name);
1821debfc3dSmrg   else
1831debfc3dSmrg     {
1841debfc3dSmrg       /* Write the macro definition, putting \'s at the end of each line,
1851debfc3dSmrg 	 if more than one.  */
1861debfc3dSmrg       printf ("#define HAVE_%s (", name);
1871debfc3dSmrg       for (p = XSTR (insn, 2); *p; p++)
1881debfc3dSmrg 	{
1891debfc3dSmrg 	  if (IS_VSPACE (*p))
1901debfc3dSmrg 	    fputs (" \\\n", stdout);
1911debfc3dSmrg 	  else
1921debfc3dSmrg 	    putchar (*p);
1931debfc3dSmrg 	}
1941debfc3dSmrg       fputs (")\n", stdout);
1951debfc3dSmrg     }
1961debfc3dSmrg 
1971debfc3dSmrg   obstack_grow (&obstack, &insn, sizeof (rtx));
1981debfc3dSmrg }
1991debfc3dSmrg 
2001debfc3dSmrg int
main(int argc,const char ** argv)2011debfc3dSmrg main (int argc, const char **argv)
2021debfc3dSmrg {
2031debfc3dSmrg   rtx dummy;
2041debfc3dSmrg   rtx *insns;
2051debfc3dSmrg   rtx *insn_ptr;
2061debfc3dSmrg 
2071debfc3dSmrg   progname = "genflags";
2081debfc3dSmrg   obstack_init (&obstack);
2091debfc3dSmrg 
2101debfc3dSmrg   /* We need to see all the possibilities.  Elided insns may have
2111debfc3dSmrg      direct calls to their generators in C code.  */
2121debfc3dSmrg   insn_elision = 0;
2131debfc3dSmrg 
2141debfc3dSmrg   if (!init_rtx_reader_args (argc, argv))
2151debfc3dSmrg     return (FATAL_EXIT_CODE);
2161debfc3dSmrg 
2171debfc3dSmrg   puts ("/* Generated automatically by the program `genflags'");
2181debfc3dSmrg   puts ("   from the machine description file `md'.  */\n");
2191debfc3dSmrg   puts ("#ifndef GCC_INSN_FLAGS_H");
2201debfc3dSmrg   puts ("#define GCC_INSN_FLAGS_H\n");
2211debfc3dSmrg 
2221debfc3dSmrg   /* Read the machine description.  */
2231debfc3dSmrg 
2241debfc3dSmrg   md_rtx_info info;
2251debfc3dSmrg   while (read_md_rtx (&info))
2261debfc3dSmrg     switch (GET_CODE (info.def))
2271debfc3dSmrg       {
2281debfc3dSmrg       case DEFINE_INSN:
2291debfc3dSmrg       case DEFINE_EXPAND:
2301debfc3dSmrg 	gen_insn (&info);
2311debfc3dSmrg 	break;
2321debfc3dSmrg 
2331debfc3dSmrg       default:
2341debfc3dSmrg 	break;
2351debfc3dSmrg       }
2361debfc3dSmrg 
2371debfc3dSmrg   /* Print out the prototypes now.  */
2381debfc3dSmrg   dummy = (rtx) 0;
2391debfc3dSmrg   obstack_grow (&obstack, &dummy, sizeof (rtx));
2401debfc3dSmrg   insns = XOBFINISH (&obstack, rtx *);
2411debfc3dSmrg 
2421debfc3dSmrg   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
2431debfc3dSmrg     gen_proto (*insn_ptr);
2441debfc3dSmrg 
2451debfc3dSmrg   puts ("\n#endif /* GCC_INSN_FLAGS_H */");
2461debfc3dSmrg 
2471debfc3dSmrg   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
2481debfc3dSmrg     return FATAL_EXIT_CODE;
2491debfc3dSmrg 
2501debfc3dSmrg   return SUCCESS_EXIT_CODE;
2511debfc3dSmrg }
252