]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genextract.c
sh.c: Do not include algorithm.
[thirdparty/gcc.git] / gcc / genextract.c
CommitLineData
41299f41 1/* Generate code from machine description to extract operands from insn as rtl.
23a5b65a 2 Copyright (C) 1987-2014 Free Software Foundation, Inc.
41299f41 3
1322177d 4This file is part of GCC.
41299f41 5
1322177d
LB
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
1322177d 9version.
41299f41 10
1322177d
LB
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
41299f41
TW
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
41299f41
TW
19
20
4977bab6 21#include "bconfig.h"
0b93b64e 22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
41299f41 25#include "rtl.h"
f8b6598e 26#include "errors.h"
10692477 27#include "read-md.h"
c88c0d42 28#include "gensupport.h"
245fc639 29#include "vec.h"
41299f41 30
9482d6de 31/* This structure contains all the information needed to describe one
3d7aafde 32 set of extractions methods. Each method may be used by more than
9482d6de
RK
33 one pattern if the operands are in the same place.
34
35 The string for each operand describes that path to the operand and
36 contains `0' through `9' when going into an expression and `a' through
37 `z' when going into a vector. We assume here that only the first operand
38 of an rtl expression is a vector. genrecog.c makes the same assumption
39 (and uses the same representation) and it is currently true. */
40
245fc639
ZW
41typedef char *locstr;
42
9482d6de
RK
43struct extraction
44{
245fc639
ZW
45 unsigned int op_count;
46 unsigned int dup_count;
47 locstr *oplocs;
48 locstr *duplocs;
49 int *dupnums;
9482d6de
RK
50 struct code_ptr *insns;
51 struct extraction *next;
52};
53
245fc639 54/* Holds a single insn code that uses an extraction method. */
9482d6de
RK
55struct code_ptr
56{
57 int insn_code;
58 struct code_ptr *next;
59};
60
245fc639 61/* All extractions needed for this machine description. */
9482d6de
RK
62static struct extraction *extractions;
63
245fc639
ZW
64/* All insn codes for old-style peepholes. */
65static struct code_ptr *peepholes;
41299f41 66
245fc639
ZW
67/* This structure is used by gen_insn and walk_rtx to accumulate the
68 data that will be used to produce an extractions structure. */
41299f41 69
41299f41 70
245fc639
ZW
71struct accum_extract
72{
9771b263
DN
73 vec<locstr> oplocs;
74 vec<locstr> duplocs;
75 vec<int> dupnums;
76 vec<char> pathstr;
245fc639 77};
41299f41 78
7ddf71e3
PB
79int line_no;
80
245fc639
ZW
81/* Forward declarations. */
82static void walk_rtx (rtx, struct accum_extract *);
f8b6598e 83
41299f41 84static void
245fc639 85gen_insn (rtx insn, int insn_code_number)
41299f41 86{
b3694847 87 int i;
245fc639 88 unsigned int op_count, dup_count, j;
b3694847
SS
89 struct extraction *p;
90 struct code_ptr *link;
245fc639 91 struct accum_extract acc;
41299f41 92
9771b263
DN
93 acc.oplocs.create (10);
94 acc.duplocs.create (10);
95 acc.dupnums.create (10);
96 acc.pathstr.create (20);
41299f41
TW
97
98 /* Walk the insn's pattern, remembering at all times the path
99 down to the walking point. */
100
101 if (XVECLEN (insn, 1) == 1)
245fc639 102 walk_rtx (XVECEXP (insn, 1, 0), &acc);
41299f41
TW
103 else
104 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
105 {
9771b263 106 acc.pathstr.safe_push ('a' + i);
245fc639 107 walk_rtx (XVECEXP (insn, 1, i), &acc);
9771b263 108 acc.pathstr.pop ();
41299f41 109 }
41299f41 110
245fc639 111 link = XNEW (struct code_ptr);
9482d6de
RK
112 link->insn_code = insn_code_number;
113
0f41302f 114 /* See if we find something that already had this extraction method. */
9482d6de 115
9771b263
DN
116 op_count = acc.oplocs.length ();
117 dup_count = acc.duplocs.length ();
118 gcc_assert (dup_count == acc.dupnums.length ());
245fc639 119
9482d6de 120 for (p = extractions; p; p = p->next)
41299f41 121 {
9482d6de
RK
122 if (p->op_count != op_count || p->dup_count != dup_count)
123 continue;
124
245fc639
ZW
125 for (j = 0; j < op_count; j++)
126 {
127 char *a = p->oplocs[j];
9771b263 128 char *b = acc.oplocs[j];
245fc639
ZW
129 if (a != b && (!a || !b || strcmp (a, b)))
130 break;
131 }
9482d6de 132
245fc639 133 if (j != op_count)
9482d6de
RK
134 continue;
135
245fc639 136 for (j = 0; j < dup_count; j++)
9771b263
DN
137 if (p->dupnums[j] != acc.dupnums[j]
138 || strcmp (p->duplocs[j], acc.duplocs[j]))
9482d6de
RK
139 break;
140
245fc639 141 if (j != dup_count)
9482d6de
RK
142 continue;
143
144 /* This extraction is the same as ours. Just link us in. */
145 link->next = p->insns;
146 p->insns = link;
245fc639 147 goto done;
41299f41
TW
148 }
149
245fc639
ZW
150 /* Otherwise, make a new extraction method. We stash the arrays
151 after the extraction structure in memory. */
41299f41 152
7cbb2a85 153 p = XNEWVAR (struct extraction, sizeof (struct extraction)
245fc639
ZW
154 + op_count*sizeof (char *)
155 + dup_count*sizeof (char *)
156 + dup_count*sizeof (int));
9482d6de
RK
157 p->op_count = op_count;
158 p->dup_count = dup_count;
159 p->next = extractions;
160 extractions = p;
161 p->insns = link;
162 link->next = 0;
163
245fc639
ZW
164 p->oplocs = (char **)((char *)p + sizeof (struct extraction));
165 p->duplocs = p->oplocs + op_count;
166 p->dupnums = (int *)(p->duplocs + dup_count);
9482d6de 167
c3284718
RS
168 memcpy (p->oplocs, acc.oplocs.address (), op_count * sizeof (locstr));
169 memcpy (p->duplocs, acc.duplocs.address (), dup_count * sizeof (locstr));
170 memcpy (p->dupnums, acc.dupnums.address (), dup_count * sizeof (int));
245fc639
ZW
171
172 done:
9771b263
DN
173 acc.oplocs.release ();
174 acc.duplocs.release ();
175 acc.dupnums.release ();
176 acc.pathstr.release ();
9482d6de
RK
177}
178\f
9771b263 179/* Helper subroutine of walk_rtx: given a vec<locstr>, an index, and a
245fc639
ZW
180 string, insert the string at the index, which should either already
181 exist and be NULL, or not yet exist within the vector. In the latter
182 case the vector is enlarged as appropriate. */
41299f41 183static void
9771b263 184VEC_safe_set_locstr (vec<locstr> *vp, unsigned int ix, char *str)
245fc639 185{
9771b263 186 if (ix < (*vp).length ())
245fc639 187 {
9771b263 188 if ((*vp)[ix])
7ddf71e3
PB
189 {
190 message_with_line (line_no, "repeated operand number %d", ix);
191 have_error = 1;
192 }
193 else
9771b263 194 (*vp)[ix] = str;
245fc639
ZW
195 }
196 else
197 {
9771b263
DN
198 while (ix > (*vp).length ())
199 vp->safe_push (NULL);
200 vp->safe_push (str);
245fc639
ZW
201 }
202}
203
9771b263 204/* Another helper subroutine of walk_rtx: given a vec<char>, convert it
245fc639
ZW
205 to a NUL-terminated string in malloc memory. */
206static char *
9771b263 207VEC_char_to_string (vec<char> v)
245fc639 208{
9771b263 209 size_t n = v.length ();
5ed6ace5 210 char *s = XNEWVEC (char, n + 1);
9771b263 211 memcpy (s, v.address (), n);
245fc639
ZW
212 s[n] = '\0';
213 return s;
214}
215
216static void
217walk_rtx (rtx x, struct accum_extract *acc)
41299f41 218{
b3694847 219 RTX_CODE code;
245fc639 220 int i, len, base;
b3694847 221 const char *fmt;
41299f41
TW
222
223 if (x == 0)
224 return;
225
226 code = GET_CODE (x);
41299f41
TW
227 switch (code)
228 {
229 case PC:
230 case CC0:
231 case CONST_INT:
232 case SYMBOL_REF:
233 return;
234
235 case MATCH_OPERAND:
236 case MATCH_SCRATCH:
11daaf60 237 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
245fc639 238 VEC_char_to_string (acc->pathstr));
41299f41
TW
239 break;
240
41299f41 241 case MATCH_OPERATOR:
245fc639 242 case MATCH_PARALLEL:
11daaf60 243 VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
245fc639 244 VEC_char_to_string (acc->pathstr));
9482d6de 245
245fc639 246 base = (code == MATCH_OPERATOR ? '0' : 'a');
41299f41
TW
247 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
248 {
9771b263 249 acc->pathstr.safe_push (base + i);
245fc639 250 walk_rtx (XVECEXP (x, 2, i), acc);
9771b263 251 acc->pathstr.pop ();
245fc639 252 }
41299f41
TW
253 return;
254
245fc639
ZW
255 case MATCH_DUP:
256 case MATCH_PAR_DUP:
257 case MATCH_OP_DUP:
9771b263
DN
258 acc->duplocs.safe_push (VEC_char_to_string (acc->pathstr));
259 acc->dupnums.safe_push (XINT (x, 0));
9482d6de 260
245fc639
ZW
261 if (code == MATCH_DUP)
262 break;
41299f41 263
245fc639
ZW
264 base = (code == MATCH_OP_DUP ? '0' : 'a');
265 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
266 {
9771b263 267 acc->pathstr.safe_push (base + i);
245fc639 268 walk_rtx (XVECEXP (x, 1, i), acc);
9771b263 269 acc->pathstr.pop ();
245fc639 270 }
41299f41 271 return;
ccd043a9
RL
272
273 default:
274 break;
41299f41
TW
275 }
276
41299f41
TW
277 fmt = GET_RTX_FORMAT (code);
278 len = GET_RTX_LENGTH (code);
279 for (i = 0; i < len; i++)
280 {
41299f41
TW
281 if (fmt[i] == 'e' || fmt[i] == 'u')
282 {
9771b263 283 acc->pathstr.safe_push ('0' + i);
245fc639 284 walk_rtx (XEXP (x, i), acc);
9771b263 285 acc->pathstr.pop ();
41299f41
TW
286 }
287 else if (fmt[i] == 'E')
288 {
289 int j;
290 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
291 {
9771b263 292 acc->pathstr.safe_push ('a' + j);
245fc639 293 walk_rtx (XVECEXP (x, i, j), acc);
9771b263 294 acc->pathstr.pop ();
41299f41
TW
295 }
296 }
297 }
298}
299
300/* Given a PATH, representing a path down the instruction's
301 pattern from the root to a certain point, output code to
302 evaluate to the rtx at that point. */
303
304static void
3d7aafde 305print_path (const char *path)
41299f41 306{
b3694847
SS
307 int len = strlen (path);
308 int i;
9482d6de 309
07704a9a
RE
310 if (len == 0)
311 {
312 /* Don't emit "pat", since we may try to take the address of it,
313 which isn't what is intended. */
245fc639 314 fputs ("PATTERN (insn)", stdout);
07704a9a
RE
315 return;
316 }
317
9482d6de 318 /* We first write out the operations (XEXP or XVECEXP) in reverse
245fc639 319 order, then write "pat", then the indices in forward order. */
9482d6de 320
6a87d634 321 for (i = len - 1; i >= 0 ; i--)
41299f41 322 {
245fc639
ZW
323 if (ISLOWER (path[i]))
324 fputs ("XVECEXP (", stdout);
325 else if (ISDIGIT (path[i]))
326 fputs ("XEXP (", stdout);
9482d6de 327 else
b2d59f6f 328 gcc_unreachable ();
41299f41 329 }
3d7aafde 330
245fc639 331 fputs ("pat", stdout);
9482d6de
RK
332
333 for (i = 0; i < len; i++)
41299f41 334 {
245fc639 335 if (ISLOWER (path[i]))
9482d6de 336 printf (", 0, %d)", path[i] - 'a');
c3284718 337 else if (ISDIGIT (path[i]))
9482d6de
RK
338 printf (", %d)", path[i] - '0');
339 else
b2d59f6f 340 gcc_unreachable ();
41299f41
TW
341 }
342}
343\f
245fc639
ZW
344static void
345print_header (void)
346{
347 /* N.B. Code below avoids putting squiggle braces in column 1 inside
348 a string, because this confuses some editors' syntax highlighting
349 engines. */
350
351 puts ("\
352/* Generated automatically by the program `genextract'\n\
353 from the machine description file `md'. */\n\
354\n\
355#include \"config.h\"\n\
356#include \"system.h\"\n\
357#include \"coretypes.h\"\n\
358#include \"tm.h\"\n\
359#include \"rtl.h\"\n\
360#include \"insn-config.h\"\n\
361#include \"recog.h\"\n\
79a3f089 362#include \"diagnostic-core.h\"\n\
245fc639
ZW
363\n\
364/* This variable is used as the \"location\" of any missing operand\n\
365 whose numbers are skipped by a given pattern. */\n\
366static rtx junk ATTRIBUTE_UNUSED;\n");
367
368 puts ("\
369void\n\
d0bffe55 370insn_extract (rtx_insn *insn)\n{\n\
245fc639
ZW
371 rtx *ro = recog_data.operand;\n\
372 rtx **ro_loc = recog_data.operand_loc;\n\
373 rtx pat = PATTERN (insn);\n\
374 int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\
375\n\
376#ifdef ENABLE_CHECKING\n\
377 memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\
378 memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\
379#endif\n");
380
381 puts ("\
382 switch (INSN_CODE (insn))\n\
383 {\n\
384 default:\n\
385 /* Control reaches here if insn_extract has been called with an\n\
386 unrecognizable insn (code -1), or an insn whose INSN_CODE\n\
387 corresponds to a DEFINE_EXPAND in the machine description;\n\
388 either way, a bug. */\n\
389 if (INSN_CODE (insn) < 0)\n\
390 fatal_insn (\"unrecognizable insn:\", insn);\n\
391 else\n\
392 fatal_insn (\"insn with invalid code number:\", insn);\n");
393}
c1b59dce 394
41299f41 395int
3d7aafde 396main (int argc, char **argv)
41299f41
TW
397{
398 rtx desc;
245fc639 399 unsigned int i;
9482d6de
RK
400 struct extraction *p;
401 struct code_ptr *link;
8ad1aa56 402 const char *name;
245fc639 403 int insn_code_number;
41299f41 404
f8b6598e 405 progname = "genextract";
41299f41 406
600ab3fc 407 if (!init_rtx_reader_args (argc, argv))
c88c0d42 408 return (FATAL_EXIT_CODE);
41299f41 409
41299f41
TW
410 /* Read the machine description. */
411
245fc639 412 while ((desc = read_md_rtx (&line_no, &insn_code_number)) != NULL)
41299f41 413 {
c88c0d42 414 if (GET_CODE (desc) == DEFINE_INSN)
0458fe77 415 gen_insn (desc, insn_code_number);
9482d6de
RK
416
417 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
41299f41 418 {
5ed6ace5 419 struct code_ptr *link = XNEW (struct code_ptr);
9482d6de
RK
420
421 link->insn_code = insn_code_number;
422 link->next = peepholes;
423 peepholes = link;
41299f41 424 }
9482d6de 425 }
41299f41 426
7ddf71e3
PB
427 if (have_error)
428 return FATAL_EXIT_CODE;
429
245fc639
ZW
430 print_header ();
431
9482d6de
RK
432 /* Write out code to handle peepholes and the insn_codes that it should
433 be called for. */
434 if (peepholes)
41299f41 435 {
9482d6de
RK
436 for (link = peepholes; link; link = link->next)
437 printf (" case %d:\n", link->insn_code);
438
41299f41
TW
439 /* The vector in the insn says how many operands it has.
440 And all it contains are operands. In fact, the vector was
2dbbe435
HPN
441 created just for the sake of this function. We need to set the
442 location of the operands for sake of simplifications after
443 extraction, like eliminating subregs. */
245fc639
ZW
444 puts (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n"
445 " ro[i] = *(ro_loc[i] = &XVECEXP (pat, 0, i));\n"
446 " break;\n");
9482d6de
RK
447 }
448
449 /* Write out all the ways to extract insn operands. */
450 for (p = extractions; p; p = p->next)
451 {
452 for (link = p->insns; link; link = link->next)
8ad1aa56
ZW
453 {
454 i = link->insn_code;
455 name = get_insn_name (i);
456 if (name)
457 printf (" case %d: /* %s */\n", i, name);
458 else
459 printf (" case %d:\n", i);
460 }
3d7aafde 461
9482d6de
RK
462 for (i = 0; i < p->op_count; i++)
463 {
464 if (p->oplocs[i] == 0)
465 {
466 printf (" ro[%d] = const0_rtx;\n", i);
8b5ba7f8 467 printf (" ro_loc[%d] = &junk;\n", i);
9482d6de
RK
468 }
469 else
470 {
471 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
472 print_path (p->oplocs[i]);
245fc639 473 puts (");");
9482d6de
RK
474 }
475 }
476
477 for (i = 0; i < p->dup_count; i++)
478 {
1ccbefce 479 printf (" recog_data.dup_loc[%d] = &", i);
9482d6de 480 print_path (p->duplocs[i]);
245fc639 481 puts (";");
1ccbefce 482 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
9482d6de
RK
483 }
484
245fc639 485 puts (" break;\n");
41299f41
TW
486 }
487
245fc639 488 puts (" }\n}");
41299f41 489 fflush (stdout);
c1b59dce 490 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
41299f41 491}