Import of virgin gcc 4.0.0 distribution.
[dragonfly.git] / contrib / gcc-4.0 / gcc / genflags.c
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,
5    1999, 2000, 2003, 2004 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 2, 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 COPYING.  If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA.  */
23
24
25 #include "bconfig.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "rtl.h"
30 #include "obstack.h"
31 #include "errors.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 (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 (rtx insn)
192 {
193   const char *name = XSTR (insn, 0);
194   const char *p;
195   int len;
196   int truth = maybe_eval_c_test (XSTR (insn, 2));
197
198   /* Don't mention instructions whose names are the null string
199      or begin with '*'.  They are in the machine description just
200      to be recognized.  */
201   if (name[0] == 0 || name[0] == '*')
202     return;
203
204   len = strlen (name);
205
206   if (len > max_id_len)
207     max_id_len = len;
208
209   if (truth == 0)
210     /* Emit nothing.  */;
211   else if (truth == 1)
212     printf ("#define HAVE_%s 1\n", name);
213   else
214     {
215       /* Write the macro definition, putting \'s at the end of each line,
216          if more than one.  */
217       printf ("#define HAVE_%s (", name);
218       for (p = XSTR (insn, 2); *p; p++)
219         {
220           if (IS_VSPACE (*p))
221             fputs (" \\\n", stdout);
222           else
223             putchar (*p);
224         }
225       fputs (")\n", stdout);
226     }
227
228   obstack_grow (&obstack, &insn, sizeof (rtx));
229 }
230
231 int
232 main (int argc, char **argv)
233 {
234   rtx desc;
235   rtx dummy;
236   rtx *insns;
237   rtx *insn_ptr;
238
239   progname = "genflags";
240   obstack_init (&obstack);
241
242   /* We need to see all the possibilities.  Elided insns may have
243      direct calls to their generators in C code.  */
244   insn_elision = 0;
245
246   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
247     return (FATAL_EXIT_CODE);
248
249   puts ("/* Generated automatically by the program `genflags'");
250   puts ("   from the machine description file `md'.  */\n");
251   puts ("#ifndef GCC_INSN_FLAGS_H");
252   puts ("#define GCC_INSN_FLAGS_H\n");
253
254   /* Read the machine description.  */
255
256   while (1)
257     {
258       int line_no, insn_code_number = 0;
259
260       desc = read_md_rtx (&line_no, &insn_code_number);
261       if (desc == NULL)
262         break;
263       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
264         gen_insn (desc);
265     }
266
267   /* Print out the prototypes now.  */
268   dummy = (rtx) 0;
269   obstack_grow (&obstack, &dummy, sizeof (rtx));
270   insns = (rtx *) obstack_finish (&obstack);
271
272   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
273     gen_proto (*insn_ptr);
274
275   puts("\n#endif /* GCC_INSN_FLAGS_H */");
276
277   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
278     return FATAL_EXIT_CODE;
279
280   return SUCCESS_EXIT_CODE;
281 }
282
283 /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
284 const char *
285 get_insn_name (int ARG_UNUSED (code))
286 {
287   return NULL;
288 }