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