xref: /dragonfly/contrib/gcc-4.7/gcc/genflags.c (revision 6e5c5008)
1 /* Generate from machine description:
2    - some flags HAVE_... saying which simple standard instructions are
3    available for this machine.
4    Copyright (C) 1987, 1991, 1995, 1998, 1999, 2000, 2003, 2004, 2007, 2010
5    Free Software Foundation, Inc.
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13 
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 
24 #include "bconfig.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "obstack.h"
30 #include "errors.h"
31 #include "read-md.h"
32 #include "gensupport.h"
33 
34 /* Obstack to remember insns with.  */
35 static struct obstack obstack;
36 
37 /* Max size of names encountered.  */
38 static int max_id_len;
39 
40 /* Max operand encountered in a scan over some insn.  */
41 static int max_opno;
42 
43 static void max_operand_1 (rtx);
44 static int num_operands (rtx);
45 static void gen_proto (rtx);
46 static void gen_macro (const char *, int, int);
47 static void gen_insn (int, rtx);
48 
49 /* Count the number of match_operand's found.  */
50 
51 static void
52 max_operand_1 (rtx x)
53 {
54   RTX_CODE code;
55   int i;
56   int len;
57   const char *fmt;
58 
59   if (x == 0)
60     return;
61 
62   code = GET_CODE (x);
63 
64   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
65       || code == MATCH_PARALLEL)
66     max_opno = MAX (max_opno, XINT (x, 0));
67 
68   fmt = GET_RTX_FORMAT (code);
69   len = GET_RTX_LENGTH (code);
70   for (i = 0; i < len; i++)
71     {
72       if (fmt[i] == 'e' || fmt[i] == 'u')
73 	max_operand_1 (XEXP (x, i));
74       else if (fmt[i] == 'E')
75 	{
76 	  int j;
77 	  for (j = 0; j < XVECLEN (x, i); j++)
78 	    max_operand_1 (XVECEXP (x, i, j));
79 	}
80     }
81 }
82 
83 static int
84 num_operands (rtx insn)
85 {
86   int len = XVECLEN (insn, 1);
87   int i;
88 
89   max_opno = -1;
90 
91   for (i = 0; i < len; i++)
92     max_operand_1 (XVECEXP (insn, 1, i));
93 
94   return max_opno + 1;
95 }
96 
97 /* Print out a wrapper macro for a function which corrects the number
98    of arguments it takes.  Any missing arguments are assumed to be at
99    the end.  */
100 static void
101 gen_macro (const char *name, int real, int expect)
102 {
103   int i;
104 
105   gcc_assert (real <= expect);
106   gcc_assert (real);
107 
108   /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
109   fputs ("#define GEN_", stdout);
110   for (i = 0; name[i]; i++)
111     putchar (TOUPPER (name[i]));
112 
113   putchar('(');
114   for (i = 0; i < expect - 1; i++)
115     printf ("%c, ", i + 'A');
116   printf ("%c) gen_%s (", i + 'A', name);
117 
118   for (i = 0; i < real - 1; i++)
119     printf ("(%c), ", i + 'A');
120   printf ("(%c))\n", i + 'A');
121 }
122 
123 /* Print out prototype information for a generator function.  If the
124    insn pattern has been elided, print out a dummy generator that
125    does nothing.  */
126 
127 static void
128 gen_proto (rtx insn)
129 {
130   int num = num_operands (insn);
131   int i;
132   const char *name = XSTR (insn, 0);
133   int truth = maybe_eval_c_test (XSTR (insn, 2));
134 
135   /* Many md files don't refer to the last two operands passed to the
136      call patterns.  This means their generator functions will be two
137      arguments too short.  Instead of changing every md file to touch
138      those operands, we wrap the prototypes in macros that take the
139      correct number of arguments.  */
140   if (name[0] == 'c' || name[0] == 's')
141     {
142       if (!strcmp (name, "call")
143 	  || !strcmp (name, "call_pop")
144 	  || !strcmp (name, "sibcall")
145 	  || !strcmp (name, "sibcall_pop"))
146 	gen_macro (name, num, 4);
147       else if (!strcmp (name, "call_value")
148 	       || !strcmp (name, "call_value_pop")
149 	       || !strcmp (name, "sibcall_value")
150 	       || !strcmp (name, "sibcall_value_pop"))
151 	gen_macro (name, num, 5);
152     }
153 
154   if (truth != 0)
155     printf ("extern rtx        gen_%-*s (", max_id_len, name);
156   else
157     printf ("static inline rtx gen_%-*s (", max_id_len, name);
158 
159   if (num == 0)
160     fputs ("void", stdout);
161   else
162     {
163       for (i = 1; i < num; i++)
164 	fputs ("rtx, ", stdout);
165 
166       fputs ("rtx", stdout);
167     }
168 
169   puts (");");
170 
171   /* Some back ends want to take the address of generator functions,
172      so we cannot simply use #define for these dummy definitions.  */
173   if (truth == 0)
174     {
175       printf ("static inline rtx\ngen_%s", name);
176       if (num > 0)
177 	{
178 	  putchar ('(');
179 	  for (i = 0; i < num-1; i++)
180 	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
181 	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
182 	}
183       else
184 	puts ("(void)");
185       puts ("{\n  return 0;\n}");
186     }
187 
188 }
189 
190 static void
191 gen_insn (int line_no, rtx insn)
192 {
193   const char *name = XSTR (insn, 0);
194   const char *p;
195   const char *lt, *gt;
196   int len;
197   int truth = maybe_eval_c_test (XSTR (insn, 2));
198 
199   lt = strchr (name, '<');
200   if (lt && strchr (lt + 1, '>'))
201     {
202       message_with_line (line_no, "unresolved iterator");
203       have_error = 1;
204       return;
205     }
206 
207   gt = strchr (name, '>');
208   if (lt || gt)
209     {
210       message_with_line (line_no,
211 			 "unmatched angle brackets, likely "
212 			 "an error in iterator syntax");
213       have_error = 1;
214       return;
215     }
216 
217   /* Don't mention instructions whose names are the null string
218      or begin with '*'.  They are in the machine description just
219      to be recognized.  */
220   if (name[0] == 0 || name[0] == '*')
221     return;
222 
223   len = strlen (name);
224 
225   if (len > max_id_len)
226     max_id_len = len;
227 
228   if (truth == 0)
229     /* Emit nothing.  */;
230   else if (truth == 1)
231     printf ("#define HAVE_%s 1\n", name);
232   else
233     {
234       /* Write the macro definition, putting \'s at the end of each line,
235 	 if more than one.  */
236       printf ("#define HAVE_%s (", name);
237       for (p = XSTR (insn, 2); *p; p++)
238 	{
239 	  if (IS_VSPACE (*p))
240 	    fputs (" \\\n", stdout);
241 	  else
242 	    putchar (*p);
243 	}
244       fputs (")\n", stdout);
245     }
246 
247   obstack_grow (&obstack, &insn, sizeof (rtx));
248 }
249 
250 int
251 main (int argc, char **argv)
252 {
253   rtx desc;
254   rtx dummy;
255   rtx *insns;
256   rtx *insn_ptr;
257 
258   progname = "genflags";
259   obstack_init (&obstack);
260 
261   /* We need to see all the possibilities.  Elided insns may have
262      direct calls to their generators in C code.  */
263   insn_elision = 0;
264 
265   if (!init_rtx_reader_args (argc, argv))
266     return (FATAL_EXIT_CODE);
267 
268   puts ("/* Generated automatically by the program `genflags'");
269   puts ("   from the machine description file `md'.  */\n");
270   puts ("#ifndef GCC_INSN_FLAGS_H");
271   puts ("#define GCC_INSN_FLAGS_H\n");
272 
273   /* Read the machine description.  */
274 
275   while (1)
276     {
277       int line_no, insn_code_number = 0;
278 
279       desc = read_md_rtx (&line_no, &insn_code_number);
280       if (desc == NULL)
281 	break;
282       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
283 	gen_insn (line_no, desc);
284     }
285 
286   /* Print out the prototypes now.  */
287   dummy = (rtx) 0;
288   obstack_grow (&obstack, &dummy, sizeof (rtx));
289   insns = XOBFINISH (&obstack, rtx *);
290 
291   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
292     gen_proto (*insn_ptr);
293 
294   puts("\n#endif /* GCC_INSN_FLAGS_H */");
295 
296   if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
297     return FATAL_EXIT_CODE;
298 
299   return SUCCESS_EXIT_CODE;
300 }
301