OSDN Git Service

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