genflags.c revision 96263
1112758Ssam/* Generate from machine description:
2112758Ssam   - some flags HAVE_... saying which simple standard instructions are
3112758Ssam   available for this machine.
4112758Ssam   Copyright (C) 1987, 1991, 1995, 1998,
5112758Ssam   1999, 2000 Free Software Foundation, Inc.
6112758Ssam
7112758SsamThis file is part of GCC.
8112758Ssam
9112758SsamGCC is free software; you can redistribute it and/or modify it under
10112758Ssamthe terms of the GNU General Public License as published by the Free
11112758SsamSoftware Foundation; either version 2, or (at your option) any later
12112758Ssamversion.
13112758Ssam
14112758SsamGCC is distributed in the hope that it will be useful, but WITHOUT ANY
15112758SsamWARRANTY; without even the implied warranty of MERCHANTABILITY or
16112758SsamFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17112758Ssamfor more details.
18112758Ssam
19112758SsamYou should have received a copy of the GNU General Public License
20112758Ssamalong with GCC; see the file COPYING.  If not, write to the Free
21112758SsamSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
22112758Ssam02111-1307, USA.  */
23112758Ssam
24112758Ssam
25112758Ssam#include "hconfig.h"
26112758Ssam#include "system.h"
27112758Ssam#include "rtl.h"
28105197Ssam#include "obstack.h"
29105197Ssam#include "errors.h"
30105197Ssam#include "gensupport.h"
31105197Ssam
32105197Ssam
33105197Ssam#define obstack_chunk_alloc xmalloc
34105197Ssam#define obstack_chunk_free free
35159965Sthompsa
36105197Ssam/* Obstack to remember insns with.  */
37105197Ssamstatic struct obstack obstack;
38105197Ssam
39105197Ssam/* Max size of names encountered.  */
40105197Ssamstatic int max_id_len;
41105197Ssam
42105197Ssam/* Max operand encountered in a scan over some insn.  */
43105197Ssamstatic int max_opno;
44105197Ssam
45181803Sbzstatic void max_operand_1	PARAMS ((rtx));
46105197Ssamstatic int num_operands		PARAMS ((rtx));
47105197Ssamstatic void gen_proto		PARAMS ((rtx));
48171497Sbzstatic void gen_macro		PARAMS ((const char *, int, int));
49105197Ssamstatic void gen_insn		PARAMS ((rtx));
50105197Ssam
51105197Ssam/* Count the number of match_operand's found.  */
52105197Ssam
53105197Ssamstatic void
54105197Ssammax_operand_1 (x)
55105197Ssam     rtx x;
56105197Ssam{
57105197Ssam  RTX_CODE code;
58105197Ssam  int i;
59105197Ssam  int len;
60105197Ssam  const char *fmt;
61105197Ssam
62105197Ssam  if (x == 0)
63105197Ssam    return;
64105197Ssam
65105197Ssam  code = GET_CODE (x);
66105197Ssam
67105197Ssam  if (code == MATCH_OPERAND || code == MATCH_OPERATOR
68185571Sbz      || code == MATCH_PARALLEL)
69105197Ssam    max_opno = MAX (max_opno, XINT (x, 0));
70105197Ssam
71105197Ssam  fmt = GET_RTX_FORMAT (code);
72105197Ssam  len = GET_RTX_LENGTH (code);
73105197Ssam  for (i = 0; i < len; i++)
74105197Ssam    {
75105197Ssam      if (fmt[i] == 'e' || fmt[i] == 'u')
76105197Ssam	max_operand_1 (XEXP (x, i));
77105197Ssam      else if (fmt[i] == 'E')
78105197Ssam	{
79105197Ssam	  int j;
80105197Ssam	  for (j = 0; j < XVECLEN (x, i); j++)
81105197Ssam	    max_operand_1 (XVECEXP (x, i, j));
82105197Ssam	}
83105197Ssam    }
84105197Ssam}
85105197Ssam
86105197Ssamstatic int
87194062Svanhunum_operands (insn)
88194062Svanhu     rtx insn;
89194062Svanhu{
90194062Svanhu  int len = XVECLEN (insn, 1);
91181627Svanhu  int i;
92181627Svanhu
93181627Svanhu  max_opno = -1;
94181627Svanhu
95181627Svanhu  for (i = 0; i < len; i++)
96105197Ssam    max_operand_1 (XVECEXP (insn, 1, i));
97105197Ssam
98105197Ssam  return max_opno + 1;
99183550Szec}
100105197Ssam
101105197Ssam/* Print out a wrapper macro for a function which corrects the number
102105197Ssam   of arguments it takes.  Any missing arguments are assumed to be at
103105197Ssam   the end.  */
104105197Ssamstatic void
105105197Ssamgen_macro (name, real, expect)
106120585Ssam     const char *name;
107120585Ssam     int real, expect;
108105197Ssam{
109120585Ssam  int i;
110120585Ssam
111105197Ssam  if (real > expect)
112105197Ssam    abort ();
113105197Ssam  if (real == 0)
114105197Ssam    abort ();
115105197Ssam
116105197Ssam  /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
117105197Ssam  fputs ("#define GEN_", stdout);
118105197Ssam  for (i = 0; name[i]; i++)
119105197Ssam    putchar (TOUPPER (name[i]));
120105197Ssam
121105197Ssam  putchar('(');
122105197Ssam  for (i = 0; i < expect - 1; i++)
123105197Ssam    printf ("%c, ", i + 'A');
124105197Ssam  printf ("%c) gen_%s (", i + 'A', name);
125105197Ssam
126105197Ssam  for (i = 0; i < real - 1; i++)
127105197Ssam    printf ("(%c), ", i + 'A');
128105197Ssam  printf ("(%c))\n", i + 'A');
129105197Ssam}
130105197Ssam
131105197Ssam/* Print out prototype information for a function.  */
132105197Ssam
133105197Ssamstatic void
134105197Ssamgen_proto (insn)
135105197Ssam     rtx insn;
136105197Ssam{
137120585Ssam  int num = num_operands (insn);
138105197Ssam  const char *name = XSTR (insn, 0);
139105197Ssam
140105197Ssam  /* Many md files don't refer to the last two operands passed to the
141105197Ssam     call patterns.  This means their generator functions will be two
142105197Ssam     arguments too short.  Instead of changing every md file to touch
143105197Ssam     those operands, we wrap the prototypes in macros that take the
144105197Ssam     correct number of arguments.  */
145105197Ssam  if (name[0] == 'c' || name[0] == 's')
146105197Ssam    {
147105197Ssam      if (!strcmp (name, "call")
148105197Ssam	  || !strcmp (name, "call_pop")
149105197Ssam	  || !strcmp (name, "sibcall")
150120585Ssam	  || !strcmp (name, "sibcall_pop"))
151105197Ssam	gen_macro (name, num, 4);
152105197Ssam      else if (!strcmp (name, "call_value")
153105197Ssam	       || !strcmp (name, "call_value_pop")
154105197Ssam	       || !strcmp (name, "sibcall_value")
155105197Ssam	       || !strcmp (name, "sibcall_value_pop"))
156105197Ssam	gen_macro (name, num, 5);
157105197Ssam    }
158105197Ssam
159105197Ssam  printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
160105197Ssam
161105197Ssam  if (num == 0)
162105197Ssam    printf ("void");
163105197Ssam  else
164105197Ssam    {
165105197Ssam      while (num-- > 1)
166105197Ssam	printf ("struct rtx_def *, ");
167105197Ssam
168105197Ssam      printf ("struct rtx_def *");
169181803Sbz    }
170105197Ssam
171105197Ssam  printf ("));\n");
172117056Ssam
173105197Ssam}
174105197Ssam
175105197Ssamstatic void
176105197Ssamgen_insn (insn)
177105197Ssam     rtx insn;
178105197Ssam{
179105197Ssam  const char *name = XSTR (insn, 0);
180105197Ssam  const char *p;
181105197Ssam  int len;
182105197Ssam
183105197Ssam  /* Don't mention instructions whose names are the null string
184105197Ssam     or begin with '*'.  They are in the machine description just
185105197Ssam     to be recognized.  */
186105197Ssam  if (name[0] == 0 || name[0] == '*')
187194062Svanhu    return;
188194062Svanhu
189194062Svanhu  len = strlen (name);
190194062Svanhu
191194062Svanhu  if (len > max_id_len)
192194062Svanhu    max_id_len = len;
193194062Svanhu
194194062Svanhu  printf ("#define HAVE_%s ", name);
195194062Svanhu  if (strlen (XSTR (insn, 2)) == 0)
196194062Svanhu    printf ("1\n");
197194062Svanhu  else
198194062Svanhu    {
199194062Svanhu      /* Write the macro definition, putting \'s at the end of each line,
200194062Svanhu	 if more than one.  */
201194062Svanhu      printf ("(");
202194062Svanhu      for (p = XSTR (insn, 2); *p; p++)
203194062Svanhu	{
204194062Svanhu	  if (IS_VSPACE (*p))
205194062Svanhu	    printf (" \\\n");
206194062Svanhu	  else
207194062Svanhu	    printf ("%c", *p);
208194062Svanhu	}
209194062Svanhu      printf (")\n");
210194062Svanhu    }
211194062Svanhu
212194062Svanhu  obstack_grow (&obstack, &insn, sizeof (rtx));
213194062Svanhu}
214194062Svanhu
215194062Svanhuextern int main PARAMS ((int, char **));
216194062Svanhu
217194062Svanhuint
218194062Svanhumain (argc, argv)
219194062Svanhu     int argc;
220194062Svanhu     char **argv;
221194062Svanhu{
222194062Svanhu  rtx desc;
223194062Svanhu  rtx dummy;
224194062Svanhu  rtx *insns;
225194062Svanhu  rtx *insn_ptr;
226194062Svanhu
227194062Svanhu  progname = "genflags";
228194062Svanhu  obstack_init (&obstack);
229194062Svanhu
230194062Svanhu  if (argc <= 1)
231194062Svanhu    fatal ("no input file name");
232194062Svanhu
233194062Svanhu  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
234194062Svanhu    return (FATAL_EXIT_CODE);
235194062Svanhu
236194062Svanhu  puts ("/* Generated automatically by the program `genflags'");
237194062Svanhu  puts ("   from the machine description file `md'.  */\n");
238105197Ssam  puts ("#ifndef GCC_INSN_FLAGS_H");
239105197Ssam  puts ("#define GCC_INSN_FLAGS_H\n");
240105197Ssam
241105197Ssam  /* Read the machine description.  */
242105197Ssam
243105197Ssam  while (1)
244105197Ssam    {
245105197Ssam      int line_no, insn_code_number = 0;
246105197Ssam
247105197Ssam      desc = read_md_rtx (&line_no, &insn_code_number);
248105197Ssam      if (desc == NULL)
249105197Ssam	break;
250105197Ssam      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
251105197Ssam	gen_insn (desc);
252105197Ssam    }
253105197Ssam
254105197Ssam  /* Print out the prototypes now.  */
255105197Ssam  dummy = (rtx) 0;
256105197Ssam  obstack_grow (&obstack, &dummy, sizeof (rtx));
257105197Ssam  insns = (rtx *) obstack_finish (&obstack);
258105197Ssam
259105197Ssam  printf ("struct rtx_def;\n");
260105197Ssam  for (insn_ptr = insns; *insn_ptr; insn_ptr++)
261105197Ssam    gen_proto (*insn_ptr);
262105197Ssam
263105197Ssam  puts("\n#endif /* GCC_INSN_FLAGS_H */");
264105197Ssam
265105197Ssam  if (ferror (stdout) || fflush (stdout) || fclose (stdout))
266105197Ssam    return FATAL_EXIT_CODE;
267183550Szec
268105197Ssam  return SUCCESS_EXIT_CODE;
269105197Ssam}
270120585Ssam
271120585Ssam/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
272120585Ssamconst char *
273120585Ssamget_insn_name (code)
274105197Ssam     int code ATTRIBUTE_UNUSED;
275105197Ssam{
276105197Ssam  return NULL;
277105197Ssam}
278105197Ssam