OSDN Git Service

* sh.md (adddi3_compact, subdi3_compact): Add earlyclobber
[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, 2003 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   if (real > expect)
106     abort ();
107   if (real == 0)
108     abort ();
109
110   /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
111   fputs ("#define GEN_", stdout);
112   for (i = 0; name[i]; i++)
113     putchar (TOUPPER (name[i]));
114
115   putchar('(');
116   for (i = 0; i < expect - 1; i++)
117     printf ("%c, ", i + 'A');
118   printf ("%c) gen_%s (", i + 'A', name);
119
120   for (i = 0; i < real - 1; i++)
121     printf ("(%c), ", i + 'A');
122   printf ("(%c))\n", i + 'A');
123 }
124
125 /* Print out prototype information for a generator function.  If the
126    insn pattern has been elided, print out a dummy generator that
127    does nothing.  */
128
129 static void
130 gen_proto (rtx insn)
131 {
132   int num = num_operands (insn);
133   int i;
134   const char *name = XSTR (insn, 0);
135   int truth = maybe_eval_c_test (XSTR (insn, 2));
136
137   /* Many md files don't refer to the last two operands passed to the
138      call patterns.  This means their generator functions will be two
139      arguments too short.  Instead of changing every md file to touch
140      those operands, we wrap the prototypes in macros that take the
141      correct number of arguments.  */
142   if (name[0] == 'c' || name[0] == 's')
143     {
144       if (!strcmp (name, "call")
145           || !strcmp (name, "call_pop")
146           || !strcmp (name, "sibcall")
147           || !strcmp (name, "sibcall_pop"))
148         gen_macro (name, num, 4);
149       else if (!strcmp (name, "call_value")
150                || !strcmp (name, "call_value_pop")
151                || !strcmp (name, "sibcall_value")
152                || !strcmp (name, "sibcall_value_pop"))
153         gen_macro (name, num, 5);
154     }
155
156   if (truth != 0)
157     printf ("extern rtx        gen_%-*s (", max_id_len, name);
158   else
159     printf ("static inline rtx gen_%-*s (", max_id_len, name);
160
161   if (num == 0)
162     fputs ("void", stdout);
163   else
164     {
165       for (i = 1; i < num; i++)
166         fputs ("rtx, ", stdout);
167
168       fputs ("rtx", stdout);
169     }
170
171   puts (");");
172
173   /* Some back ends want to take the address of generator functions,
174      so we cannot simply use #define for these dummy definitions.  */
175   if (truth == 0)
176     {
177       printf ("static inline rtx\ngen_%s", name);
178       if (num > 0)
179         {
180           putchar ('(');
181           for (i = 0; i < num-1; i++)
182             printf ("%c, ", 'a' + i);
183           printf ("%c)\n", 'a' + i);
184           for (i = 0; i < num; i++)
185             printf ("     rtx %c ATTRIBUTE_UNUSED;\n", 'a' + i);
186         }
187       else
188         puts ("()");
189       puts ("{\n  return 0;\n}");
190     }
191
192 }
193
194 static void
195 gen_insn (rtx insn)
196 {
197   const char *name = XSTR (insn, 0);
198   const char *p;
199   int len;
200   int truth = maybe_eval_c_test (XSTR (insn, 2));
201
202   /* Don't mention instructions whose names are the null string
203      or begin with '*'.  They are in the machine description just
204      to be recognized.  */
205   if (name[0] == 0 || name[0] == '*')
206     return;
207
208   len = strlen (name);
209
210   if (len > max_id_len)
211     max_id_len = len;
212
213   if (truth == 0)
214     /* emit nothing */;
215   else if (truth == 1)
216     printf ("#define HAVE_%s 1\n", name);
217   else
218     {
219       /* Write the macro definition, putting \'s at the end of each line,
220          if more than one.  */
221       printf ("#define HAVE_%s (", name);
222       for (p = XSTR (insn, 2); *p; p++)
223         {
224           if (IS_VSPACE (*p))
225             fputs (" \\\n", stdout);
226           else
227             putchar (*p);
228         }
229       fputs (")\n", stdout);
230     }
231
232   obstack_grow (&obstack, &insn, sizeof (rtx));
233 }
234
235 int
236 main (int argc, char **argv)
237 {
238   rtx desc;
239   rtx dummy;
240   rtx *insns;
241   rtx *insn_ptr;
242
243   progname = "genflags";
244   obstack_init (&obstack);
245
246   /* We need to see all the possibilities.  Elided insns may have
247      direct calls to their generators in C code.  */
248   insn_elision = 0;
249
250   if (argc <= 1)
251     fatal ("no input file name");
252
253   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
254     return (FATAL_EXIT_CODE);
255
256   puts ("/* Generated automatically by the program `genflags'");
257   puts ("   from the machine description file `md'.  */\n");
258   puts ("#ifndef GCC_INSN_FLAGS_H");
259   puts ("#define GCC_INSN_FLAGS_H\n");
260
261   /* Read the machine description.  */
262
263   while (1)
264     {
265       int line_no, insn_code_number = 0;
266
267       desc = read_md_rtx (&line_no, &insn_code_number);
268       if (desc == NULL)
269         break;
270       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
271         gen_insn (desc);
272     }
273
274   /* Print out the prototypes now.  */
275   dummy = (rtx) 0;
276   obstack_grow (&obstack, &dummy, sizeof (rtx));
277   insns = (rtx *) obstack_finish (&obstack);
278
279   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
280     gen_proto (*insn_ptr);
281
282   puts("\n#endif /* GCC_INSN_FLAGS_H */");
283
284   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
285     return FATAL_EXIT_CODE;
286
287   return SUCCESS_EXIT_CODE;
288 }
289
290 /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
291 const char *
292 get_insn_name (int code ATTRIBUTE_UNUSED)
293 {
294   return NULL;
295 }