xref: /netbsd/external/gpl3/gcc/dist/gcc/genflags.c (revision dd083157)
1c3d31fe1Smrg /* Generate from machine description:
2c3d31fe1Smrg    - some flags HAVE_... saying which simple standard instructions are
3c3d31fe1Smrg    available for this machine.
4*dd083157Smrg    Copyright (C) 1987-2020 Free Software Foundation, Inc.
5c3d31fe1Smrg 
6c3d31fe1Smrg This file is part of GCC.
7c3d31fe1Smrg 
8c3d31fe1Smrg GCC is free software; you can redistribute it and/or modify it under
9c3d31fe1Smrg the terms of the GNU General Public License as published by the Free
10c3d31fe1Smrg Software Foundation; either version 3, or (at your option) any later
11c3d31fe1Smrg version.
12c3d31fe1Smrg 
13c3d31fe1Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14c3d31fe1Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
15c3d31fe1Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16c3d31fe1Smrg for more details.
17c3d31fe1Smrg 
18c3d31fe1Smrg You should have received a copy of the GNU General Public License
19c3d31fe1Smrg along with GCC; see the file COPYING3.  If not see
20c3d31fe1Smrg <http://www.gnu.org/licenses/>.  */
21c3d31fe1Smrg 
22c3d31fe1Smrg 
23c3d31fe1Smrg #include "bconfig.h"
24c3d31fe1Smrg #include "system.h"
25c3d31fe1Smrg #include "coretypes.h"
26c3d31fe1Smrg #include "tm.h"
27c3d31fe1Smrg #include "rtl.h"
28c3d31fe1Smrg #include "obstack.h"
29c3d31fe1Smrg #include "errors.h"
30af526226Smrg #include "read-md.h"
31c3d31fe1Smrg #include "gensupport.h"
32c3d31fe1Smrg 
33c3d31fe1Smrg /* Obstack to remember insns with.  */
34c3d31fe1Smrg static struct obstack obstack;
35c3d31fe1Smrg 
36c3d31fe1Smrg /* Max size of names encountered.  */
37c3d31fe1Smrg static int max_id_len;
38c3d31fe1Smrg 
39c3d31fe1Smrg /* Max operand encountered in a scan over some insn.  */
40c3d31fe1Smrg static int max_opno;
41c3d31fe1Smrg 
42c3d31fe1Smrg static void max_operand_1 (rtx);
43c3d31fe1Smrg static int num_operands (rtx);
44c3d31fe1Smrg static void gen_proto (rtx);
45c3d31fe1Smrg 
46c3d31fe1Smrg /* Count the number of match_operand's found.  */
47c3d31fe1Smrg 
48c3d31fe1Smrg static void
max_operand_1(rtx x)49c3d31fe1Smrg max_operand_1 (rtx x)
50c3d31fe1Smrg {
51c3d31fe1Smrg   RTX_CODE code;
52c3d31fe1Smrg   int i;
53c3d31fe1Smrg   int len;
54c3d31fe1Smrg   const char *fmt;
55c3d31fe1Smrg 
56c3d31fe1Smrg   if (x == 0)
57c3d31fe1Smrg     return;
58c3d31fe1Smrg 
59c3d31fe1Smrg   code = GET_CODE (x);
60c3d31fe1Smrg 
61c3d31fe1Smrg   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
62c3d31fe1Smrg       || code == MATCH_PARALLEL)
63c3d31fe1Smrg     max_opno = MAX (max_opno, XINT (x, 0));
64c3d31fe1Smrg 
65c3d31fe1Smrg   fmt = GET_RTX_FORMAT (code);
66c3d31fe1Smrg   len = GET_RTX_LENGTH (code);
67c3d31fe1Smrg   for (i = 0; i < len; i++)
68c3d31fe1Smrg     {
69c3d31fe1Smrg       if (fmt[i] == 'e' || fmt[i] == 'u')
70c3d31fe1Smrg 	max_operand_1 (XEXP (x, i));
71c3d31fe1Smrg       else if (fmt[i] == 'E')
72c3d31fe1Smrg 	{
73c3d31fe1Smrg 	  int j;
74c3d31fe1Smrg 	  for (j = 0; j < XVECLEN (x, i); j++)
75c3d31fe1Smrg 	    max_operand_1 (XVECEXP (x, i, j));
76c3d31fe1Smrg 	}
77c3d31fe1Smrg     }
78c3d31fe1Smrg }
79c3d31fe1Smrg 
80c3d31fe1Smrg static int
num_operands(rtx insn)81c3d31fe1Smrg num_operands (rtx insn)
82c3d31fe1Smrg {
83c3d31fe1Smrg   int len = XVECLEN (insn, 1);
84c3d31fe1Smrg   int i;
85c3d31fe1Smrg 
86c3d31fe1Smrg   max_opno = -1;
87c3d31fe1Smrg 
88c3d31fe1Smrg   for (i = 0; i < len; i++)
89c3d31fe1Smrg     max_operand_1 (XVECEXP (insn, 1, i));
90c3d31fe1Smrg 
91c3d31fe1Smrg   return max_opno + 1;
92c3d31fe1Smrg }
93c3d31fe1Smrg 
94c3d31fe1Smrg /* Print out prototype information for a generator function.  If the
95c3d31fe1Smrg    insn pattern has been elided, print out a dummy generator that
96c3d31fe1Smrg    does nothing.  */
97c3d31fe1Smrg 
98c3d31fe1Smrg static void
gen_proto(rtx insn)99c3d31fe1Smrg gen_proto (rtx insn)
100c3d31fe1Smrg {
101c3d31fe1Smrg   int num = num_operands (insn);
102c3d31fe1Smrg   int i;
103c3d31fe1Smrg   const char *name = XSTR (insn, 0);
104c3d31fe1Smrg   int truth = maybe_eval_c_test (XSTR (insn, 2));
105c3d31fe1Smrg 
106c3d31fe1Smrg   if (truth != 0)
107c3d31fe1Smrg     printf ("extern rtx        gen_%-*s (", max_id_len, name);
108c3d31fe1Smrg   else
109c3d31fe1Smrg     printf ("static inline rtx gen_%-*s (", max_id_len, name);
110c3d31fe1Smrg 
111c3d31fe1Smrg   if (num == 0)
112c3d31fe1Smrg     fputs ("void", stdout);
113c3d31fe1Smrg   else
114c3d31fe1Smrg     {
115c3d31fe1Smrg       for (i = 1; i < num; i++)
116c3d31fe1Smrg 	fputs ("rtx, ", stdout);
117c3d31fe1Smrg 
118c3d31fe1Smrg       fputs ("rtx", stdout);
119c3d31fe1Smrg     }
120c3d31fe1Smrg 
121c3d31fe1Smrg   puts (");");
122c3d31fe1Smrg 
123c3d31fe1Smrg   /* Some back ends want to take the address of generator functions,
124c3d31fe1Smrg      so we cannot simply use #define for these dummy definitions.  */
125c3d31fe1Smrg   if (truth == 0)
126c3d31fe1Smrg     {
127c3d31fe1Smrg       printf ("static inline rtx\ngen_%s", name);
128c3d31fe1Smrg       if (num > 0)
129c3d31fe1Smrg 	{
130c3d31fe1Smrg 	  putchar ('(');
131c3d31fe1Smrg 	  for (i = 0; i < num-1; i++)
132c3d31fe1Smrg 	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
133c3d31fe1Smrg 	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
134c3d31fe1Smrg 	}
135c3d31fe1Smrg       else
136c3d31fe1Smrg 	puts ("(void)");
137c3d31fe1Smrg       puts ("{\n  return 0;\n}");
138c3d31fe1Smrg     }
139c3d31fe1Smrg 
140c3d31fe1Smrg }
141c3d31fe1Smrg 
142c3d31fe1Smrg static void
gen_insn(md_rtx_info * info)14363aace61Smrg gen_insn (md_rtx_info *info)
144c3d31fe1Smrg {
14563aace61Smrg   rtx insn = info->def;
146c3d31fe1Smrg   const char *name = XSTR (insn, 0);
147c3d31fe1Smrg   const char *p;
148c3d31fe1Smrg   const char *lt, *gt;
149c3d31fe1Smrg   int len;
150c3d31fe1Smrg   int truth = maybe_eval_c_test (XSTR (insn, 2));
151c3d31fe1Smrg 
152c3d31fe1Smrg   lt = strchr (name, '<');
153c3d31fe1Smrg   if (lt && strchr (lt + 1, '>'))
154c3d31fe1Smrg     {
15563aace61Smrg       error_at (info->loc, "unresolved iterator");
156c3d31fe1Smrg       return;
157c3d31fe1Smrg     }
158c3d31fe1Smrg 
159c3d31fe1Smrg   gt = strchr (name, '>');
160c3d31fe1Smrg   if (lt || gt)
161c3d31fe1Smrg     {
16263aace61Smrg       error_at (info->loc, "unmatched angle brackets, likely "
163c3d31fe1Smrg 		"an error in iterator syntax");
164c3d31fe1Smrg       return;
165c3d31fe1Smrg     }
166c3d31fe1Smrg 
167c3d31fe1Smrg   /* Don't mention instructions whose names are the null string
168c3d31fe1Smrg      or begin with '*'.  They are in the machine description just
169c3d31fe1Smrg      to be recognized.  */
170c3d31fe1Smrg   if (name[0] == 0 || name[0] == '*')
171c3d31fe1Smrg     return;
172c3d31fe1Smrg 
173c3d31fe1Smrg   len = strlen (name);
174c3d31fe1Smrg 
175c3d31fe1Smrg   if (len > max_id_len)
176c3d31fe1Smrg     max_id_len = len;
177c3d31fe1Smrg 
178c3d31fe1Smrg   if (truth == 0)
179c3d31fe1Smrg     /* Emit nothing.  */;
180c3d31fe1Smrg   else if (truth == 1)
181c3d31fe1Smrg     printf ("#define HAVE_%s 1\n", name);
182c3d31fe1Smrg   else
183c3d31fe1Smrg     {
184c3d31fe1Smrg       /* Write the macro definition, putting \'s at the end of each line,
185c3d31fe1Smrg 	 if more than one.  */
186c3d31fe1Smrg       printf ("#define HAVE_%s (", name);
187c3d31fe1Smrg       for (p = XSTR (insn, 2); *p; p++)
188c3d31fe1Smrg 	{
189c3d31fe1Smrg 	  if (IS_VSPACE (*p))
190c3d31fe1Smrg 	    fputs (" \\\n", stdout);
191c3d31fe1Smrg 	  else
192c3d31fe1Smrg 	    putchar (*p);
193c3d31fe1Smrg 	}
194c3d31fe1Smrg       fputs (")\n", stdout);
195c3d31fe1Smrg     }
196c3d31fe1Smrg 
197c3d31fe1Smrg   obstack_grow (&obstack, &insn, sizeof (rtx));
198c3d31fe1Smrg }
199c3d31fe1Smrg 
200c3d31fe1Smrg int
main(int argc,const char ** argv)2016a5c9aabSmrg main (int argc, const char **argv)
202c3d31fe1Smrg {
203c3d31fe1Smrg   rtx dummy;
204c3d31fe1Smrg   rtx *insns;
205c3d31fe1Smrg   rtx *insn_ptr;
206c3d31fe1Smrg 
207c3d31fe1Smrg   progname = "genflags";
208c3d31fe1Smrg   obstack_init (&obstack);
209c3d31fe1Smrg 
210c3d31fe1Smrg   /* We need to see all the possibilities.  Elided insns may have
211c3d31fe1Smrg      direct calls to their generators in C code.  */
212c3d31fe1Smrg   insn_elision = 0;
213c3d31fe1Smrg 
214af526226Smrg   if (!init_rtx_reader_args (argc, argv))
215c3d31fe1Smrg     return (FATAL_EXIT_CODE);
216c3d31fe1Smrg 
217c3d31fe1Smrg   puts ("/* Generated automatically by the program `genflags'");
218c3d31fe1Smrg   puts ("   from the machine description file `md'.  */\n");
219c3d31fe1Smrg   puts ("#ifndef GCC_INSN_FLAGS_H");
220c3d31fe1Smrg   puts ("#define GCC_INSN_FLAGS_H\n");
221c3d31fe1Smrg 
222c3d31fe1Smrg   /* Read the machine description.  */
223c3d31fe1Smrg 
22463aace61Smrg   md_rtx_info info;
22563aace61Smrg   while (read_md_rtx (&info))
22663aace61Smrg     switch (GET_CODE (info.def))
227c3d31fe1Smrg       {
22863aace61Smrg       case DEFINE_INSN:
22963aace61Smrg       case DEFINE_EXPAND:
23063aace61Smrg 	gen_insn (&info);
231c3d31fe1Smrg 	break;
23263aace61Smrg 
23363aace61Smrg       default:
23463aace61Smrg 	break;
235c3d31fe1Smrg       }
236c3d31fe1Smrg 
237c3d31fe1Smrg   /* Print out the prototypes now.  */
238c3d31fe1Smrg   dummy = (rtx) 0;
239c3d31fe1Smrg   obstack_grow (&obstack, &dummy, sizeof (rtx));
240c3d31fe1Smrg   insns = XOBFINISH (&obstack, rtx *);
241c3d31fe1Smrg 
242c3d31fe1Smrg   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
243c3d31fe1Smrg     gen_proto (*insn_ptr);
244c3d31fe1Smrg 
245c3d31fe1Smrg   puts ("\n#endif /* GCC_INSN_FLAGS_H */");
246c3d31fe1Smrg 
247c3d31fe1Smrg   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
248c3d31fe1Smrg     return FATAL_EXIT_CODE;
249c3d31fe1Smrg 
250c3d31fe1Smrg   return SUCCESS_EXIT_CODE;
251c3d31fe1Smrg }
252