OSDN Git Service

* genattr.c, gencheck.c, gencodes.c, genconfig.c, genflags.c,
[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 GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 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
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
35
36 /* Obstack to remember insns with.  */
37 static struct obstack obstack;
38
39 /* Max size of names encountered.  */
40 static int max_id_len;
41
42 /* Max operand encountered in a scan over some insn.  */
43 static int max_opno;
44
45 static void max_operand_1       PARAMS ((rtx));
46 static int num_operands         PARAMS ((rtx));
47 static void gen_proto           PARAMS ((rtx));
48 static void gen_macro           PARAMS ((const char *, int, int));
49 static void gen_insn            PARAMS ((rtx));
50
51 /* Count the number of match_operand's found.  */
52
53 static void
54 max_operand_1 (x)
55      rtx x;
56 {
57   register RTX_CODE code;
58   register int i;
59   register int len;
60   register const char *fmt;
61
62   if (x == 0)
63     return;
64
65   code = GET_CODE (x);
66
67   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
68       || code == MATCH_PARALLEL)
69     max_opno = MAX (max_opno, XINT (x, 0));
70
71   fmt = GET_RTX_FORMAT (code);
72   len = GET_RTX_LENGTH (code);
73   for (i = 0; i < len; i++)
74     {
75       if (fmt[i] == 'e' || fmt[i] == 'u')
76         max_operand_1 (XEXP (x, i));
77       else if (fmt[i] == 'E')
78         {
79           int j;
80           for (j = 0; j < XVECLEN (x, i); j++)
81             max_operand_1 (XVECEXP (x, i, j));
82         }
83     }
84 }
85
86 static int
87 num_operands (insn)
88      rtx insn;
89 {
90   register int len = XVECLEN (insn, 1);
91   register int i;
92
93   max_opno = -1;
94
95   for (i = 0; i < len; i++)
96     max_operand_1 (XVECEXP (insn, 1, i));
97
98   return max_opno + 1;
99 }
100
101 /* Print out a wrapper macro for a function which corrects the number
102    of arguments it takes.  Any missing arguments are assumed to be at
103    the end.  */
104 static void
105 gen_macro (name, real, expect)
106      const char *name;
107      int real, expect;
108 {
109   int i;
110
111   if (real > expect)
112     abort ();
113   if (real == 0)
114     abort ();
115
116   /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
117   fputs ("#define GEN_", stdout);
118   for (i = 0; name[i]; i++)
119     putchar (TOUPPER (name[i]));
120
121   putchar('(');
122   for (i = 0; i < expect - 1; i++)
123     printf ("%c, ", i + 'A');
124   printf ("%c) gen_%s (", i + 'A', name);
125
126   for (i = 0; i < real - 1; i++)
127     printf ("(%c), ", i + 'A');
128   printf ("(%c))\n", i + 'A');
129 }
130
131 /* Print out prototype information for a function.  */
132
133 static void
134 gen_proto (insn)
135      rtx insn;
136 {
137   int num = num_operands (insn);
138   const char *name = XSTR (insn, 0);
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   printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
160
161   if (num == 0)
162     printf ("void");
163   else
164     {
165       while (num-- > 1)
166         printf ("struct rtx_def *, ");
167
168       printf ("struct rtx_def *");
169     }
170
171   printf ("));\n");
172
173 }
174
175 static void
176 gen_insn (insn)
177      rtx insn;
178 {
179   const char *name = XSTR (insn, 0);
180   const char *p;
181   int len;
182
183   /* Don't mention instructions whose names are the null string
184      or begin with '*'.  They are in the machine description just
185      to be recognized.  */
186   if (name[0] == 0 || name[0] == '*')
187     return;
188
189   len = strlen (name);
190
191   if (len > max_id_len)
192     max_id_len = len;
193
194   printf ("#define HAVE_%s ", name);
195   if (strlen (XSTR (insn, 2)) == 0)
196     printf ("1\n");
197   else
198     {
199       /* Write the macro definition, putting \'s at the end of each line,
200          if more than one.  */
201       printf ("(");
202       for (p = XSTR (insn, 2); *p; p++)
203         {
204           if (*p == '\n')
205             printf (" \\\n");
206           else
207             printf ("%c", *p);
208         }
209       printf (")\n");
210     }
211
212   obstack_grow (&obstack, &insn, sizeof (rtx));
213 }
214
215 extern int main PARAMS ((int, char **));
216
217 int
218 main (argc, argv)
219      int argc;
220      char **argv;
221 {
222   rtx desc;
223   rtx dummy;
224   rtx *insns;
225   rtx *insn_ptr;
226
227   progname = "genflags";
228   obstack_init (&obstack);
229
230   if (argc <= 1)
231     fatal ("No input file name.");
232
233   if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
234     return (FATAL_EXIT_CODE);
235   
236   puts ("/* Generated automatically by the program `genflags'");
237   puts ("   from the machine description file `md'.  */\n");
238   puts ("#ifndef GCC_INSN_FLAGS_H");
239   puts ("#define GCC_INSN_FLAGS_H\n");
240
241   /* Read the machine description.  */
242
243   while (1)
244     {
245       int line_no, insn_code_number = 0;
246
247       desc = read_md_rtx (&line_no, &insn_code_number);
248       if (desc == NULL)
249         break;
250       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
251         gen_insn (desc);
252     }
253
254   /* Print out the prototypes now.  */
255   dummy = (rtx) 0;
256   obstack_grow (&obstack, &dummy, sizeof (rtx));
257   insns = (rtx *) obstack_finish (&obstack);
258
259   printf ("struct rtx_def;\n");
260   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
261     gen_proto (*insn_ptr);
262
263   puts("\n#endif /* GCC_INSN_FLAGS_H */");
264
265   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
266     return FATAL_EXIT_CODE;
267
268   return SUCCESS_EXIT_CODE;
269 }
270
271 /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
272 const char *
273 get_insn_name (code)
274      int code ATTRIBUTE_UNUSED;
275 {
276   return NULL;
277 }