]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gengenrtl.c
re PR testsuite/32062 (Some MASKs aren't sufficient in certain sse4_1 tests)
[thirdparty/gcc.git] / gcc / gengenrtl.c
CommitLineData
3b80f6ca 1/* Generate code to allocate RTL structures.
f30278e8 2 Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004
3d7aafde 3 Free Software Foundation, Inc.
3b80f6ca 4
1322177d 5This file is part of GCC.
3b80f6ca 6
1322177d
LB
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
3b80f6ca 11
1322177d
LB
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
3b80f6ca
RH
16
17You should have received a copy of the GNU General Public License
1322177d 18along with GCC; see the file COPYING. If not, write to the Free
366ccddb
KC
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA. */
3b80f6ca
RH
21
22
4977bab6 23#include "bconfig.h"
b04cd507 24#include "system.h"
aa0b4465 25
8f9eb495 26struct rtx_definition
3b80f6ca 27{
8b60264b 28 const char *const enumname, *const name, *const format;
3b80f6ca
RH
29};
30
0974c7d7
ZW
31/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
32 CONST_DOUBLE_FORMAT is because we're not going to be generating
33 anything for CONST_DOUBLE anyway. */
34#define CONST_DOUBLE_FORMAT ""
35
9a238586 36#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
3b80f6ca 37
8f9eb495
AJ
38static const struct rtx_definition defs[] =
39{
3b80f6ca
RH
40#include "rtl.def" /* rtl expressions are documented here */
41};
0974c7d7 42#define NUM_RTX_CODE ARRAY_SIZE(defs)
3b80f6ca 43
0b5826ac 44static const char *formats[NUM_RTX_CODE];
3b80f6ca 45
3d7aafde
AJ
46static const char *type_from_format (int);
47static const char *accessor_from_format (int);
48static int special_format (const char *);
49static int special_rtx (int);
50static int excluded_rtx (int);
51static void find_formats (void);
52static void gendecl (const char *);
53static void genmacro (int);
54static void gendef (const char *);
55static void genlegend (void);
56static void genheader (void);
57static void gencode (void);
c5c76735 58\f
0133b7d9
RH
59/* Decode a format letter into a C type string. */
60
3b80f6ca 61static const char *
3d7aafde 62type_from_format (int c)
3b80f6ca
RH
63{
64 switch (c)
65 {
66 case 'i':
c5c76735
JL
67 return "int ";
68
3b80f6ca 69 case 'w':
c5c76735
JL
70 return "HOST_WIDE_INT ";
71
3b80f6ca 72 case 's':
3cce094d 73 return "const char *";
c5c76735
JL
74
75 case 'e': case 'u':
76 return "rtx ";
77
3b80f6ca 78 case 'E':
c5c76735 79 return "rtvec ";
0dfa1860 80 case 'b':
8f985ec4 81 return "struct bitmap_head_def *"; /* bitmap - typedef not available */
0dfa1860 82 case 't':
8f985ec4 83 return "union tree_node *"; /* tree - typedef not available */
c8ea9a0f
JH
84 case 'B':
85 return "struct basic_block_def *"; /* basic block - typedef not available */
3b80f6ca 86 default:
b2d59f6f 87 gcc_unreachable ();
3b80f6ca
RH
88 }
89}
90
0133b7d9
RH
91/* Decode a format letter into the proper accessor function. */
92
3b80f6ca 93static const char *
3d7aafde 94accessor_from_format (int c)
3b80f6ca
RH
95{
96 switch (c)
97 {
98 case 'i':
99 return "XINT";
c5c76735 100
3b80f6ca
RH
101 case 'w':
102 return "XWINT";
c5c76735 103
3b80f6ca
RH
104 case 's':
105 return "XSTR";
c5c76735
JL
106
107 case 'e': case 'u':
3b80f6ca 108 return "XEXP";
c5c76735 109
3b80f6ca
RH
110 case 'E':
111 return "XVEC";
c5c76735 112
0dfa1860
MM
113 case 'b':
114 return "XBITMAP";
c5c76735 115
0dfa1860
MM
116 case 't':
117 return "XTREE";
c5c76735 118
c8ea9a0f
JH
119 case 'B':
120 return "XBBDEF";
10d1bb36
JH
121
122 default:
b2d59f6f 123 gcc_unreachable ();
3b80f6ca
RH
124 }
125}
126
c5c76735
JL
127/* Return nonzero if we should ignore FMT, an RTL format, when making
128 the list of formats we write routines to create. */
0133b7d9 129
3b80f6ca 130static int
3d7aafde 131special_format (const char *fmt)
3b80f6ca
RH
132{
133 return (strchr (fmt, '*') != 0
134 || strchr (fmt, 'V') != 0
135 || strchr (fmt, 'S') != 0
136 || strchr (fmt, 'n') != 0);
137}
138
5692c7bc
ZW
139/* Return nonzero if the RTL code given by index IDX is one that we should
140 generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
141 is a wrapper in emit-rtl.c). */
0133b7d9 142
3b80f6ca 143static int
3d7aafde 144special_rtx (int idx)
3b80f6ca
RH
145{
146 return (strcmp (defs[idx].enumname, "CONST_INT") == 0
41472af8 147 || strcmp (defs[idx].enumname, "REG") == 0
ddef6bc7 148 || strcmp (defs[idx].enumname, "SUBREG") == 0
a06e3c40
R
149 || strcmp (defs[idx].enumname, "MEM") == 0
150 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
3b80f6ca
RH
151}
152
5692c7bc
ZW
153/* Return nonzero if the RTL code given by index IDX is one that we should
154 generate no macro for at all (because gen_rtx_FOO is never used or
155 cannot have the obvious interface). */
156
157static int
3d7aafde 158excluded_rtx (int idx)
5692c7bc
ZW
159{
160 return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0);
161}
162
dc297297 163/* Place a list of all format specifiers we use into the array FORMAT. */
0133b7d9 164
3b80f6ca 165static void
3d7aafde 166find_formats (void)
3b80f6ca 167{
3ef996b0 168 unsigned int i;
3b80f6ca 169
3ef996b0 170 for (i = 0; i < NUM_RTX_CODE; i++)
3b80f6ca
RH
171 {
172 const char **f;
173
174 if (special_format (defs[i].format))
175 continue;
176
c5c76735 177 for (f = formats; *f; f++)
0133b7d9 178 if (! strcmp (*f, defs[i].format))
3b80f6ca
RH
179 break;
180
c5c76735 181 if (*f == 0)
3b80f6ca
RH
182 *f = defs[i].format;
183 }
184}
185
c5c76735 186/* Write the declarations for the routine to allocate RTL with FORMAT. */
0133b7d9 187
3b80f6ca 188static void
3d7aafde 189gendecl (const char *format)
3b80f6ca
RH
190{
191 const char *p;
c5c76735 192 int i, pos;
8f9eb495 193
3d7aafde 194 printf ("extern rtx gen_rtx_fmt_%s\t (RTX_CODE, ", format);
c5c76735
JL
195 printf ("enum machine_mode mode");
196
197 /* Write each parameter that is needed and start a new line when the line
198 would overflow. */
199 for (p = format, i = 0, pos = 75; *p != 0; p++)
3b80f6ca 200 if (*p != '0')
c5c76735
JL
201 {
202 int ourlen = strlen (type_from_format (*p)) + 6 + (i > 9);
203
204 printf (",");
205 if (pos + ourlen > 76)
206 printf ("\n\t\t\t\t "), pos = 39;
207
208 printf (" %sarg%d", type_from_format (*p), i++);
209 pos += ourlen;
210 }
211
3d7aafde 212 printf (");\n");
3b80f6ca
RH
213}
214
c5c76735
JL
215/* Generate macros to generate RTL of code IDX using the functions we
216 write. */
0133b7d9 217
8f9eb495 218static void
3d7aafde 219genmacro (int idx)
3b80f6ca
RH
220{
221 const char *p;
222 int i;
223
c5c76735
JL
224 /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
225 gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */
3b80f6ca 226
5692c7bc
ZW
227 if (excluded_rtx (idx))
228 /* Don't define a macro for this code. */
229 return;
230
c5c76735
JL
231 printf ("#define gen_rtx_%s%s(MODE",
232 special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
233
234 for (p = defs[idx].format, i = 0; *p != 0; p++)
3b80f6ca 235 if (*p != '0')
c5c76735
JL
236 printf (", ARG%d", i++);
237
238 printf (") \\\n gen_rtx_fmt_%s (%s, (MODE)",
239 defs[idx].format, defs[idx].enumname);
3b80f6ca 240
c5c76735 241 for (p = defs[idx].format, i = 0; *p != 0; p++)
3b80f6ca 242 if (*p != '0')
c5c76735
JL
243 printf (", (ARG%d)", i++);
244
f8a83ee3 245 puts (")");
3b80f6ca
RH
246}
247
c5c76735
JL
248/* Generate the code for the function to generate RTL whose
249 format is FORMAT. */
0133b7d9 250
3b80f6ca 251static void
3d7aafde 252gendef (const char *format)
3b80f6ca
RH
253{
254 const char *p;
255 int i, j;
8f9eb495 256
c5c76735
JL
257 /* Start by writing the definition of the function name and the types
258 of the arguments. */
3b80f6ca 259
6906ba40 260 printf ("rtx\ngen_rtx_fmt_%s (RTX_CODE code, enum machine_mode mode", format);
c5c76735 261 for (p = format, i = 0; *p != 0; p++)
3b80f6ca 262 if (*p != '0')
6906ba40 263 printf (",\n\t%sarg%d", type_from_format (*p), i++);
3b80f6ca 264
6906ba40 265 puts (")");
c5c76735
JL
266
267 /* Now write out the body of the function itself, which allocates
268 the memory and initializes it. */
f8a83ee3
ZW
269 puts ("{");
270 puts (" rtx rt;");
1e8964cf 271 puts (" rt = rtx_alloc (code);\n");
f8a83ee3 272
f8a83ee3 273 puts (" PUT_MODE (rt, mode);");
3b80f6ca
RH
274
275 for (p = format, i = j = 0; *p ; ++p, ++i)
276 if (*p != '0')
c5c76735 277 printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
f8a83ee3
ZW
278 else
279 printf (" X0EXP (rt, %d) = NULL_RTX;\n", i);
3b80f6ca 280
f8a83ee3 281 puts ("\n return rt;\n}\n");
3b80f6ca
RH
282}
283
c5c76735 284/* Generate the documentation header for files we write. */
0133b7d9 285
3b80f6ca 286static void
3d7aafde 287genlegend (void)
3b80f6ca 288{
f8a83ee3 289 puts ("/* Generated automatically by gengenrtl from rtl.def. */\n");
3b80f6ca
RH
290}
291
c5c76735 292/* Generate the text of the header file we make, genrtl.h. */
0133b7d9 293
3b80f6ca 294static void
3d7aafde 295genheader (void)
3b80f6ca 296{
3ef996b0 297 unsigned int i;
3b80f6ca 298 const char **fmt;
0313e85b
ZW
299
300 puts ("#ifndef GCC_GENRTL_H");
301 puts ("#define GCC_GENRTL_H\n");
302
3b80f6ca 303 for (fmt = formats; *fmt; ++fmt)
c5c76735 304 gendecl (*fmt);
3b80f6ca 305
f8a83ee3 306 putchar ('\n');
3b80f6ca 307
3ef996b0 308 for (i = 0; i < NUM_RTX_CODE; i++)
c5c76735
JL
309 if (! special_format (defs[i].format))
310 genmacro (i);
0313e85b
ZW
311
312 puts ("\n#endif /* GCC_GENRTL_H */");
3b80f6ca
RH
313}
314
c5c76735 315/* Generate the text of the code file we write, genrtl.c. */
0133b7d9 316
3b80f6ca 317static void
3d7aafde 318gencode (void)
3b80f6ca
RH
319{
320 const char **fmt;
321
f8a83ee3
ZW
322 puts ("#include \"config.h\"");
323 puts ("#include \"system.h\"");
4977bab6
ZW
324 puts ("#include \"coretypes.h\"");
325 puts ("#include \"tm.h\"");
f8a83ee3
ZW
326 puts ("#include \"obstack.h\"");
327 puts ("#include \"rtl.h\"");
328 puts ("#include \"ggc.h\"\n");
c5c76735
JL
329
330 for (fmt = formats; *fmt != 0; fmt++)
331 gendef (*fmt);
3b80f6ca
RH
332}
333
c5c76735
JL
334/* This is the main program. We accept only one argument, "-h", which
335 says we are writing the genrtl.h file. Otherwise we are writing the
336 genrtl.c file. */
337
3b80f6ca 338int
3d7aafde 339main (int argc, char **argv)
3b80f6ca 340{
3b80f6ca 341 find_formats ();
c5c76735 342 genlegend ();
3b80f6ca 343
c5c76735
JL
344 if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h')
345 genheader ();
346 else
347 gencode ();
3b80f6ca 348
0313e85b
ZW
349 if (ferror (stdout) || fflush (stdout) || fclose (stdout))
350 return FATAL_EXIT_CODE;
351
352 return SUCCESS_EXIT_CODE;
3b80f6ca 353}