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