OSDN Git Service

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