OSDN Git Service

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