OSDN Git Service

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