OSDN Git Service

* ChangeLog: Follow spelling conventions.
[pf3gnuchains/gcc-fork.git] / 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 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 "hconfig.h"
26 #include "system.h"
27 #include "rtl.h"
28 #include "obstack.h"
29 #include "errors.h"
30 #include "gensupport.h"
31
32 /* Obstack to remember insns with.  */
33 static struct obstack obstack;
34
35 /* Max size of names encountered.  */
36 static int max_id_len;
37
38 /* Max operand encountered in a scan over some insn.  */
39 static int max_opno;
40
41 static void max_operand_1       PARAMS ((rtx));
42 static int num_operands         PARAMS ((rtx));
43 static void gen_proto           PARAMS ((rtx));
44 static void gen_macro           PARAMS ((const char *, int, int));
45 static void gen_insn            PARAMS ((rtx));
46
47 /* Count the number of match_operand's found.  */
48
49 static void
50 max_operand_1 (x)
51      rtx x;
52 {
53   RTX_CODE code;
54   int i;
55   int len;
56   const char *fmt;
57
58   if (x == 0)
59     return;
60
61   code = GET_CODE (x);
62
63   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
64       || code == MATCH_PARALLEL)
65     max_opno = MAX (max_opno, XINT (x, 0));
66
67   fmt = GET_RTX_FORMAT (code);
68   len = GET_RTX_LENGTH (code);
69   for (i = 0; i < len; i++)
70     {
71       if (fmt[i] == 'e' || fmt[i] == 'u')
72         max_operand_1 (XEXP (x, i));
73       else if (fmt[i] == 'E')
74         {
75           int j;
76           for (j = 0; j < XVECLEN (x, i); j++)
77             max_operand_1 (XVECEXP (x, i, j));
78         }
79     }
80 }
81
82 static int
83 num_operands (insn)
84      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 (name, real, expect)
102      const char *name;
103      int real, expect;
104 {
105   int i;
106
107   if (real > expect)
108     abort ();
109   if (real == 0)
110     abort ();
111
112   /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
113   fputs ("#define GEN_", stdout);
114   for (i = 0; name[i]; i++)
115     putchar (TOUPPER (name[i]));
116
117   putchar('(');
118   for (i = 0; i < expect - 1; i++)
119     printf ("%c, ", i + 'A');
120   printf ("%c) gen_%s (", i + 'A', name);
121
122   for (i = 0; i < real - 1; i++)
123     printf ("(%c), ", i + 'A');
124   printf ("(%c))\n", i + 'A');
125 }
126
127 /* Print out prototype information for a generator function.  If the
128    insn pattern has been elided, print out a dummy generator that
129    does nothing.  */
130
131 static void
132 gen_proto (insn)
133      rtx insn;
134 {
135   int num = num_operands (insn);
136   int i;
137   const char *name = XSTR (insn, 0);
138   int truth = maybe_eval_c_test (XSTR (insn, 2));
139
140   /* Many md files don't refer to the last two operands passed to the
141      call patterns.  This means their generator functions will be two
142      arguments too short.  Instead of changing every md file to touch
143      those operands, we wrap the prototypes in macros that take the
144      correct number of arguments.  */
145   if (name[0] == 'c' || name[0] == 's')
146     {
147       if (!strcmp (name, "call")
148           || !strcmp (name, "call_pop")
149           || !strcmp (name, "sibcall")
150           || !strcmp (name, "sibcall_pop"))
151         gen_macro (name, num, 4);
152       else if (!strcmp (name, "call_value")
153                || !strcmp (name, "call_value_pop")
154                || !strcmp (name, "sibcall_value")
155                || !strcmp (name, "sibcall_value_pop"))
156         gen_macro (name, num, 5);
157     }
158
159   if (truth != 0)
160     printf ("extern rtx        gen_%-*s PARAMS ((", max_id_len, name);
161   else
162     printf ("static inline rtx gen_%-*s PARAMS ((", max_id_len, name);
163
164   if (num == 0)
165     fputs ("void", stdout);
166   else
167     {
168       for (i = 1; i < num; i++)
169         fputs ("rtx, ", stdout);
170       
171       fputs ("rtx", stdout);
172     }
173
174   puts ("));");
175
176   /* Some back ends want to take the address of generator functions,
177      so we cannot simply use #define for these dummy definitions.  */
178   if (truth == 0)
179     {
180       printf ("static inline rtx\ngen_%s", name);
181       if (num > 0)
182         {
183           putchar ('(');
184           for (i = 0; i < num-1; i++)
185             printf ("%c, ", 'a' + i);
186           printf ("%c)\n", 'a' + i);
187           for (i = 0; i < num; i++)
188             printf ("     rtx %c ATTRIBUTE_UNUSED;\n", 'a' + i);
189         }
190       else
191         puts ("()");
192       puts ("{\n  return 0;\n}");
193     }
194
195 }
196
197 static void
198 gen_insn (insn)
199      rtx insn;
200 {
201   const char *name = XSTR (insn, 0);
202   const char *p;
203   int len;
204   int truth = maybe_eval_c_test (XSTR (insn, 2));
205
206   /* Don't mention instructions whose names are the null string
207      or begin with '*'.  They are in the machine description just
208      to be recognized.  */
209   if (name[0] == 0 || name[0] == '*')
210     return;
211
212   len = strlen (name);
213
214   if (len > max_id_len)
215     max_id_len = len;
216
217   if (truth == 0)
218     /* emit nothing */;
219   else if (truth == 1)
220     printf ("#define HAVE_%s 1\n", name);
221   else
222     {
223       /* Write the macro definition, putting \'s at the end of each line,
224          if more than one.  */
225       printf ("#define HAVE_%s (", name);
226       for (p = XSTR (insn, 2); *p; p++)
227         {
228           if (IS_VSPACE (*p))
229             fputs (" \\\n", stdout);
230           else
231             putchar (*p);
232         }
233       fputs (")\n", stdout);
234     }
235
236   obstack_grow (&obstack, &insn, sizeof (rtx));
237 }
238
239 extern int main PARAMS ((int, char **));
240
241 int
242 main (argc, argv)
243      int argc;
244      char **argv;
245 {
246   rtx desc;
247   rtx dummy;
248   rtx *insns;
249   rtx *insn_ptr;
250
251   progname = "genflags";
252   obstack_init (&obstack);
253
254   /* We need to see all the possibilities.  Elided insns may have
255      direct calls to their generators in C code.  */
256   insn_elision = 0;
257
258   if (argc <= 1)
259     fatal ("no input file name");
260
261   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
262     return (FATAL_EXIT_CODE);
263   
264   puts ("/* Generated automatically by the program `genflags'");
265   puts ("   from the machine description file `md'.  */\n");
266   puts ("#ifndef GCC_INSN_FLAGS_H");
267   puts ("#define GCC_INSN_FLAGS_H\n");
268
269   /* Read the machine description.  */
270
271   while (1)
272     {
273       int line_no, insn_code_number = 0;
274
275       desc = read_md_rtx (&line_no, &insn_code_number);
276       if (desc == NULL)
277         break;
278       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
279         gen_insn (desc);
280     }
281
282   /* Print out the prototypes now.  */
283   dummy = (rtx) 0;
284   obstack_grow (&obstack, &dummy, sizeof (rtx));
285   insns = (rtx *) obstack_finish (&obstack);
286
287   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
288     gen_proto (*insn_ptr);
289
290   puts("\n#endif /* GCC_INSN_FLAGS_H */");
291
292   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
293     return FATAL_EXIT_CODE;
294
295   return SUCCESS_EXIT_CODE;
296 }
297
298 /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
299 const char *
300 get_insn_name (code)
301      int code ATTRIBUTE_UNUSED;
302 {
303   return NULL;
304 }