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