Line data Source code
1 : /* RTL reader for GCC.
2 : Copyright (C) 1987-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : /* This file is compiled twice: once for the generator programs
21 : once for the compiler. */
22 : #ifdef GENERATOR_FILE
23 : #include "bconfig.h"
24 : #else
25 : #include "config.h"
26 : #endif
27 :
28 : /* Disable rtl checking; it conflicts with the iterator handling. */
29 : #undef ENABLE_RTL_CHECKING
30 :
31 : #include "system.h"
32 : #include "coretypes.h"
33 : #include "tm.h"
34 : #include "rtl.h"
35 : #include "obstack.h"
36 : #include "read-md.h"
37 : #include "gensupport.h"
38 :
39 : /* One element in a singly-linked list of (integer, string) pairs. */
40 : struct map_value {
41 : struct map_value *next;
42 : int number;
43 : const char *string;
44 : };
45 :
46 : /* Maps an iterator or attribute name to a list of (integer, string) pairs.
47 : The integers are iterator values; the strings are either C conditions
48 : or attribute values. */
49 : struct mapping {
50 : /* The name of the iterator or attribute. */
51 : const char *name;
52 :
53 : /* The group (modes or codes) to which the iterator or attribute belongs. */
54 : struct iterator_group *group;
55 :
56 : /* The list of (integer, string) pairs. */
57 : struct map_value *values;
58 :
59 : /* For iterators, records the current value of the iterator. */
60 : struct map_value *current_value;
61 : };
62 :
63 : /* A structure for abstracting the common parts of iterators. */
64 : struct iterator_group {
65 : /* Tables of "mapping" structures, one for attributes and one for
66 : iterators. */
67 : htab_t attrs, iterators;
68 :
69 : /* The C++ type of the iterator, such as "machine_mode" for modes. */
70 : const char *type;
71 :
72 : /* Treat the given string as the name of a standard mode, etc., and
73 : return its integer value. */
74 : HOST_WIDE_INT (*find_builtin) (const char *);
75 :
76 : /* Make the given rtx use the iterator value given by the third argument.
77 : If the iterator applies to operands, the second argument gives the
78 : operand index, otherwise it is ignored. */
79 : void (*apply_iterator) (rtx, unsigned int, HOST_WIDE_INT);
80 :
81 : /* Return the C token for the given standard mode, code, etc. */
82 : const char *(*get_c_token) (int);
83 :
84 : /* True if each iterator name should be treated as an attribute that
85 : maps to the C token produced by get_c_token. This means that for
86 : an iterator ITER, <ITER> can be used in strings to refer to the
87 : current value of ITER, as a C token. */
88 : bool has_self_attr;
89 : };
90 :
91 : /* Records one use of an iterator. */
92 : struct iterator_use {
93 : /* The iterator itself. */
94 : struct mapping *iterator;
95 :
96 : /* The location of the use, as passed to the apply_iterator callback.
97 : The index is the number of the operand that used the iterator
98 : if applicable, otherwise it is ignored. */
99 : rtx x;
100 : unsigned int index;
101 : };
102 :
103 : /* Records one use of an attribute (the "<[iterator:]attribute>" syntax)
104 : in a non-string rtx field. */
105 : struct attribute_use {
106 : /* The group that describes the use site. */
107 : struct iterator_group *group;
108 :
109 : /* The location at which the use occurs. */
110 : file_location loc;
111 :
112 : /* The name of the attribute, possibly with an "iterator:" prefix. */
113 : const char *value;
114 :
115 : /* The location of the use, as passed to GROUP's apply_iterator callback.
116 : The index is the number of the operand that used the iterator
117 : if applicable, otherwise it is ignored. */
118 : rtx x;
119 : unsigned int index;
120 : };
121 :
122 : /* This struct is used to link subst_attr named ATTR_NAME with
123 : corresponding define_subst named ITER_NAME. */
124 : struct subst_attr_to_iter_mapping
125 : {
126 : char *attr_name;
127 : char *iter_name;
128 : };
129 :
130 : /* Hash-table to store links between subst-attributes and
131 : define_substs. */
132 : htab_t subst_attr_to_iter_map = NULL;
133 : /* This global stores name of subst-iterator which is currently being
134 : processed. */
135 : const char *current_iterator_name;
136 :
137 : static void validate_const_int (const char *);
138 : static void one_time_initialization (void);
139 :
140 : /* Global singleton. */
141 : rtx_reader *rtx_reader_ptr = NULL;
142 :
143 : /* The mode and code iterator structures. */
144 : static struct iterator_group modes, codes, ints, substs;
145 :
146 : /* All iterators used in the current rtx. */
147 : static vec<mapping *> current_iterators;
148 :
149 : /* The list of all iterator uses in the current rtx. */
150 : static vec<iterator_use> iterator_uses;
151 :
152 : /* The list of all attribute uses in the current rtx. */
153 : static vec<attribute_use> attribute_uses;
154 :
155 : /* Provide a version of a function to read a long long if the system does
156 : not provide one. */
157 : #if (HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG \
158 : && !HAVE_DECL_ATOLL \
159 : && !defined (HAVE_ATOQ))
160 : HOST_WIDE_INT atoll (const char *);
161 :
162 : HOST_WIDE_INT
163 : atoll (const char *p)
164 : {
165 : int neg = 0;
166 : HOST_WIDE_INT tmp_wide;
167 :
168 : while (ISSPACE (*p))
169 : p++;
170 : if (*p == '-')
171 : neg = 1, p++;
172 : else if (*p == '+')
173 : p++;
174 :
175 : tmp_wide = 0;
176 : while (ISDIGIT (*p))
177 : {
178 : HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
179 : if (new_wide < tmp_wide)
180 : {
181 : /* Return INT_MAX equiv on overflow. */
182 : tmp_wide = HOST_WIDE_INT_M1U >> 1;
183 : break;
184 : }
185 : tmp_wide = new_wide;
186 : p++;
187 : }
188 :
189 : if (neg)
190 : tmp_wide = -tmp_wide;
191 : return tmp_wide;
192 : }
193 : #endif
194 :
195 : /* Implementations of the iterator_group callbacks for modes. */
196 :
197 : static HOST_WIDE_INT
198 1044 : find_mode (const char *name)
199 : {
200 1044 : machine_mode mode;
201 1044 : if (!parse_machine_mode (name, &mode))
202 0 : fatal_with_file_and_line ("unknown mode `%s'", name);
203 :
204 1044 : return (HOST_WIDE_INT) mode;
205 : }
206 :
207 : static void
208 1044 : apply_mode_iterator (rtx x, unsigned int, HOST_WIDE_INT mode)
209 : {
210 1044 : PUT_MODE (x, (machine_mode) mode);
211 1044 : }
212 :
213 : static const char *
214 0 : get_mode_token (int mode)
215 : {
216 0 : return concat ("E_", GET_MODE_NAME (mode), "mode", NULL);
217 : }
218 :
219 : /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn",
220 : "cnote" etc, and CODE_LABEL is special-cased as "clabel". */
221 :
222 : struct compact_insn_name {
223 : RTX_CODE code;
224 : const char *name;
225 : };
226 :
227 : static const compact_insn_name compact_insn_names[] = {
228 : { DEBUG_INSN, "cdebug_insn" },
229 : { INSN, "cinsn" },
230 : { JUMP_INSN, "cjump_insn" },
231 : { CALL_INSN, "ccall_insn" },
232 : { JUMP_TABLE_DATA, "cjump_table_data" },
233 : { BARRIER, "cbarrier" },
234 : { CODE_LABEL, "clabel" },
235 : { NOTE, "cnote" }
236 : };
237 :
238 : /* Return the rtx code for NAME, or UNKNOWN if NAME isn't a valid rtx code. */
239 :
240 : static rtx_code
241 2218 : maybe_find_code (const char *name)
242 : {
243 143911 : for (int i = 0; i < NUM_RTX_CODE; i++)
244 143434 : if (strcmp (GET_RTX_NAME (i), name) == 0)
245 1741 : return (rtx_code) i;
246 :
247 2042 : for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++)
248 2041 : if (strcmp (compact_insn_names[i].name, name) == 0)
249 476 : return compact_insn_names[i].code;
250 :
251 : return UNKNOWN;
252 : }
253 :
254 : /* Implementations of the iterator_group callbacks for codes. */
255 :
256 : static HOST_WIDE_INT
257 2218 : find_code (const char *name)
258 : {
259 2218 : rtx_code code = maybe_find_code (name);
260 2218 : if (code == UNKNOWN)
261 1 : fatal_with_file_and_line ("unknown rtx code `%s'", name);
262 2217 : return code;
263 : }
264 :
265 : static void
266 0 : apply_code_iterator (rtx x, unsigned int, HOST_WIDE_INT code)
267 : {
268 0 : PUT_CODE (x, (enum rtx_code) code);
269 0 : }
270 :
271 : static const char *
272 0 : get_code_token (int code)
273 : {
274 0 : char *name = xstrdup (GET_RTX_NAME (code));
275 0 : for (int i = 0; name[i]; ++i)
276 0 : name[i] = TOUPPER (name[i]);
277 0 : return name;
278 : }
279 :
280 : /* Implementations of the iterator_group callbacks for ints. */
281 :
282 : /* Since GCC does not construct a table of valid constants,
283 : we have to accept any int as valid. No cross-checking can
284 : be done. */
285 :
286 : static HOST_WIDE_INT
287 244 : find_int (const char *name)
288 : {
289 244 : HOST_WIDE_INT tmp;
290 :
291 244 : struct md_constant tmp_def;
292 244 : tmp_def.name = const_cast<char *> (name);
293 244 : auto htab = rtx_reader_ptr->get_md_constants ();
294 244 : if (auto def = (struct md_constant *) htab_find (htab, &tmp_def))
295 0 : name = def->value;
296 :
297 244 : validate_const_int (name);
298 : #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
299 : tmp = atoi (name);
300 : #else
301 : #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
302 244 : tmp = atol (name);
303 : #else
304 : /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
305 : But prefer not to use our hand-rolled function above either. */
306 : #if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ)
307 : tmp = atoll (name);
308 : #else
309 : tmp = atoq (name);
310 : #endif
311 : #endif
312 : #endif
313 244 : return tmp;
314 : }
315 :
316 : static void
317 244 : apply_int_iterator (rtx x, unsigned int index, HOST_WIDE_INT value)
318 : {
319 244 : RTX_CODE code = GET_CODE (x);
320 244 : const char *format_ptr = GET_RTX_FORMAT (code);
321 :
322 244 : switch (format_ptr[index])
323 : {
324 0 : case 'i':
325 0 : case 'n':
326 0 : XINT (x, index) = value;
327 0 : break;
328 0 : case 'L':
329 0 : XLOC (x, index) = value;
330 0 : break;
331 240 : case 'w':
332 240 : XWINT (x, index) = value;
333 240 : break;
334 4 : case 'p':
335 4 : gcc_assert (code == SUBREG);
336 4 : SUBREG_BYTE (x) = value;
337 4 : break;
338 0 : default:
339 0 : gcc_unreachable ();
340 : }
341 244 : }
342 :
343 : static const char *
344 0 : get_int_token (int value)
345 : {
346 0 : char buffer[HOST_BITS_PER_INT + 1];
347 0 : sprintf (buffer, "%d", value);
348 0 : return xstrdup (buffer);
349 : }
350 :
351 : #ifdef GENERATOR_FILE
352 :
353 : /* This routine adds attribute or does nothing depending on VALUE. When
354 : VALUE is 1, it does nothing - the first duplicate of original
355 : template is kept untouched when it's subjected to a define_subst.
356 : When VALUE isn't 1, the routine modifies RTL-template RT, adding
357 : attribute, named exactly as define_subst, which later will be
358 : applied. If such attribute has already been added, then no the
359 : routine has no effect. */
360 : static void
361 : apply_subst_iterator (rtx rt, unsigned int, HOST_WIDE_INT value)
362 : {
363 : rtx new_attr;
364 : rtvec attrs_vec, new_attrs_vec;
365 : int i;
366 : /* define_split has no attributes. */
367 : if (value == 1 || GET_CODE (rt) == DEFINE_SPLIT)
368 : return;
369 : gcc_assert (GET_CODE (rt) == DEFINE_INSN
370 : || GET_CODE (rt) == DEFINE_INSN_AND_SPLIT
371 : || GET_CODE (rt) == DEFINE_INSN_AND_REWRITE
372 : || GET_CODE (rt) == DEFINE_EXPAND);
373 :
374 : int attrs = (GET_CODE (rt) == DEFINE_INSN_AND_SPLIT ? 7
375 : : GET_CODE (rt) == DEFINE_INSN_AND_REWRITE ? 6 : 4);
376 : attrs_vec = XVEC (rt, attrs);
377 :
378 : /* If we've already added attribute 'current_iterator_name', then we
379 : have nothing to do now. */
380 : if (attrs_vec)
381 : {
382 : for (i = 0; i < GET_NUM_ELEM (attrs_vec); i++)
383 : {
384 : if (strcmp (XSTR (attrs_vec->elem[i], 0), current_iterator_name) == 0)
385 : return;
386 : }
387 : }
388 :
389 : /* Add attribute with subst name - it serves as a mark for
390 : define_subst which later would be applied to this pattern. */
391 : new_attr = rtx_alloc (SET_ATTR);
392 : PUT_CODE (new_attr, SET_ATTR);
393 : XSTR (new_attr, 0) = xstrdup (current_iterator_name);
394 : XSTR (new_attr, 1) = xstrdup ("yes");
395 :
396 : if (!attrs_vec)
397 : {
398 : new_attrs_vec = rtvec_alloc (1);
399 : new_attrs_vec->elem[0] = new_attr;
400 : }
401 : else
402 : {
403 : new_attrs_vec = rtvec_alloc (GET_NUM_ELEM (attrs_vec) + 1);
404 : memcpy (&new_attrs_vec->elem[0], &attrs_vec->elem[0],
405 : GET_NUM_ELEM (attrs_vec) * sizeof (rtx));
406 : new_attrs_vec->elem[GET_NUM_ELEM (attrs_vec)] = new_attr;
407 : }
408 : XVEC (rt, attrs) = new_attrs_vec;
409 : }
410 :
411 : /* Map subst-attribute ATTR to subst iterator ITER. */
412 :
413 : static void
414 : bind_subst_iter_and_attr (const char *iter, const char *attr)
415 : {
416 : struct subst_attr_to_iter_mapping *value;
417 : void **slot;
418 : if (!subst_attr_to_iter_map)
419 : subst_attr_to_iter_map =
420 : htab_create (1, leading_string_hash, leading_string_eq_p, 0);
421 : value = XNEW (struct subst_attr_to_iter_mapping);
422 : value->attr_name = xstrdup (attr);
423 : value->iter_name = xstrdup (iter);
424 : slot = htab_find_slot (subst_attr_to_iter_map, value, INSERT);
425 : *slot = value;
426 : }
427 :
428 : #endif /* #ifdef GENERATOR_FILE */
429 :
430 : /* Return name of a subst-iterator, corresponding to subst-attribute ATTR. */
431 :
432 : static char*
433 0 : find_subst_iter_by_attr (const char *attr)
434 : {
435 0 : char *iter_name = NULL;
436 0 : struct subst_attr_to_iter_mapping *value;
437 0 : value = (struct subst_attr_to_iter_mapping*)
438 0 : htab_find (subst_attr_to_iter_map, &attr);
439 0 : if (value)
440 0 : iter_name = value->iter_name;
441 0 : return iter_name;
442 : }
443 :
444 : /* Map attribute string P to its current value. Return null if the attribute
445 : isn't known. If ITERATOR_OUT is nonnull, store the associated iterator
446 : there. Report any errors against location LOC. */
447 :
448 : static struct map_value *
449 0 : map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0)
450 : {
451 0 : const char *attr;
452 0 : struct mapping *iterator;
453 0 : unsigned int i;
454 0 : struct mapping *m;
455 0 : struct map_value *v;
456 0 : int iterator_name_len;
457 0 : struct map_value *res = NULL;
458 0 : struct mapping *prev = NULL;
459 :
460 : /* Peel off any "iterator:" prefix. Set ATTR to the start of the
461 : attribute name. */
462 0 : attr = strchr (p, ':');
463 0 : if (attr == 0)
464 : {
465 0 : iterator_name_len = -1;
466 : attr = p;
467 : }
468 : else
469 : {
470 0 : iterator_name_len = attr - p;
471 0 : attr++;
472 : }
473 :
474 0 : FOR_EACH_VEC_ELT (current_iterators, i, iterator)
475 : {
476 : /* If an iterator name was specified, check that it matches. */
477 0 : if (iterator_name_len >= 0
478 0 : && (strncmp (p, iterator->name, iterator_name_len) != 0
479 0 : || iterator->name[iterator_name_len] != 0))
480 0 : continue;
481 :
482 0 : if (iterator->group->has_self_attr
483 0 : && strcmp (attr, iterator->name) == 0)
484 : {
485 0 : if (iterator_out)
486 0 : *iterator_out = iterator;
487 0 : int number = iterator->current_value->number;
488 0 : const char *string = iterator->group->get_c_token (number);
489 0 : if (res && strcmp (string, res->string) != 0)
490 : {
491 0 : error_at (loc, "ambiguous attribute '%s'; could be"
492 : " '%s' (via '%s:%s') or '%s' (via '%s:%s')",
493 : attr, res->string, prev->name, attr,
494 : string, iterator->name, attr);
495 0 : return res;
496 : }
497 0 : prev = iterator;
498 0 : res = new map_value { nullptr, number, string };
499 : }
500 :
501 : /* Find the attribute specification. */
502 0 : m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
503 0 : if (m)
504 : {
505 : /* In contrast to code/mode/int iterators, attributes of subst
506 : iterators are linked to one specific subst-iterator. So, if
507 : we are dealing with subst-iterator, we should check if it's
508 : the one which linked with the given attribute. */
509 0 : if (iterator->group == &substs)
510 : {
511 0 : char *iter_name = find_subst_iter_by_attr (attr);
512 0 : if (strcmp (iter_name, iterator->name) != 0)
513 0 : continue;
514 : }
515 : /* Find the attribute value associated with the current
516 : iterator value. */
517 0 : for (v = m->values; v; v = v->next)
518 0 : if (v->number == iterator->current_value->number)
519 : {
520 0 : if (res && strcmp (v->string, res->string) != 0)
521 : {
522 0 : error_at (loc, "ambiguous attribute '%s'; could be"
523 : " '%s' (via '%s:%s') or '%s' (via '%s:%s')",
524 : attr, res->string, prev->name, attr,
525 : v->string, iterator->name, attr);
526 0 : return v;
527 : }
528 0 : if (iterator_out)
529 0 : *iterator_out = iterator;
530 : prev = iterator;
531 : res = v;
532 : }
533 : }
534 : }
535 : return res;
536 : }
537 :
538 : /* Apply the current iterator values to STRING. Return the new string
539 : if any changes were needed, otherwise return STRING itself. */
540 :
541 : const char *
542 0 : md_reader::apply_iterator_to_string (const char *string)
543 : {
544 0 : char *base, *copy, *p, *start, *end;
545 0 : struct map_value *v;
546 :
547 0 : if (string == 0 || string[0] == 0)
548 : return string;
549 :
550 0 : file_location loc = get_md_ptr_loc (string)->loc;
551 0 : base = p = copy = ASTRDUP (string);
552 0 : while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
553 : {
554 0 : p = start + 1;
555 :
556 0 : *end = 0;
557 0 : v = map_attr_string (loc, p);
558 0 : *end = '>';
559 0 : if (v == 0)
560 0 : continue;
561 :
562 : /* Add everything between the last copied byte and the '<',
563 : then add in the attribute value. */
564 0 : obstack_grow (&m_string_obstack, base, start - base);
565 0 : obstack_grow (&m_string_obstack, v->string, strlen (v->string));
566 0 : base = end + 1;
567 : }
568 0 : if (base != copy)
569 : {
570 0 : obstack_grow (&m_string_obstack, base, strlen (base) + 1);
571 0 : copy = XOBFINISH (&m_string_obstack, char *);
572 0 : copy_md_ptr_loc (copy, string);
573 0 : return copy;
574 : }
575 : return string;
576 : }
577 :
578 : /* Return a deep copy of X, substituting the current iterator
579 : values into any strings. */
580 :
581 : rtx
582 0 : md_reader::copy_rtx_for_iterators (rtx original)
583 : {
584 0 : const char *format_ptr, *p;
585 0 : int i, j;
586 0 : rtx x;
587 :
588 0 : if (original == 0)
589 : return original;
590 :
591 : /* Create a shallow copy of ORIGINAL. */
592 0 : x = rtx_alloc (GET_CODE (original));
593 0 : memcpy (x, original, RTX_CODE_SIZE (GET_CODE (original)));
594 :
595 : /* Change each string and recursively change each rtx. */
596 0 : format_ptr = GET_RTX_FORMAT (GET_CODE (original));
597 0 : for (i = 0; format_ptr[i] != 0; i++)
598 0 : switch (format_ptr[i])
599 : {
600 : case 'T':
601 0 : while (XTMPL (x, i) != (p = apply_iterator_to_string (XTMPL (x, i))))
602 0 : XTMPL (x, i) = p;
603 : break;
604 :
605 : case 'S':
606 : case 's':
607 0 : while (XSTR (x, i) != (p = apply_iterator_to_string (XSTR (x, i))))
608 0 : XSTR (x, i) = p;
609 : break;
610 :
611 0 : case 'e':
612 0 : XEXP (x, i) = copy_rtx_for_iterators (XEXP (x, i));
613 0 : break;
614 :
615 0 : case 'V':
616 0 : case 'E':
617 0 : if (XVEC (original, i))
618 : {
619 0 : XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
620 0 : for (j = 0; j < XVECLEN (x, i); j++)
621 0 : XVECEXP (x, i, j)
622 0 : = copy_rtx_for_iterators (XVECEXP (original, i, j));
623 : }
624 : break;
625 :
626 : default:
627 : break;
628 : }
629 : return x;
630 : }
631 :
632 : #ifdef GENERATOR_FILE
633 :
634 : /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL
635 : has the form "&& ..." (as used in define_insn_and_splits), assume that
636 : EXTRA is already satisfied. Empty strings are treated like "true". */
637 :
638 : static const char *
639 : add_condition_to_string (const char *original, const char *extra)
640 : {
641 : if (original != 0 && original[0] == '&' && original[1] == '&')
642 : return original;
643 : return rtx_reader_ptr->join_c_conditions (original, extra);
644 : }
645 :
646 : /* Like add_condition, but applied to all conditions in rtx X. */
647 :
648 : static void
649 : add_condition_to_rtx (rtx x, const char *extra)
650 : {
651 : switch (GET_CODE (x))
652 : {
653 : case DEFINE_INSN:
654 : case DEFINE_EXPAND:
655 : case DEFINE_SUBST:
656 : XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
657 : break;
658 :
659 : case DEFINE_SPLIT:
660 : case DEFINE_PEEPHOLE:
661 : case DEFINE_PEEPHOLE2:
662 : case DEFINE_COND_EXEC:
663 : XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
664 : break;
665 :
666 : case DEFINE_INSN_AND_SPLIT:
667 : case DEFINE_INSN_AND_REWRITE:
668 : XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
669 : XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
670 : break;
671 :
672 : default:
673 : break;
674 : }
675 : }
676 :
677 : /* Apply the current iterator values to all attribute_uses. */
678 :
679 : static void
680 : apply_attribute_uses (void)
681 : {
682 : struct map_value *v;
683 : attribute_use *ause;
684 : unsigned int i;
685 :
686 : FOR_EACH_VEC_ELT (attribute_uses, i, ause)
687 : {
688 : v = map_attr_string (ause->loc, ause->value);
689 : if (!v)
690 : fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
691 : ause->group->apply_iterator (ause->x, ause->index,
692 : ause->group->find_builtin (v->string));
693 : }
694 : }
695 :
696 : /* A htab_traverse callback for iterators. Add all used iterators
697 : to current_iterators. */
698 :
699 : static int
700 : add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED)
701 : {
702 : struct mapping *iterator;
703 :
704 : iterator = (struct mapping *) *slot;
705 : if (iterator->current_value)
706 : current_iterators.safe_push (iterator);
707 : return 1;
708 : }
709 :
710 : /* Return a hash value for overloaded_name UNCAST_ONAME. There shouldn't
711 : be many instances of two overloaded_names having the same name but
712 : different arguments, so hashing on the name should be good enough in
713 : practice. */
714 :
715 : static hashval_t
716 : overloaded_name_hash (const void *uncast_oname)
717 : {
718 : const overloaded_name *oname = (const overloaded_name *) uncast_oname;
719 : return htab_hash_string (oname->name);
720 : }
721 :
722 : /* Return true if two overloaded_names are similar enough to share
723 : the same generated functions. */
724 :
725 : static int
726 : overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2)
727 : {
728 : const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1;
729 : const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2;
730 : if (strcmp (oname1->name, oname2->name) != 0
731 : || oname1->arg_types.length () != oname2->arg_types.length ())
732 : return 0;
733 :
734 : for (unsigned int i = 0; i < oname1->arg_types.length (); ++i)
735 : if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0)
736 : return 0;
737 :
738 : return 1;
739 : }
740 :
741 : /* Return true if X has an instruction name in XSTR (X, 0). */
742 :
743 : static bool
744 : named_rtx_p (rtx x)
745 : {
746 : switch (GET_CODE (x))
747 : {
748 : case DEFINE_EXPAND:
749 : case DEFINE_INSN:
750 : case DEFINE_INSN_AND_SPLIT:
751 : case DEFINE_INSN_AND_REWRITE:
752 : return true;
753 :
754 : default:
755 : return false;
756 : }
757 : }
758 :
759 : /* Check whether ORIGINAL is a named pattern whose name starts with '@'.
760 : If so, return the associated overloaded_name and add the iterator for
761 : each argument to ITERATORS. Return null otherwise. */
762 :
763 : overloaded_name *
764 : md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
765 : {
766 : /* Check for the leading '@'. */
767 : if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@')
768 : return NULL;
769 :
770 : /* Remove the '@', so that no other code needs to worry about it. */
771 : const char *name = XSTR (original, 0);
772 : file_location loc = get_md_ptr_loc (name)->loc;
773 : copy_md_ptr_loc (name + 1, name);
774 : name += 1;
775 : XSTR (original, 0) = name;
776 :
777 : /* Build a copy of the name without the '<...>' attribute strings.
778 : Add the iterator associated with each such attribute string to ITERATORS
779 : and add an associated argument to TMP_ONAME. */
780 : char *copy = ASTRDUP (name);
781 : char *base = copy, *start, *end;
782 : overloaded_name tmp_oname;
783 : tmp_oname.arg_types.create (current_iterators.length ());
784 : bool pending_underscore_p = false;
785 : while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
786 : {
787 : *end = 0;
788 : mapping *iterator;
789 : if (!map_attr_string (loc, start + 1, &iterator))
790 : fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
791 : *end = '>';
792 :
793 : /* Remove a trailing underscore, so that we don't end a name
794 : with "_" or turn "_<...>_" into "__". */
795 : if (start != base && start[-1] == '_')
796 : {
797 : start -= 1;
798 : pending_underscore_p = true;
799 : }
800 :
801 : /* Add the text between either the last '>' or the start of
802 : the string and this '<'. */
803 : obstack_grow (&m_string_obstack, base, start - base);
804 : base = end + 1;
805 :
806 : /* If there's a character we need to keep after the '>', check
807 : whether we should prefix it with a previously-dropped '_'. */
808 : if (base[0] != 0 && base[0] != '<')
809 : {
810 : if (pending_underscore_p && base[0] != '_')
811 : obstack_1grow (&m_string_obstack, '_');
812 : pending_underscore_p = false;
813 : }
814 :
815 : /* Skip define_subst iterators, since define_substs are allowed to
816 : add new match_operands in their output templates. */
817 : if (iterator->group != &substs)
818 : {
819 : /* Record an argument for ITERATOR. */
820 : iterators->safe_push (iterator);
821 : tmp_oname.arg_types.safe_push (iterator->group->type);
822 : }
823 : }
824 : if (base == copy)
825 : fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
826 :
827 : size_t length = obstack_object_size (&m_string_obstack);
828 : if (length == 0)
829 : fatal_with_file_and_line ("`%s' only contains iterator attributes", name);
830 :
831 : /* Get the completed name. */
832 : obstack_grow (&m_string_obstack, base, strlen (base) + 1);
833 : char *new_name = XOBFINISH (&m_string_obstack, char *);
834 : tmp_oname.name = new_name;
835 :
836 : if (!m_overloads_htab)
837 : m_overloads_htab = htab_create (31, overloaded_name_hash,
838 : overloaded_name_eq_p, NULL);
839 :
840 : /* See whether another pattern had the same overload name and list
841 : of argument types. Create a new permanent one if not. */
842 : void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT);
843 : overloaded_name *oname = (overloaded_name *) *slot;
844 : if (!oname)
845 : {
846 : *slot = oname = new overloaded_name;
847 : oname->name = tmp_oname.name;
848 : oname->arg_types = tmp_oname.arg_types;
849 : oname->next = NULL;
850 : oname->first_instance = NULL;
851 : oname->next_instance_ptr = &oname->first_instance;
852 :
853 : *m_next_overload_ptr = oname;
854 : m_next_overload_ptr = &oname->next;
855 : }
856 : else
857 : {
858 : obstack_free (&m_string_obstack, new_name);
859 : tmp_oname.arg_types.release ();
860 : }
861 :
862 : return oname;
863 : }
864 :
865 : /* Add an instance of ONAME for instruction pattern X. ITERATORS[I]
866 : gives the iterator associated with argument I of ONAME. */
867 :
868 : static void
869 : add_overload_instance (overloaded_name *oname, const vec<mapping *> &iterators, rtx x)
870 : {
871 : /* Create the instance. */
872 : overloaded_instance *instance = new overloaded_instance;
873 : instance->next = NULL;
874 : instance->arg_values.create (oname->arg_types.length ());
875 : for (unsigned int i = 0; i < iterators.length (); ++i)
876 : {
877 : int value = iterators[i]->current_value->number;
878 : const char *name = iterators[i]->group->get_c_token (value);
879 : instance->arg_values.quick_push (name);
880 : }
881 : instance->name = XSTR (x, 0);
882 : instance->insn = x;
883 :
884 : /* Chain it onto the end of ONAME's list. */
885 : *oname->next_instance_ptr = instance;
886 : oname->next_instance_ptr = &instance->next;
887 : }
888 :
889 : /* Expand all iterators in the current rtx, which is given as ORIGINAL.
890 : Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE. */
891 :
892 : static void
893 : apply_iterators (rtx original, vec<rtx> *queue)
894 : {
895 : unsigned int i;
896 : const char *condition;
897 : iterator_use *iuse;
898 : struct mapping *iterator;
899 : struct map_value *v;
900 : rtx x;
901 :
902 : if (iterator_uses.is_empty ())
903 : {
904 : /* Raise an error if any attributes were used. */
905 : apply_attribute_uses ();
906 :
907 : if (named_rtx_p (original) && XSTR (original, 0)[0] == '@')
908 : fatal_with_file_and_line ("'@' used without iterators");
909 :
910 : queue->safe_push (original);
911 : return;
912 : }
913 :
914 : /* Clear out the iterators from the previous run. */
915 : FOR_EACH_VEC_ELT (current_iterators, i, iterator)
916 : iterator->current_value = NULL;
917 : current_iterators.truncate (0);
918 :
919 : /* Mark the iterators that we need this time. */
920 : FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
921 : iuse->iterator->current_value = iuse->iterator->values;
922 :
923 : /* Get the list of iterators that are in use, preserving the
924 : definition order within each group. */
925 : htab_traverse (modes.iterators, add_current_iterators, NULL);
926 : htab_traverse (codes.iterators, add_current_iterators, NULL);
927 : htab_traverse (ints.iterators, add_current_iterators, NULL);
928 : htab_traverse (substs.iterators, add_current_iterators, NULL);
929 : gcc_assert (!current_iterators.is_empty ());
930 :
931 : /* Check whether this is a '@' overloaded pattern. */
932 : auto_vec<mapping *, 16> iterators;
933 : overloaded_name *oname
934 : = rtx_reader_ptr->handle_overloaded_name (original, &iterators);
935 :
936 : for (;;)
937 : {
938 : /* Apply the current iterator values. Accumulate a condition to
939 : say when the resulting rtx can be used. */
940 : condition = "";
941 : FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
942 : {
943 : if (iuse->iterator->group == &substs)
944 : continue;
945 : v = iuse->iterator->current_value;
946 : iuse->iterator->group->apply_iterator (iuse->x, iuse->index,
947 : v->number);
948 : condition = rtx_reader_ptr->join_c_conditions (condition, v->string);
949 : }
950 : apply_attribute_uses ();
951 : x = rtx_reader_ptr->copy_rtx_for_iterators (original);
952 : add_condition_to_rtx (x, condition);
953 :
954 : /* We apply subst iterator after RTL-template is copied, as during
955 : subst-iterator processing, we could add an attribute to the
956 : RTL-template, and we don't want to do it in the original one. */
957 : bool add_oname = true;
958 : FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
959 : {
960 : v = iuse->iterator->current_value;
961 : if (iuse->iterator->group == &substs)
962 : {
963 : iuse->x = x;
964 : iuse->index = 0;
965 : current_iterator_name = iuse->iterator->name;
966 : iuse->iterator->group->apply_iterator (iuse->x, iuse->index,
967 : v->number);
968 : /* Only handle '@' overloading for the default value.
969 : See handle_overloaded_name for details. */
970 : if (v != iuse->iterator->values)
971 : add_oname = false;
972 : }
973 : }
974 :
975 : if (oname && add_oname)
976 : add_overload_instance (oname, iterators, x);
977 :
978 : /* Add the new rtx to the end of the queue. */
979 : queue->safe_push (x);
980 :
981 : /* Lexicographically increment the iterator value sequence.
982 : That is, cycle through iterator values, starting from the right,
983 : and stopping when one of them doesn't wrap around. */
984 : i = current_iterators.length ();
985 : for (;;)
986 : {
987 : if (i == 0)
988 : return;
989 : i--;
990 : iterator = current_iterators[i];
991 : iterator->current_value = iterator->current_value->next;
992 : if (iterator->current_value)
993 : break;
994 : iterator->current_value = iterator->values;
995 : }
996 : }
997 : }
998 : #endif /* #ifdef GENERATOR_FILE */
999 :
1000 : /* Add a new "mapping" structure to hashtable TABLE. NAME is the name
1001 : of the mapping and GROUP is the group to which it belongs. */
1002 :
1003 : static struct mapping *
1004 88 : add_mapping (struct iterator_group *group, htab_t table, const char *name)
1005 : {
1006 88 : struct mapping *m;
1007 88 : void **slot;
1008 :
1009 88 : m = XNEW (struct mapping);
1010 88 : m->name = xstrdup (name);
1011 88 : m->group = group;
1012 88 : m->values = 0;
1013 88 : m->current_value = NULL;
1014 :
1015 88 : slot = htab_find_slot (table, m, INSERT);
1016 88 : if (*slot != 0)
1017 0 : fatal_with_file_and_line ("`%s' already defined", name);
1018 :
1019 88 : *slot = m;
1020 88 : return m;
1021 : }
1022 :
1023 : /* Add the pair (NUMBER, STRING) to a list of map_value structures.
1024 : END_PTR points to the current null terminator for the list; return
1025 : a pointer the new null terminator. */
1026 :
1027 : static struct map_value **
1028 12276 : add_map_value (struct map_value **end_ptr, int number, const char *string)
1029 : {
1030 12276 : struct map_value *value;
1031 :
1032 0 : value = XNEW (struct map_value);
1033 12276 : value->next = 0;
1034 12276 : value->number = number;
1035 12276 : value->string = string;
1036 :
1037 12276 : *end_ptr = value;
1038 12276 : return &value->next;
1039 : }
1040 :
1041 : /* Do one-time initialization of the mode and code attributes. */
1042 :
1043 : static void
1044 22 : initialize_iterators (void)
1045 : {
1046 22 : struct mapping *lower, *upper;
1047 22 : struct map_value **lower_ptr, **upper_ptr;
1048 22 : char *copy, *p;
1049 22 : int i;
1050 :
1051 22 : modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1052 22 : modes.iterators = htab_create (13, leading_string_hash,
1053 : leading_string_eq_p, 0);
1054 22 : modes.type = "machine_mode";
1055 22 : modes.find_builtin = find_mode;
1056 22 : modes.apply_iterator = apply_mode_iterator;
1057 22 : modes.get_c_token = get_mode_token;
1058 :
1059 22 : codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1060 22 : codes.iterators = htab_create (13, leading_string_hash,
1061 : leading_string_eq_p, 0);
1062 22 : codes.type = "rtx_code";
1063 22 : codes.find_builtin = find_code;
1064 22 : codes.apply_iterator = apply_code_iterator;
1065 22 : codes.get_c_token = get_code_token;
1066 :
1067 22 : ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1068 22 : ints.iterators = htab_create (13, leading_string_hash,
1069 : leading_string_eq_p, 0);
1070 22 : ints.type = "int";
1071 22 : ints.find_builtin = find_int;
1072 22 : ints.apply_iterator = apply_int_iterator;
1073 22 : ints.get_c_token = get_int_token;
1074 22 : ints.has_self_attr = true;
1075 :
1076 22 : substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1077 22 : substs.iterators = htab_create (13, leading_string_hash,
1078 : leading_string_eq_p, 0);
1079 22 : substs.type = "int";
1080 22 : substs.find_builtin = find_int; /* We don't use it, anyway. */
1081 : #ifdef GENERATOR_FILE
1082 : substs.apply_iterator = apply_subst_iterator;
1083 : #endif
1084 22 : substs.get_c_token = get_int_token;
1085 :
1086 22 : lower = add_mapping (&modes, modes.attrs, "mode");
1087 22 : upper = add_mapping (&modes, modes.attrs, "MODE");
1088 22 : lower_ptr = &lower->values;
1089 22 : upper_ptr = &upper->values;
1090 2750 : for (i = 0; i < MAX_MACHINE_MODE; i++)
1091 : {
1092 2728 : copy = xstrdup (GET_MODE_NAME (i));
1093 14938 : for (p = copy; *p != 0; p++)
1094 9482 : *p = TOLOWER (*p);
1095 :
1096 2728 : upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
1097 2728 : lower_ptr = add_map_value (lower_ptr, i, copy);
1098 : }
1099 :
1100 22 : lower = add_mapping (&codes, codes.attrs, "code");
1101 22 : upper = add_mapping (&codes, codes.attrs, "CODE");
1102 22 : lower_ptr = &lower->values;
1103 22 : upper_ptr = &upper->values;
1104 3432 : for (i = 0; i < NUM_RTX_CODE; i++)
1105 : {
1106 3410 : copy = xstrdup (GET_RTX_NAME (i));
1107 32560 : for (p = copy; *p != 0; p++)
1108 25740 : *p = TOUPPER (*p);
1109 :
1110 3410 : lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
1111 3410 : upper_ptr = add_map_value (upper_ptr, i, copy);
1112 : }
1113 22 : }
1114 :
1115 :
1116 : #ifdef GENERATOR_FILE
1117 : /* Process a define_conditions directive, starting with the optional
1118 : space after the "define_conditions". The directive looks like this:
1119 :
1120 : (define_conditions [
1121 : (number "string")
1122 : (number "string")
1123 : ...
1124 : ])
1125 :
1126 : It's not intended to appear in machine descriptions. It is
1127 : generated by (the program generated by) genconditions.cc, and
1128 : slipped in at the beginning of the sequence of MD files read by
1129 : most of the other generators. */
1130 : void
1131 : md_reader::read_conditions ()
1132 : {
1133 : int c;
1134 :
1135 : require_char_ws ('[');
1136 :
1137 : while ( (c = read_skip_spaces ()) != ']')
1138 : {
1139 : struct md_name name;
1140 : char *expr;
1141 : int value;
1142 :
1143 : if (c != '(')
1144 : fatal_expected_char ('(', c);
1145 :
1146 : read_name (&name);
1147 : validate_const_int (name.string);
1148 : value = atoi (name.string);
1149 :
1150 : require_char_ws ('"');
1151 : expr = read_quoted_string ();
1152 :
1153 : require_char_ws (')');
1154 :
1155 : add_c_test (expr, value);
1156 : }
1157 : }
1158 : #endif /* #ifdef GENERATOR_FILE */
1159 :
1160 : static void
1161 244 : validate_const_int (const char *string)
1162 : {
1163 244 : const char *cp;
1164 244 : int valid = 1;
1165 :
1166 244 : cp = string;
1167 244 : while (*cp && ISSPACE (*cp))
1168 0 : cp++;
1169 244 : if (*cp == '-' || *cp == '+')
1170 148 : cp++;
1171 244 : if (*cp == 0)
1172 0 : valid = 0;
1173 553 : for (; *cp; cp++)
1174 309 : if (! ISDIGIT (*cp))
1175 : {
1176 : valid = 0;
1177 : break;
1178 : }
1179 244 : if (!valid)
1180 0 : fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string);
1181 244 : }
1182 :
1183 : static void
1184 0 : validate_const_wide_int (const char *string)
1185 : {
1186 0 : const char *cp;
1187 0 : int valid = 1;
1188 :
1189 0 : cp = string;
1190 0 : while (*cp && ISSPACE (*cp))
1191 0 : cp++;
1192 : /* Skip the leading 0x. */
1193 0 : if (cp[0] == '0' || cp[1] == 'x')
1194 0 : cp += 2;
1195 : else
1196 : valid = 0;
1197 0 : if (*cp == 0)
1198 0 : valid = 0;
1199 0 : for (; *cp; cp++)
1200 0 : if (! ISXDIGIT (*cp))
1201 0 : valid = 0;
1202 0 : if (!valid)
1203 0 : fatal_with_file_and_line ("invalid hex constant \"%s\"\n", string);
1204 0 : }
1205 :
1206 : /* Record that X uses iterator ITERATOR. If the use is in an operand
1207 : of X, INDEX is the index of that operand, otherwise it is ignored. */
1208 :
1209 : static void
1210 0 : record_iterator_use (struct mapping *iterator, rtx x, unsigned int index)
1211 : {
1212 0 : struct iterator_use iuse = {iterator, x, index};
1213 0 : iterator_uses.safe_push (iuse);
1214 0 : }
1215 :
1216 : /* Record that X uses attribute VALUE at location LOC, where VALUE must
1217 : match a built-in value from group GROUP. If the use is in an operand
1218 : of X, INDEX is the index of that operand, otherwise it is ignored. */
1219 :
1220 : static void
1221 0 : record_attribute_use (struct iterator_group *group, file_location loc, rtx x,
1222 : unsigned int index, const char *value)
1223 : {
1224 0 : struct attribute_use ause = {group, loc, value, x, index};
1225 0 : attribute_uses.safe_push (ause);
1226 0 : }
1227 :
1228 : /* Interpret NAME as either a built-in value, iterator or attribute
1229 : for group GROUP. X and INDEX are the values to pass to GROUP's
1230 : apply_iterator callback. LOC is the location of the use. */
1231 :
1232 : void
1233 1288 : md_reader::record_potential_iterator_use (struct iterator_group *group,
1234 : file_location loc,
1235 : rtx x, unsigned int index,
1236 : const char *name)
1237 : {
1238 1288 : struct mapping *m;
1239 1288 : size_t len;
1240 :
1241 1288 : len = strlen (name);
1242 1288 : if (name[0] == '<' && name[len - 1] == '>')
1243 : {
1244 : /* Copy the attribute string into permanent storage, without the
1245 : angle brackets around it. */
1246 0 : obstack_grow0 (&m_string_obstack, name + 1, len - 2);
1247 0 : record_attribute_use (group, loc, x, index,
1248 0 : XOBFINISH (&m_string_obstack, char *));
1249 0 : }
1250 : else
1251 : {
1252 1288 : m = (struct mapping *) htab_find (group->iterators, &name);
1253 1288 : if (m != 0)
1254 0 : record_iterator_use (m, x, index);
1255 : else
1256 1288 : group->apply_iterator (x, index, group->find_builtin (name));
1257 : }
1258 1288 : }
1259 :
1260 : #ifdef GENERATOR_FILE
1261 :
1262 : /* Finish reading a declaration of the form:
1263 :
1264 : (define... <name> [<value1> ... <valuen>])
1265 :
1266 : from the MD file, where each <valuei> is either a bare symbol name or a
1267 : "(<name> <string>)" pair. The "(define..." part has already been read.
1268 :
1269 : Represent the declaration as a "mapping" structure; add it to TABLE
1270 : (which belongs to GROUP) and return it. */
1271 :
1272 : struct mapping *
1273 : md_reader::read_mapping (struct iterator_group *group, htab_t table)
1274 : {
1275 : struct md_name name;
1276 : struct mapping *m;
1277 : struct map_value **end_ptr;
1278 : const char *string;
1279 : int number, c;
1280 :
1281 : /* Read the mapping name and create a structure for it. */
1282 : read_name (&name);
1283 : m = add_mapping (group, table, name.string);
1284 :
1285 : require_char_ws ('[');
1286 :
1287 : /* Read each value. */
1288 : end_ptr = &m->values;
1289 : c = read_skip_spaces ();
1290 : do
1291 : {
1292 : if (c != '(')
1293 : {
1294 : /* A bare symbol name that is implicitly paired to an
1295 : empty string. */
1296 : unread_char (c);
1297 : read_name (&name);
1298 : string = "";
1299 : }
1300 : else
1301 : {
1302 : /* A "(name string)" pair. */
1303 : read_name (&name);
1304 : string = read_string (false);
1305 : require_char_ws (')');
1306 : }
1307 : auto *subm = (struct mapping *) htab_find (group->iterators,
1308 : &name.string);
1309 : if (subm)
1310 : {
1311 : if (m == subm)
1312 : fatal_with_file_and_line ("recursive definition of `%s'",
1313 : name.string);
1314 : for (map_value *v = subm->values; v; v = v->next)
1315 : {
1316 : auto *joined = rtx_reader_ptr->join_c_conditions (v->string,
1317 : string);
1318 : end_ptr = add_map_value (end_ptr, v->number, joined);
1319 : }
1320 : }
1321 : else
1322 : {
1323 : number = group->find_builtin (name.string);
1324 : end_ptr = add_map_value (end_ptr, number, string);
1325 : }
1326 : c = read_skip_spaces ();
1327 : }
1328 : while (c != ']');
1329 :
1330 : return m;
1331 : }
1332 :
1333 : /* For iterator with name ATTR_NAME generate define_attr with values
1334 : 'yes' and 'no'. This attribute is used to mark templates to which
1335 : define_subst ATTR_NAME should be applied. This attribute is set and
1336 : defined implicitly and automatically. */
1337 : static void
1338 : add_define_attr_for_define_subst (const char *attr_name, vec<rtx> *queue)
1339 : {
1340 : rtx const_str, return_rtx;
1341 :
1342 : return_rtx = rtx_alloc (DEFINE_ATTR);
1343 : PUT_CODE (return_rtx, DEFINE_ATTR);
1344 :
1345 : const_str = rtx_alloc (CONST_STRING);
1346 : PUT_CODE (const_str, CONST_STRING);
1347 : XSTR (const_str, 0) = xstrdup ("no");
1348 :
1349 : XSTR (return_rtx, 0) = xstrdup (attr_name);
1350 : XSTR (return_rtx, 1) = xstrdup ("no,yes");
1351 : XEXP (return_rtx, 2) = const_str;
1352 :
1353 : queue->safe_push (return_rtx);
1354 : }
1355 :
1356 : /* This routine generates DEFINE_SUBST_ATTR expression with operands
1357 : ATTR_OPERANDS and places it to QUEUE. */
1358 : static void
1359 : add_define_subst_attr (const char **attr_operands, vec<rtx> *queue)
1360 : {
1361 : rtx return_rtx;
1362 : int i;
1363 :
1364 : return_rtx = rtx_alloc (DEFINE_SUBST_ATTR);
1365 : PUT_CODE (return_rtx, DEFINE_SUBST_ATTR);
1366 :
1367 : for (i = 0; i < 4; i++)
1368 : XSTR (return_rtx, i) = xstrdup (attr_operands[i]);
1369 :
1370 : queue->safe_push (return_rtx);
1371 : }
1372 :
1373 : /* Read define_subst_attribute construction. It has next form:
1374 : (define_subst_attribute <attribute_name> <iterator_name> <value1> <value2>)
1375 : Attribute is substituted with value1 when no subst is applied and with
1376 : value2 in the opposite case.
1377 : Attributes are added to SUBST_ATTRS_TABLE.
1378 : In case the iterator is encountered for the first time, it's added to
1379 : SUBST_ITERS_TABLE. Also, implicit define_attr is generated. */
1380 :
1381 : static void
1382 : read_subst_mapping (htab_t subst_iters_table, htab_t subst_attrs_table,
1383 : vec<rtx> *queue)
1384 : {
1385 : struct mapping *m;
1386 : struct map_value **end_ptr;
1387 : const char *attr_operands[4];
1388 : int i;
1389 :
1390 : for (i = 0; i < 4; i++)
1391 : attr_operands[i] = rtx_reader_ptr->read_string (false);
1392 :
1393 : add_define_subst_attr (attr_operands, queue);
1394 :
1395 : bind_subst_iter_and_attr (attr_operands[1], attr_operands[0]);
1396 :
1397 : m = (struct mapping *) htab_find (substs.iterators, &attr_operands[1]);
1398 : if (!m)
1399 : {
1400 : m = add_mapping (&substs, subst_iters_table, attr_operands[1]);
1401 : end_ptr = &m->values;
1402 : end_ptr = add_map_value (end_ptr, 1, "");
1403 : add_map_value (end_ptr, 2, "");
1404 :
1405 : add_define_attr_for_define_subst (attr_operands[1], queue);
1406 : }
1407 :
1408 : m = add_mapping (&substs, subst_attrs_table, attr_operands[0]);
1409 : end_ptr = &m->values;
1410 : end_ptr = add_map_value (end_ptr, 1, attr_operands[2]);
1411 : add_map_value (end_ptr, 2, attr_operands[3]);
1412 : }
1413 :
1414 : /* Check newly-created code iterator ITERATOR to see whether every code has the
1415 : same format. */
1416 :
1417 : static void
1418 : check_code_iterator (struct mapping *iterator)
1419 : {
1420 : struct map_value *v;
1421 : enum rtx_code bellwether;
1422 :
1423 : bellwether = (enum rtx_code) iterator->values->number;
1424 : for (v = iterator->values->next; v != 0; v = v->next)
1425 : if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
1426 : fatal_with_file_and_line ("code iterator `%s' combines "
1427 : "`%s' and `%s', which have different "
1428 : "rtx formats", iterator->name,
1429 : GET_RTX_NAME (bellwether),
1430 : GET_RTX_NAME (v->number));
1431 : }
1432 :
1433 : /* Check that all values of attribute ATTR are rtx codes that have a
1434 : consistent format. Return a representative code. */
1435 :
1436 : static rtx_code
1437 : check_attribute_codes (mapping *attr)
1438 : {
1439 : rtx_code bellwether = UNKNOWN;
1440 : for (map_value *v = attr->values; v != 0; v = v->next)
1441 : {
1442 : rtx_code code = maybe_find_code (v->string);
1443 : if (code == UNKNOWN)
1444 : fatal_with_file_and_line ("attribute `%s' contains "
1445 : "unrecognized rtx code `%s'",
1446 : attr->name, v->string);
1447 : if (bellwether == UNKNOWN)
1448 : bellwether = code;
1449 : else if (strcmp (GET_RTX_FORMAT (bellwether),
1450 : GET_RTX_FORMAT (code)) != 0)
1451 : fatal_with_file_and_line ("attribute `%s' combines "
1452 : "`%s' and `%s', which have different "
1453 : "rtx formats", attr->name,
1454 : GET_RTX_NAME (bellwether),
1455 : GET_RTX_NAME (code));
1456 : }
1457 : return bellwether;
1458 : }
1459 :
1460 : /* Read an rtx-related declaration from the MD file, given that it
1461 : starts with directive name RTX_NAME. Return true if it expands to
1462 : one or more rtxes (as defined by rtx.def). When returning true,
1463 : store the list of rtxes as an EXPR_LIST in *X. */
1464 :
1465 : bool
1466 : rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen)
1467 : {
1468 : /* Handle various rtx-related declarations that aren't themselves
1469 : encoded as rtxes. */
1470 : if (strcmp (rtx_name, "define_conditions") == 0)
1471 : {
1472 : read_conditions ();
1473 : return false;
1474 : }
1475 : if (strcmp (rtx_name, "define_mode_attr") == 0)
1476 : {
1477 : read_mapping (&modes, modes.attrs);
1478 : return false;
1479 : }
1480 : if (strcmp (rtx_name, "define_mode_iterator") == 0)
1481 : {
1482 : read_mapping (&modes, modes.iterators);
1483 : return false;
1484 : }
1485 : if (strcmp (rtx_name, "define_code_attr") == 0)
1486 : {
1487 : read_mapping (&codes, codes.attrs);
1488 : return false;
1489 : }
1490 : if (strcmp (rtx_name, "define_code_iterator") == 0)
1491 : {
1492 : check_code_iterator (read_mapping (&codes, codes.iterators));
1493 : return false;
1494 : }
1495 : if (strcmp (rtx_name, "define_int_attr") == 0)
1496 : {
1497 : read_mapping (&ints, ints.attrs);
1498 : return false;
1499 : }
1500 : if (strcmp (rtx_name, "define_int_iterator") == 0)
1501 : {
1502 : read_mapping (&ints, ints.iterators);
1503 : return false;
1504 : }
1505 : if (strcmp (rtx_name, "define_subst_attr") == 0)
1506 : {
1507 : read_subst_mapping (substs.iterators, substs.attrs, rtxen);
1508 :
1509 : /* READ_SUBST_MAPPING could generate a new DEFINE_ATTR. Return
1510 : TRUE to process it. */
1511 : return true;
1512 : }
1513 :
1514 : apply_iterators (rtx_reader_ptr->read_rtx_code (rtx_name), rtxen);
1515 : iterator_uses.truncate (0);
1516 : attribute_uses.truncate (0);
1517 :
1518 : return true;
1519 : }
1520 :
1521 : #endif /* #ifdef GENERATOR_FILE */
1522 :
1523 : /* Do one-time initialization. */
1524 :
1525 : static void
1526 104 : one_time_initialization (void)
1527 : {
1528 104 : static bool initialized = false;
1529 :
1530 104 : if (!initialized)
1531 : {
1532 22 : initialize_iterators ();
1533 22 : initialized = true;
1534 : }
1535 104 : }
1536 :
1537 : /* Consume characters until encountering a character in TERMINATOR_CHARS,
1538 : consuming the terminator character if CONSUME_TERMINATOR is true.
1539 : Return all characters before the terminator as an allocated buffer. */
1540 :
1541 : char *
1542 311 : rtx_reader::read_until (const char *terminator_chars, bool consume_terminator)
1543 : {
1544 311 : int ch = read_skip_spaces ();
1545 311 : unread_char (ch);
1546 311 : auto_vec<char> buf;
1547 2167 : while (1)
1548 : {
1549 1239 : ch = read_char ();
1550 1239 : if (strchr (terminator_chars, ch))
1551 : {
1552 311 : if (!consume_terminator)
1553 145 : unread_char (ch);
1554 311 : break;
1555 : }
1556 928 : buf.safe_push (ch);
1557 : }
1558 311 : buf.safe_push ('\0');
1559 622 : return xstrdup (buf.address ());
1560 311 : }
1561 :
1562 : /* Subroutine of read_rtx_code, for parsing zero or more flags. */
1563 :
1564 : static void
1565 2217 : read_flags (rtx return_rtx)
1566 : {
1567 2563 : while (1)
1568 : {
1569 2563 : int ch = read_char ();
1570 2563 : if (ch != '/')
1571 : {
1572 2217 : unread_char (ch);
1573 2217 : break;
1574 : }
1575 :
1576 346 : int flag_char = read_char ();
1577 346 : switch (flag_char)
1578 : {
1579 0 : case 's':
1580 0 : RTX_FLAG (return_rtx, in_struct) = 1;
1581 0 : break;
1582 28 : case 'v':
1583 28 : RTX_FLAG (return_rtx, volatil) = 1;
1584 28 : break;
1585 0 : case 'u':
1586 0 : RTX_FLAG (return_rtx, unchanging) = 1;
1587 0 : break;
1588 134 : case 'f':
1589 134 : RTX_FLAG (return_rtx, frame_related) = 1;
1590 134 : break;
1591 5 : case 'j':
1592 5 : RTX_FLAG (return_rtx, jump) = 1;
1593 5 : break;
1594 116 : case 'c':
1595 116 : RTX_FLAG (return_rtx, call) = 1;
1596 116 : break;
1597 63 : case 'i':
1598 63 : RTX_FLAG (return_rtx, return_val) = 1;
1599 63 : break;
1600 0 : default:
1601 0 : fatal_with_file_and_line ("unrecognized flag: `%c'", flag_char);
1602 : }
1603 : }
1604 2217 : }
1605 :
1606 : /* Return the numeric value n for GET_REG_NOTE_NAME (n) for STRING,
1607 : or fail if STRING isn't recognized. */
1608 :
1609 : static int
1610 42 : parse_reg_note_name (const char *string)
1611 : {
1612 480 : for (int i = 0; i < REG_NOTE_MAX; i++)
1613 480 : if (strcmp (string, GET_REG_NOTE_NAME (i)) == 0)
1614 42 : return i;
1615 0 : fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string);
1616 : }
1617 :
1618 : /* Allocate an rtx for code NAME. If NAME is a code iterator or an
1619 : attribute, record its use for later and use one of its possible
1620 : values as an interim rtx code. */
1621 :
1622 : rtx
1623 2218 : rtx_reader::rtx_alloc_for_name (const char *name)
1624 : {
1625 : #ifdef GENERATOR_FILE
1626 : size_t len = strlen (name);
1627 : if (name[0] == '<' && name[len - 1] == '>')
1628 : {
1629 : /* Copy the attribute string into permanent storage, without the
1630 : angle brackets around it. */
1631 : obstack *strings = get_string_obstack ();
1632 : obstack_grow0 (strings, name + 1, len - 2);
1633 : char *deferred_name = XOBFINISH (strings, char *);
1634 :
1635 : /* Find the name of the attribute. */
1636 : const char *attr = strchr (deferred_name, ':');
1637 : if (!attr)
1638 : attr = deferred_name;
1639 :
1640 : /* Find the attribute itself. */
1641 : mapping *m = nullptr;
1642 : for (auto attrs : { codes.attrs, ints.attrs, modes.attrs })
1643 : if (auto *newm = (mapping *) htab_find (attrs, &attr))
1644 : {
1645 : if (m)
1646 : fatal_with_file_and_line ("ambiguous attribute `%s`", attr);
1647 : m = newm;
1648 : }
1649 : if (!m)
1650 : fatal_with_file_and_line ("unknown attribute `%s'", attr);
1651 :
1652 : /* Pick the first possible code for now, and record the attribute
1653 : use for later. */
1654 : rtx x = rtx_alloc (check_attribute_codes (m));
1655 : record_attribute_use (&codes, get_current_location (),
1656 : x, 0, deferred_name);
1657 : return x;
1658 : }
1659 :
1660 : mapping *iterator = (mapping *) htab_find (codes.iterators, &name);
1661 : if (iterator != 0)
1662 : {
1663 : /* Pick the first possible code for now, and record the iterator
1664 : use for later. */
1665 : rtx x = rtx_alloc (rtx_code (iterator->values->number));
1666 : record_iterator_use (iterator, x, 0);
1667 : return x;
1668 : }
1669 : #endif
1670 :
1671 2218 : return rtx_alloc (rtx_code (codes.find_builtin (name)));
1672 : }
1673 :
1674 : /* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of
1675 : either an rtx code or a code iterator. Parse the rest of the rtx and
1676 : return it. */
1677 :
1678 : rtx
1679 2228 : rtx_reader::read_rtx_code (const char *code_name)
1680 : {
1681 2228 : RTX_CODE code;
1682 2228 : const char *format_ptr;
1683 2228 : struct md_name name;
1684 2228 : rtx return_rtx;
1685 2228 : int c;
1686 :
1687 : /* Linked list structure for making RTXs: */
1688 2228 : struct rtx_list
1689 : {
1690 : struct rtx_list *next;
1691 : rtx value; /* Value of this node. */
1692 : };
1693 :
1694 : #ifndef GENERATOR_FILE
1695 2228 : long reuse_id = -1;
1696 : /* Handle reuse_rtx ids e.g. "(0|scratch:DI)". */
1697 2228 : if (ISDIGIT (code_name[0]))
1698 : {
1699 10 : reuse_id = atoi (code_name);
1700 20 : while (char ch = *code_name++)
1701 20 : if (ch == '|')
1702 : break;
1703 : }
1704 :
1705 : /* Handle "reuse_rtx". */
1706 2228 : if (strcmp (code_name, "reuse_rtx") == 0)
1707 : {
1708 10 : read_name (&name);
1709 10 : unsigned idx = atoi (name.string);
1710 : /* Look it up by ID. */
1711 10 : if (idx >= m_reuse_rtx_by_id.length ())
1712 0 : fatal_with_file_and_line ("invalid reuse index %u", idx);
1713 10 : return_rtx = m_reuse_rtx_by_id[idx];
1714 10 : return return_rtx;
1715 : }
1716 : #endif
1717 :
1718 : /* Handle "const_double_zero". */
1719 2218 : if (strcmp (code_name, "const_double_zero") == 0)
1720 : {
1721 0 : code = CONST_DOUBLE;
1722 0 : return_rtx = rtx_alloc (code);
1723 0 : memset (return_rtx, 0, RTX_CODE_SIZE (code));
1724 0 : PUT_CODE (return_rtx, code);
1725 0 : c = read_skip_spaces ();
1726 0 : if (c == ':')
1727 : {
1728 0 : file_location loc = read_name (&name);
1729 0 : record_potential_iterator_use (&modes, loc, return_rtx, 0,
1730 0 : name.string);
1731 : }
1732 : else
1733 0 : unread_char (c);
1734 : return return_rtx;
1735 : }
1736 :
1737 : /* If we end up with an insn expression then we free this space below. */
1738 2218 : return_rtx = rtx_alloc_for_name (code_name);
1739 2217 : code = GET_CODE (return_rtx);
1740 2217 : format_ptr = GET_RTX_FORMAT (code);
1741 2217 : memset (return_rtx, 0, RTX_CODE_SIZE (code));
1742 2217 : PUT_CODE (return_rtx, code);
1743 :
1744 : #ifndef GENERATOR_FILE
1745 2217 : if (reuse_id != -1)
1746 : {
1747 : /* Store away for later reuse. */
1748 10 : m_reuse_rtx_by_id.safe_grow_cleared (reuse_id + 1, true);
1749 10 : m_reuse_rtx_by_id[reuse_id] = return_rtx;
1750 : }
1751 : #endif
1752 :
1753 : /* Check for flags. */
1754 2217 : read_flags (return_rtx);
1755 :
1756 : /* Read REG_NOTE names for EXPR_LIST and INSN_LIST. */
1757 2217 : if ((GET_CODE (return_rtx) == EXPR_LIST
1758 : || GET_CODE (return_rtx) == INSN_LIST
1759 2217 : || GET_CODE (return_rtx) == INT_LIST)
1760 47 : && !m_in_call_function_usage)
1761 : {
1762 42 : char ch = read_char ();
1763 42 : if (ch == ':')
1764 : {
1765 42 : read_name (&name);
1766 42 : PUT_MODE_RAW (return_rtx,
1767 : (machine_mode)parse_reg_note_name (name.string));
1768 : }
1769 : else
1770 0 : unread_char (ch);
1771 : }
1772 :
1773 : /* If what follows is `: mode ', read it and
1774 : store the mode in the rtx. */
1775 :
1776 2217 : c = read_skip_spaces ();
1777 2217 : if (c == ':')
1778 : {
1779 1044 : file_location loc = read_name (&name);
1780 1044 : record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string);
1781 : }
1782 : else
1783 1173 : unread_char (c);
1784 :
1785 2217 : if (INSN_CHAIN_CODE_P (code))
1786 : {
1787 480 : read_name (&name);
1788 480 : INSN_UID (return_rtx) = atoi (name.string);
1789 : }
1790 :
1791 : /* Use the format_ptr to parse the various operands of this rtx. */
1792 7889 : for (int idx = 0; format_ptr[idx] != 0; idx++)
1793 5672 : return_rtx = read_rtx_operand (return_rtx, idx);
1794 :
1795 : /* Handle any additional information that after the regular fields
1796 : (e.g. when parsing function dumps). */
1797 2217 : handle_any_trailing_information (return_rtx);
1798 :
1799 2217 : if (CONST_WIDE_INT_P (return_rtx))
1800 : {
1801 0 : read_name (&name);
1802 0 : validate_const_wide_int (name.string);
1803 0 : {
1804 0 : const char *s = name.string;
1805 0 : int len;
1806 0 : int index = 0;
1807 0 : int gs = HOST_BITS_PER_WIDE_INT/4;
1808 0 : int pos;
1809 0 : char * buf = XALLOCAVEC (char, gs + 1);
1810 0 : unsigned HOST_WIDE_INT wi;
1811 0 : int wlen;
1812 :
1813 : /* Skip the leading spaces. */
1814 0 : while (*s && ISSPACE (*s))
1815 0 : s++;
1816 :
1817 : /* Skip the leading 0x. */
1818 0 : gcc_assert (s[0] == '0');
1819 0 : gcc_assert (s[1] == 'x');
1820 0 : s += 2;
1821 :
1822 0 : len = strlen (s);
1823 0 : pos = len - gs;
1824 0 : wlen = (len + gs - 1) / gs; /* Number of words needed */
1825 :
1826 0 : return_rtx = const_wide_int_alloc (wlen);
1827 :
1828 0 : while (pos > 0)
1829 : {
1830 : #if HOST_BITS_PER_WIDE_INT == 64
1831 0 : sscanf (s + pos, "%16" HOST_WIDE_INT_PRINT "x", &wi);
1832 : #else
1833 : sscanf (s + pos, "%8" HOST_WIDE_INT_PRINT "x", &wi);
1834 : #endif
1835 0 : CWI_ELT (return_rtx, index++) = wi;
1836 0 : pos -= gs;
1837 : }
1838 0 : strncpy (buf, s, gs - pos);
1839 0 : buf [gs - pos] = 0;
1840 0 : sscanf (buf, "%" HOST_WIDE_INT_PRINT "x", &wi);
1841 0 : CWI_ELT (return_rtx, index++) = wi;
1842 : /* TODO: After reading, do we want to canonicalize with:
1843 : value = lookup_const_wide_int (value); ? */
1844 : }
1845 : }
1846 :
1847 2217 : c = read_skip_spaces ();
1848 : /* Syntactic sugar for AND and IOR, allowing Lisp-like
1849 : arbitrary number of arguments for them. */
1850 2217 : if (c == '('
1851 0 : && (GET_CODE (return_rtx) == AND
1852 0 : || GET_CODE (return_rtx) == IOR))
1853 0 : return read_rtx_variadic (return_rtx);
1854 :
1855 2217 : unread_char (c);
1856 2217 : return return_rtx;
1857 : }
1858 :
1859 : /* Subroutine of read_rtx_code. Parse operand IDX within RETURN_RTX,
1860 : based on the corresponding format character within GET_RTX_FORMAT
1861 : for the GET_CODE (RETURN_RTX), and return RETURN_RTX.
1862 : This is a virtual function, so that function_reader can override
1863 : some parsing, and potentially return a different rtx. */
1864 :
1865 : rtx
1866 2694 : rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
1867 : {
1868 2694 : RTX_CODE code = GET_CODE (return_rtx);
1869 2694 : const char *format_ptr = GET_RTX_FORMAT (code);
1870 2694 : int c;
1871 2694 : struct md_name name;
1872 :
1873 2694 : switch (format_ptr[idx])
1874 : {
1875 : /* 0 means a field for internal use only.
1876 : Don't expect it to be present in the input. */
1877 477 : case '0':
1878 477 : if (code == REG)
1879 0 : ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx);
1880 : break;
1881 :
1882 1888 : case 'e':
1883 1888 : XEXP (return_rtx, idx) = read_nested_rtx ();
1884 1888 : break;
1885 :
1886 0 : case 'u':
1887 0 : XEXP (return_rtx, idx) = read_nested_rtx ();
1888 0 : break;
1889 :
1890 0 : case 'V':
1891 : /* 'V' is an optional vector: if a closeparen follows,
1892 : just store NULL for this element. */
1893 0 : c = read_skip_spaces ();
1894 0 : unread_char (c);
1895 0 : if (c == ')')
1896 : {
1897 0 : XVEC (return_rtx, idx) = 0;
1898 0 : break;
1899 : }
1900 : /* Now process the vector. */
1901 : /* FALLTHRU */
1902 :
1903 43 : case 'E':
1904 43 : {
1905 : /* Obstack to store scratch vector in. */
1906 43 : struct obstack vector_stack;
1907 43 : int list_counter = 0;
1908 43 : rtvec return_vec = NULL_RTVEC;
1909 43 : rtx saved_rtx = NULL_RTX;
1910 :
1911 43 : require_char_ws ('[');
1912 :
1913 : /* Add expressions to a list, while keeping a count. */
1914 43 : obstack_init (&vector_stack);
1915 180 : while ((c = read_skip_spaces ()) && c != ']')
1916 : {
1917 94 : if (c == EOF)
1918 0 : fatal_expected_char (']', c);
1919 94 : unread_char (c);
1920 :
1921 94 : rtx value;
1922 94 : int repeat_count = 1;
1923 94 : if (c == 'r')
1924 : {
1925 : /* Process "repeated xN" directive. */
1926 4 : read_name (&name);
1927 4 : if (strcmp (name.string, "repeated"))
1928 0 : fatal_with_file_and_line ("invalid directive \"%s\"\n",
1929 : name.string);
1930 4 : read_name (&name);
1931 4 : if (!sscanf (name.string, "x%d", &repeat_count))
1932 0 : fatal_with_file_and_line ("invalid repeat count \"%s\"\n",
1933 : name.string);
1934 :
1935 : /* We already saw one of the instances. */
1936 4 : repeat_count--;
1937 4 : value = saved_rtx;
1938 : }
1939 90 : else if (c == '(')
1940 90 : value = read_nested_rtx ();
1941 : else
1942 0 : fatal_with_file_and_line ("unexpected character in vector");
1943 :
1944 436 : for (; repeat_count > 0; repeat_count--)
1945 : {
1946 342 : list_counter++;
1947 342 : obstack_ptr_grow (&vector_stack, value);
1948 : }
1949 94 : saved_rtx = value;
1950 : }
1951 43 : if (list_counter > 0)
1952 : {
1953 43 : return_vec = rtvec_alloc (list_counter);
1954 43 : memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
1955 : list_counter * sizeof (rtx));
1956 : }
1957 0 : else if (format_ptr[idx] == 'E')
1958 0 : fatal_with_file_and_line ("vector must have at least one element");
1959 43 : XVEC (return_rtx, idx) = return_vec;
1960 43 : obstack_free (&vector_stack, NULL);
1961 : /* close bracket gotten */
1962 : }
1963 43 : break;
1964 :
1965 42 : case 'S':
1966 42 : case 'T':
1967 42 : case 's':
1968 42 : {
1969 42 : char *stringbuf;
1970 42 : int star_if_braced;
1971 :
1972 42 : c = read_skip_spaces ();
1973 42 : unread_char (c);
1974 42 : if (c == ')')
1975 : {
1976 : /* 'S' fields are optional and should be NULL if no string
1977 : was given. Also allow normal 's' and 'T' strings to be
1978 : omitted, treating them in the same way as empty strings. */
1979 16 : XSTR (return_rtx, idx) = (format_ptr[idx] == 'S' ? NULL : "");
1980 16 : break;
1981 : }
1982 :
1983 : /* The output template slot of a DEFINE_INSN, DEFINE_INSN_AND_SPLIT,
1984 : DEFINE_INSN_AND_REWRITE or DEFINE_PEEPHOLE automatically
1985 : gets a star inserted as its first character, if it is
1986 : written with a brace block instead of a string constant. */
1987 26 : star_if_braced = (format_ptr[idx] == 'T');
1988 :
1989 26 : stringbuf = read_string (star_if_braced);
1990 26 : if (!stringbuf)
1991 : break;
1992 :
1993 : #ifdef GENERATOR_FILE
1994 : /* For insn patterns, we want to provide a default name
1995 : based on the file and line, like "*foo.md:12", if the
1996 : given name is blank. These are only for define_insn and
1997 : define_insn_and_split, to aid debugging. */
1998 : if (*stringbuf == '\0'
1999 : && idx == 0
2000 : && (GET_CODE (return_rtx) == DEFINE_INSN
2001 : || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT
2002 : || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE))
2003 : {
2004 : const char *old_stringbuf = stringbuf;
2005 : struct obstack *string_obstack = get_string_obstack ();
2006 : char line_name[20];
2007 : const char *read_md_filename = get_filename ();
2008 : const char *fn = (read_md_filename ? read_md_filename : "rtx");
2009 : const char *slash;
2010 : for (slash = fn; *slash; slash ++)
2011 : if (*slash == '/' || *slash == '\\' || *slash == ':')
2012 : fn = slash + 1;
2013 : obstack_1grow (string_obstack, '*');
2014 : obstack_grow (string_obstack, fn, strlen (fn));
2015 : sprintf (line_name, ":%d", get_lineno ());
2016 : obstack_grow (string_obstack, line_name, strlen (line_name)+1);
2017 : stringbuf = XOBFINISH (string_obstack, char *);
2018 : copy_md_ptr_loc (stringbuf, old_stringbuf);
2019 : }
2020 :
2021 : /* Find attr-names in the string. */
2022 : char *str;
2023 : char *start, *end, *ptr;
2024 : char tmpstr[256];
2025 : ptr = &tmpstr[0];
2026 : end = stringbuf;
2027 : while ((start = strchr (end, '<')) && (end = strchr (start, '>')))
2028 : {
2029 : if ((end - start - 1 > 0)
2030 : && (end - start - 1 < (int)sizeof (tmpstr)))
2031 : {
2032 : strncpy (tmpstr, start+1, end-start-1);
2033 : tmpstr[end-start-1] = 0;
2034 : end++;
2035 : }
2036 : else
2037 : break;
2038 : struct mapping *m
2039 : = (struct mapping *) htab_find (substs.attrs, &ptr);
2040 : if (m != 0)
2041 : {
2042 : /* Here we should find linked subst-iter. */
2043 : str = find_subst_iter_by_attr (ptr);
2044 : if (str)
2045 : m = (struct mapping *) htab_find (substs.iterators, &str);
2046 : else
2047 : m = 0;
2048 : }
2049 : if (m != 0)
2050 : record_iterator_use (m, return_rtx, 0);
2051 : }
2052 : #endif /* #ifdef GENERATOR_FILE */
2053 :
2054 18 : const char *string_ptr = finalize_string (stringbuf);
2055 :
2056 18 : if (star_if_braced)
2057 0 : XTMPL (return_rtx, idx) = string_ptr;
2058 : else
2059 18 : XSTR (return_rtx, idx) = string_ptr;
2060 : }
2061 : break;
2062 :
2063 244 : case 'i':
2064 244 : case 'n':
2065 244 : case 'w':
2066 244 : case 'p':
2067 244 : case 'L':
2068 244 : {
2069 : /* Can be an iterator or an integer constant. */
2070 244 : file_location loc = read_name (&name);
2071 244 : record_potential_iterator_use (&ints, loc, return_rtx, idx,
2072 244 : name.string);
2073 244 : break;
2074 : }
2075 :
2076 0 : case 'r':
2077 0 : read_name (&name);
2078 0 : validate_const_int (name.string);
2079 0 : set_regno_raw (return_rtx, atoi (name.string), 1);
2080 0 : REG_ATTRS (return_rtx) = NULL;
2081 0 : break;
2082 :
2083 0 : default:
2084 0 : gcc_unreachable ();
2085 : }
2086 :
2087 2694 : return return_rtx;
2088 : }
2089 :
2090 : /* Read a nested rtx construct from the MD file and return it. */
2091 :
2092 : rtx
2093 1978 : rtx_reader::read_nested_rtx ()
2094 : {
2095 1978 : struct md_name name;
2096 1978 : rtx return_rtx;
2097 :
2098 : /* In compact dumps, trailing "(nil)" values can be omitted.
2099 : Handle such dumps. */
2100 1978 : if (peek_char () == ')')
2101 : return NULL_RTX;
2102 :
2103 1782 : require_char_ws ('(');
2104 :
2105 1782 : read_name (&name);
2106 1782 : if (strcmp (name.string, "nil") == 0)
2107 : return_rtx = NULL;
2108 : else
2109 1676 : return_rtx = read_rtx_code (name.string);
2110 :
2111 1782 : require_char_ws (')');
2112 :
2113 1782 : return_rtx = postprocess (return_rtx);
2114 :
2115 1782 : return return_rtx;
2116 : }
2117 :
2118 : /* Mutually recursive subroutine of read_rtx which reads
2119 : (thing x1 x2 x3 ...) and produces RTL as if
2120 : (thing x1 (thing x2 (thing x3 ...))) had been written.
2121 : When called, FORM is (thing x1 x2), and the file position
2122 : is just past the leading parenthesis of x3. Only works
2123 : for THINGs which are dyadic expressions, e.g. AND, IOR. */
2124 : rtx
2125 0 : rtx_reader::read_rtx_variadic (rtx form)
2126 : {
2127 0 : char c = '(';
2128 0 : rtx p = form, q;
2129 :
2130 0 : do
2131 : {
2132 0 : unread_char (c);
2133 :
2134 0 : q = rtx_alloc (GET_CODE (p));
2135 0 : PUT_MODE (q, GET_MODE (p));
2136 :
2137 0 : XEXP (q, 0) = XEXP (p, 1);
2138 0 : XEXP (q, 1) = read_nested_rtx ();
2139 :
2140 0 : XEXP (p, 1) = q;
2141 0 : p = q;
2142 0 : c = read_skip_spaces ();
2143 : }
2144 0 : while (c == '(');
2145 0 : unread_char (c);
2146 0 : return form;
2147 : }
2148 :
2149 : /* Constructor for class rtx_reader. */
2150 :
2151 104 : rtx_reader::rtx_reader (bool compact)
2152 : : md_reader (compact),
2153 104 : m_in_call_function_usage (false)
2154 : {
2155 : /* Set the global singleton pointer. */
2156 104 : rtx_reader_ptr = this;
2157 :
2158 104 : one_time_initialization ();
2159 104 : }
2160 :
2161 : /* Destructor for class rtx_reader. */
2162 :
2163 103 : rtx_reader::~rtx_reader ()
2164 : {
2165 : /* Clear the global singleton pointer. */
2166 103 : rtx_reader_ptr = NULL;
2167 103 : }
|