OSDN Git Service

d1f19e08b815cf00578bac9f837a6b7d4ba55d0c
[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
31 static struct obstack obstack;
32 struct obstack *rtl_obstack = &obstack;
33
34 #define obstack_chunk_alloc xmalloc
35 #define obstack_chunk_free free
36
37 /* Obstacks to remember normal, and call insns.  */
38 static struct obstack call_obstack, normal_obstack;
39
40 /* Max size of names encountered.  */
41 static int max_id_len;
42
43 /* Max operand encountered in a scan over some insn.  */
44 static int max_opno;
45
46 static void max_operand_1       PARAMS ((rtx));
47 static int num_operands         PARAMS ((rtx));
48 static void gen_proto           PARAMS ((rtx));
49 static void gen_nonproto        PARAMS ((rtx));
50 static void gen_insn            PARAMS ((rtx));
51
52 /* Count the number of match_operand's found.  */
53
54 static void
55 max_operand_1 (x)
56      rtx x;
57 {
58   register RTX_CODE code;
59   register int i;
60   register int len;
61   register const char *fmt;
62
63   if (x == 0)
64     return;
65
66   code = GET_CODE (x);
67
68   if (code == MATCH_OPERAND || code == MATCH_OPERATOR
69       || code == MATCH_PARALLEL)
70     max_opno = MAX (max_opno, XINT (x, 0));
71
72   fmt = GET_RTX_FORMAT (code);
73   len = GET_RTX_LENGTH (code);
74   for (i = 0; i < len; i++)
75     {
76       if (fmt[i] == 'e' || fmt[i] == 'u')
77         max_operand_1 (XEXP (x, i));
78       else if (fmt[i] == 'E')
79         {
80           int j;
81           for (j = 0; j < XVECLEN (x, i); j++)
82             max_operand_1 (XVECEXP (x, i, j));
83         }
84     }
85 }
86
87 static int
88 num_operands (insn)
89      rtx insn;
90 {
91   register int len = XVECLEN (insn, 1);
92   register int i;
93
94   max_opno = -1;
95
96   for (i = 0; i < len; i++)
97     max_operand_1 (XVECEXP (insn, 1, i));
98
99   return max_opno + 1;
100 }
101
102 /* Print out prototype information for a function.  */
103
104 static void
105 gen_proto (insn)
106      rtx insn;
107 {
108   int num = num_operands (insn);
109   printf ("extern rtx gen_%-*s PARAMS ((", max_id_len, XSTR (insn, 0));
110
111   if (num == 0)
112     printf ("void");
113   else
114     {
115       while (num-- > 1)
116         printf ("rtx, ");
117
118       printf ("rtx");
119     }
120
121   printf ("));\n");
122 }
123
124 /* Print out a function declaration without a prototype.  */
125
126 static void
127 gen_nonproto (insn)
128      rtx insn;
129 {
130   printf ("extern rtx gen_%s ();\n", XSTR (insn, 0));
131 }
132
133 static void
134 gen_insn (insn)
135      rtx insn;
136 {
137   const char *name = XSTR (insn, 0);
138   const char *p;
139   struct obstack *obstack_ptr;
140   int len;
141
142   /* Don't mention instructions whose names are the null string
143      or begin with '*'.  They are in the machine description just
144      to be recognized.  */
145   if (name[0] == 0 || name[0] == '*')
146     return;
147
148   len = strlen (name);
149
150   if (len > max_id_len)
151     max_id_len = len;
152
153   printf ("#define HAVE_%s ", name);
154   if (strlen (XSTR (insn, 2)) == 0)
155     printf ("1\n");
156   else
157     {
158       /* Write the macro definition, putting \'s at the end of each line,
159          if more than one.  */
160       printf ("(");
161       for (p = XSTR (insn, 2); *p; p++)
162         {
163           if (*p == '\n')
164             printf (" \\\n");
165           else
166             printf ("%c", *p);
167         }
168       printf (")\n");
169     }
170
171   /* Save the current insn, so that we can later put out appropriate
172      prototypes.  At present, most md files have the wrong number of
173      arguments for the call insns (call, call_value, call_pop,
174      call_value_pop) ignoring the extra arguments that are passed for
175      some machines, so by default, turn off the prototype.  */
176
177   obstack_ptr = (name[0] == 'c'
178                  && (!strcmp (name, "call")
179                      || !strcmp (name, "call_value")
180                      || !strcmp (name, "call_pop")
181                      || !strcmp (name, "call_value_pop")))
182     ? &call_obstack : &normal_obstack;
183
184   obstack_grow (obstack_ptr, &insn, sizeof (rtx));
185 }
186 \f
187 PTR
188 xmalloc (size)
189   size_t size;
190 {
191   register PTR val = (PTR) malloc (size);
192
193   if (val == 0)
194     fatal ("virtual memory exhausted");
195
196   return val;
197 }
198
199 PTR
200 xrealloc (old, size)
201   PTR old;
202   size_t size;
203 {
204   register PTR ptr;
205   if (old)
206     ptr = (PTR) realloc (old, size);
207   else
208     ptr = (PTR) malloc (size);
209   if (!ptr)
210     fatal ("virtual memory exhausted");
211   return ptr;
212 }
213
214 extern int main PARAMS ((int, char **));
215
216 int
217 main (argc, argv)
218      int argc;
219      char **argv;
220 {
221   rtx desc;
222   rtx dummy;
223   rtx *call_insns;
224   rtx *normal_insns;
225   rtx *insn_ptr;
226   FILE *infile;
227   register int c;
228
229   progname = "genflags";
230   obstack_init (rtl_obstack);
231   obstack_init (&call_obstack);
232   obstack_init (&normal_obstack);
233
234   if (argc <= 1)
235     fatal ("No input file name.");
236
237   infile = fopen (argv[1], "r");
238   if (infile == 0)
239     {
240       perror (argv[1]);
241       return (FATAL_EXIT_CODE);
242     }
243   read_rtx_filename = argv[1];
244
245   printf ("/* Generated automatically by the program `genflags'\n\
246 from the machine description file `md'.  */\n\n");
247
248   /* Read the machine description.  */
249
250   while (1)
251     {
252       c = read_skip_spaces (infile);
253       if (c == EOF)
254         break;
255       ungetc (c, infile);
256
257       desc = read_rtx (infile);
258       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
259         gen_insn (desc);
260     }
261
262   /* Print out the prototypes now.  */
263   dummy = (rtx) 0;
264   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
265   call_insns = (rtx *) obstack_finish (&call_obstack);
266
267   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
268   normal_insns = (rtx *) obstack_finish (&normal_obstack);
269
270   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
271     gen_proto (*insn_ptr);
272
273   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
274   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
275     gen_proto (*insn_ptr);
276
277   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
278   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
279     gen_nonproto (*insn_ptr);
280
281   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
282
283   fflush (stdout);
284   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
285 }
286
287 /* Define this so we can link with print-rtl.o to get debug_rtx function.  */
288 const char *
289 get_insn_name (code)
290      int code ATTRIBUTE_UNUSED;
291 {
292   return NULL;
293 }