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.
7 This file is part of GNU CC.
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)
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.
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. */
30 #include "gensupport.h"
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
36 /* Obstack to remember insns with. */
37 static struct obstack obstack
;
39 /* Max size of names encountered. */
40 static int max_id_len
;
42 /* Max operand encountered in a scan over some insn. */
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_macro
PARAMS ((const char *, int, int));
49 static void gen_insn
PARAMS ((rtx
));
51 /* Count the number of match_operand's found. */
57 register RTX_CODE code
;
60 register const char *fmt
;
67 if (code
== MATCH_OPERAND
|| code
== MATCH_OPERATOR
68 || code
== MATCH_PARALLEL
)
69 max_opno
= MAX (max_opno
, XINT (x
, 0));
71 fmt
= GET_RTX_FORMAT (code
);
72 len
= GET_RTX_LENGTH (code
);
73 for (i
= 0; i
< len
; i
++)
75 if (fmt
[i
] == 'e' || fmt
[i
] == 'u')
76 max_operand_1 (XEXP (x
, i
));
77 else if (fmt
[i
] == 'E')
80 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
81 max_operand_1 (XVECEXP (x
, i
, j
));
90 register int len
= XVECLEN (insn
, 1);
95 for (i
= 0; i
< len
; i
++)
96 max_operand_1 (XVECEXP (insn
, 1, i
));
101 /* Print out a wrapper macro for a function which corrects the number
102 of arguments it takes. Any missing arguments are assumed to be at
105 gen_macro (name
, real
, expect
)
116 /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
117 fputs ("#define GEN_", stdout
);
118 for (i
= 0; name
[i
]; i
++)
119 putchar (TOUPPER (name
[i
]));
122 for (i
= 0; i
< expect
- 1; i
++)
123 printf ("%c, ", i
+ 'A');
124 printf ("%c) gen_%s (", i
+ 'A', name
);
126 for (i
= 0; i
< real
- 1; i
++)
127 printf ("(%c), ", i
+ 'A');
128 printf ("(%c))\n", i
+ 'A');
131 /* Print out prototype information for a function. */
137 int num
= num_operands (insn
);
138 const char *name
= XSTR (insn
, 0);
140 /* Many md files don't refer to the last two operands passed to the
141 call patterns. This means their generator functions will be two
142 arguments too short. Instead of changing every md file to touch
143 those operands, we wrap the prototypes in macros that take the
144 correct number of arguments. */
145 if (name
[0] == 'c' || name
[0] == 's')
147 if (!strcmp (name
, "call")
148 || !strcmp (name
, "call_pop")
149 || !strcmp (name
, "sibcall")
150 || !strcmp (name
, "sibcall_pop"))
151 gen_macro (name
, num
, 4);
152 else if (!strcmp (name
, "call_value")
153 || !strcmp (name
, "call_value_pop")
154 || !strcmp (name
, "sibcall_value")
155 || !strcmp (name
, "sibcall_value_pop"))
156 gen_macro (name
, num
, 5);
159 printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len
, name
);
166 printf ("struct rtx_def *, ");
168 printf ("struct rtx_def *");
179 const char *name
= XSTR (insn
, 0);
183 /* Don't mention instructions whose names are the null string
184 or begin with '*'. They are in the machine description just
186 if (name
[0] == 0 || name
[0] == '*')
191 if (len
> max_id_len
)
194 printf ("#define HAVE_%s ", name
);
195 if (strlen (XSTR (insn
, 2)) == 0)
199 /* Write the macro definition, putting \'s at the end of each line,
202 for (p
= XSTR (insn
, 2); *p
; p
++)
212 obstack_grow (&obstack
, &insn
, sizeof (rtx
));
215 extern int main
PARAMS ((int, char **));
227 progname
= "genflags";
228 obstack_init (&obstack
);
231 fatal ("No input file name.");
233 if (init_md_reader (argv
[1]) != SUCCESS_EXIT_CODE
)
234 return (FATAL_EXIT_CODE
);
236 puts ("/* Generated automatically by the program `genflags'");
237 puts (" from the machine description file `md'. */\n");
238 puts ("#ifndef GCC_INSN_FLAGS_H");
239 puts ("#define GCC_INSN_FLAGS_H\n");
241 /* Read the machine description. */
245 int line_no
, insn_code_number
= 0;
247 desc
= read_md_rtx (&line_no
, &insn_code_number
);
250 if (GET_CODE (desc
) == DEFINE_INSN
|| GET_CODE (desc
) == DEFINE_EXPAND
)
254 /* Print out the prototypes now. */
256 obstack_grow (&obstack
, &dummy
, sizeof (rtx
));
257 insns
= (rtx
*) obstack_finish (&obstack
);
259 printf ("struct rtx_def;\n");
260 for (insn_ptr
= insns
; *insn_ptr
; insn_ptr
++)
261 gen_proto (*insn_ptr
);
263 puts("\n#endif /* GCC_INSN_FLAGS_H */");
265 if (ferror (stdout
) || fflush (stdout
) || fclose (stdout
))
266 return FATAL_EXIT_CODE
;
268 return SUCCESS_EXIT_CODE
;
271 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
274 int code ATTRIBUTE_UNUSED
;