OSDN Git Service

(output_function_{pro,epi}logue): Use lea instead of add.w when
[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 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 <stdio.h>
26 #include "hconfig.h"
27 #include "rtl.h"
28 #include "obstack.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 extern void free ();
37 extern rtx read_rtx ();
38
39 char *xmalloc ();
40 static void fatal ();
41 void fancy_abort ();
42
43 /* Names for patterns.  Need to allow linking with print-rtl.  */
44 char **insn_name_ptr;
45
46 /* Obstacks to remember normal, and call insns.  */
47 static struct obstack call_obstack, normal_obstack;
48
49 /* Max size of names encountered.  */
50 static int max_id_len;
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   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 char *
176 xmalloc (size)
177      unsigned size;
178 {
179   register char *val = (char *) malloc (size);
180
181   if (val == 0)
182     fatal ("virtual memory exhausted");
183
184   return val;
185 }
186
187 char *
188 xrealloc (ptr, size)
189      char *ptr;
190      unsigned size;
191 {
192   char *result = (char *) realloc (ptr, size);
193   if (!result)
194     fatal ("virtual memory exhausted");
195   return result;
196 }
197
198 static void
199 fatal (s, a1, a2)
200      char *s;
201 {
202   fprintf (stderr, "genflags: ");
203   fprintf (stderr, s, a1, a2);
204   fprintf (stderr, "\n");
205   exit (FATAL_EXIT_CODE);
206 }
207
208 /* More 'friendly' abort that prints the line and file.
209    config.h can #define abort fancy_abort if you like that sort of thing.  */
210
211 void
212 fancy_abort ()
213 {
214   fatal ("Internal gcc abort.");
215 }
216 \f
217 int
218 main (argc, argv)
219      int argc;
220      char **argv;
221 {
222   rtx desc;
223   rtx dummy;
224   rtx *call_insns;
225   rtx *normal_insns;
226   rtx *insn_ptr;
227   FILE *infile;
228   register int c;
229
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       exit (FATAL_EXIT_CODE);
242     }
243
244   init_rtl ();
245
246   printf ("/* Generated automatically by the program `genflags'\n\
247 from the machine description file `md'.  */\n\n");
248
249   /* Read the machine description.  */
250
251   while (1)
252     {
253       c = read_skip_spaces (infile);
254       if (c == EOF)
255         break;
256       ungetc (c, infile);
257
258       desc = read_rtx (infile);
259       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
260         gen_insn (desc);
261     }
262
263   /* Print out the prototypes now.  */
264   dummy = (rtx) 0;
265   obstack_grow (&call_obstack, &dummy, sizeof (rtx));
266   call_insns = (rtx *) obstack_finish (&call_obstack);
267
268   obstack_grow (&normal_obstack, &dummy, sizeof (rtx));
269   normal_insns = (rtx *) obstack_finish (&normal_obstack);
270
271   printf ("\n#ifndef NO_MD_PROTOTYPES\n");
272   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
273     gen_proto (*insn_ptr);
274
275   printf ("\n#ifdef MD_CALL_PROTOTYPES\n");
276   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
277     gen_proto (*insn_ptr);
278
279   printf ("\n#else /* !MD_CALL_PROTOTYPES */\n");
280   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
281     gen_nonproto (*insn_ptr);
282
283   printf ("#endif /* !MD_CALL_PROTOTYPES */\n");
284   printf ("\n#else  /* NO_MD_PROTOTYPES */\n");
285   for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++)
286     gen_nonproto (*insn_ptr);
287
288   for (insn_ptr = call_insns; *insn_ptr; insn_ptr++)
289     gen_nonproto (*insn_ptr);
290
291   printf ("#endif  /* NO_MD_PROTOTYPES */\n");
292
293   fflush (stdout);
294   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
295   /* NOTREACHED */
296   return 0;
297 }