Branch data Line data Source code
1 : : /* RTL reader for GCC.
2 : : Copyright (C) 1987-2025 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 : 966 : find_mode (const char *name)
199 : : {
200 : 966 : int i;
201 : :
202 : 18579 : for (i = 0; i < NUM_MACHINE_MODES; i++)
203 : 18579 : if (strcmp (GET_MODE_NAME (i), name) == 0)
204 : 966 : return i;
205 : :
206 : 0 : fatal_with_file_and_line ("unknown mode `%s'", name);
207 : : }
208 : :
209 : : static void
210 : 966 : apply_mode_iterator (rtx x, unsigned int, HOST_WIDE_INT mode)
211 : : {
212 : 966 : PUT_MODE (x, (machine_mode) mode);
213 : 966 : }
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 : 2030 : maybe_find_code (const char *name)
244 : : {
245 : 129578 : for (int i = 0; i < NUM_RTX_CODE; i++)
246 : 129156 : if (strcmp (GET_RTX_NAME (i), name) == 0)
247 : 1608 : return (rtx_code) i;
248 : :
249 : 1764 : for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++)
250 : 1763 : if (strcmp (compact_insn_names[i].name, name) == 0)
251 : 421 : 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 : 2030 : find_code (const char *name)
260 : : {
261 : 2030 : rtx_code code = maybe_find_code (name);
262 : 2030 : if (code == UNKNOWN)
263 : 1 : fatal_with_file_and_line ("unknown rtx code `%s'", name);
264 : 2029 : 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 : 216 : find_int (const char *name)
290 : : {
291 : 216 : HOST_WIDE_INT tmp;
292 : :
293 : 216 : struct md_constant tmp_def;
294 : 216 : tmp_def.name = const_cast<char *> (name);
295 : 216 : auto htab = rtx_reader_ptr->get_md_constants ();
296 : 216 : if (auto def = (struct md_constant *) htab_find (htab, &tmp_def))
297 : 0 : name = def->value;
298 : :
299 : 216 : 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 : 216 : 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 : 216 : return tmp;
316 : : }
317 : :
318 : : static void
319 : 216 : apply_int_iterator (rtx x, unsigned int index, HOST_WIDE_INT value)
320 : : {
321 : 216 : RTX_CODE code = GET_CODE (x);
322 : 216 : const char *format_ptr = GET_RTX_FORMAT (code);
323 : :
324 : 216 : 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 : 212 : case 'w':
334 : 212 : XWINT (x, index) = value;
335 : 212 : 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 : 216 : }
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 : 80 : add_mapping (struct iterator_group *group, htab_t table, const char *name)
1007 : : {
1008 : 80 : struct mapping *m;
1009 : 80 : void **slot;
1010 : :
1011 : 80 : m = XNEW (struct mapping);
1012 : 80 : m->name = xstrdup (name);
1013 : 80 : m->group = group;
1014 : 80 : m->values = 0;
1015 : 80 : m->current_value = NULL;
1016 : :
1017 : 80 : slot = htab_find_slot (table, m, INSERT);
1018 : 80 : if (*slot != 0)
1019 : 0 : fatal_with_file_and_line ("`%s' already defined", name);
1020 : :
1021 : 80 : *slot = m;
1022 : 80 : 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 : 11360 : add_map_value (struct map_value **end_ptr, int number, const char *string)
1031 : : {
1032 : 11360 : struct map_value *value;
1033 : :
1034 : 0 : value = XNEW (struct map_value);
1035 : 11360 : value->next = 0;
1036 : 11360 : value->number = number;
1037 : 11360 : value->string = string;
1038 : :
1039 : 11360 : *end_ptr = value;
1040 : 11360 : return &value->next;
1041 : : }
1042 : :
1043 : : /* Do one-time initialization of the mode and code attributes. */
1044 : :
1045 : : static void
1046 : 20 : initialize_iterators (void)
1047 : : {
1048 : 20 : struct mapping *lower, *upper;
1049 : 20 : struct map_value **lower_ptr, **upper_ptr;
1050 : 20 : char *copy, *p;
1051 : 20 : int i;
1052 : :
1053 : 20 : modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1054 : 20 : modes.iterators = htab_create (13, leading_string_hash,
1055 : : leading_string_eq_p, 0);
1056 : 20 : modes.type = "machine_mode";
1057 : 20 : modes.find_builtin = find_mode;
1058 : 20 : modes.apply_iterator = apply_mode_iterator;
1059 : 20 : modes.get_c_token = get_mode_token;
1060 : :
1061 : 20 : codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1062 : 20 : codes.iterators = htab_create (13, leading_string_hash,
1063 : : leading_string_eq_p, 0);
1064 : 20 : codes.type = "rtx_code";
1065 : 20 : codes.find_builtin = find_code;
1066 : 20 : codes.apply_iterator = apply_code_iterator;
1067 : 20 : codes.get_c_token = get_code_token;
1068 : :
1069 : 20 : ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1070 : 20 : ints.iterators = htab_create (13, leading_string_hash,
1071 : : leading_string_eq_p, 0);
1072 : 20 : ints.type = "int";
1073 : 20 : ints.find_builtin = find_int;
1074 : 20 : ints.apply_iterator = apply_int_iterator;
1075 : 20 : ints.get_c_token = get_int_token;
1076 : 20 : ints.has_self_attr = true;
1077 : :
1078 : 20 : substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
1079 : 20 : substs.iterators = htab_create (13, leading_string_hash,
1080 : : leading_string_eq_p, 0);
1081 : 20 : substs.type = "int";
1082 : 20 : 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 : 20 : substs.get_c_token = get_int_token;
1087 : :
1088 : 20 : lower = add_mapping (&modes, modes.attrs, "mode");
1089 : 20 : upper = add_mapping (&modes, modes.attrs, "MODE");
1090 : 20 : lower_ptr = &lower->values;
1091 : 20 : upper_ptr = &upper->values;
1092 : 2620 : for (i = 0; i < MAX_MACHINE_MODE; i++)
1093 : : {
1094 : 2600 : copy = xstrdup (GET_MODE_NAME (i));
1095 : 14460 : for (p = copy; *p != 0; p++)
1096 : 9260 : *p = TOLOWER (*p);
1097 : :
1098 : 2600 : upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
1099 : 2600 : lower_ptr = add_map_value (lower_ptr, i, copy);
1100 : : }
1101 : :
1102 : 20 : lower = add_mapping (&codes, codes.attrs, "code");
1103 : 20 : upper = add_mapping (&codes, codes.attrs, "CODE");
1104 : 20 : lower_ptr = &lower->values;
1105 : 20 : upper_ptr = &upper->values;
1106 : 3100 : for (i = 0; i < NUM_RTX_CODE; i++)
1107 : : {
1108 : 3080 : copy = xstrdup (GET_RTX_NAME (i));
1109 : 29500 : for (p = copy; *p != 0; p++)
1110 : 23340 : *p = TOUPPER (*p);
1111 : :
1112 : 3080 : lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
1113 : 3080 : upper_ptr = add_map_value (upper_ptr, i, copy);
1114 : : }
1115 : 20 : }
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 : 216 : validate_const_int (const char *string)
1164 : : {
1165 : 216 : const char *cp;
1166 : 216 : int valid = 1;
1167 : :
1168 : 216 : cp = string;
1169 : 216 : while (*cp && ISSPACE (*cp))
1170 : 0 : cp++;
1171 : 216 : if (*cp == '-' || *cp == '+')
1172 : 120 : cp++;
1173 : 216 : if (*cp == 0)
1174 : 0 : valid = 0;
1175 : 497 : for (; *cp; cp++)
1176 : 281 : if (! ISDIGIT (*cp))
1177 : : {
1178 : : valid = 0;
1179 : : break;
1180 : : }
1181 : 216 : if (!valid)
1182 : 0 : fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string);
1183 : 216 : }
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 : 1182 : 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 : 1182 : struct mapping *m;
1241 : 1182 : size_t len;
1242 : :
1243 : 1182 : len = strlen (name);
1244 : 1182 : 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 : 1182 : m = (struct mapping *) htab_find (group->iterators, &name);
1255 : 1182 : if (m != 0)
1256 : 0 : record_iterator_use (m, x, index);
1257 : : else
1258 : 1182 : group->apply_iterator (x, index, group->find_builtin (name));
1259 : : }
1260 : 1182 : }
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 : 94 : one_time_initialization (void)
1529 : : {
1530 : 94 : static bool initialized = false;
1531 : :
1532 : 94 : if (!initialized)
1533 : : {
1534 : 20 : initialize_iterators ();
1535 : 20 : initialized = true;
1536 : : }
1537 : 94 : }
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 : 305 : rtx_reader::read_until (const char *terminator_chars, bool consume_terminator)
1545 : : {
1546 : 305 : int ch = read_skip_spaces ();
1547 : 305 : unread_char (ch);
1548 : 305 : auto_vec<char> buf;
1549 : 2125 : while (1)
1550 : : {
1551 : 1215 : ch = read_char ();
1552 : 1215 : if (strchr (terminator_chars, ch))
1553 : : {
1554 : 305 : if (!consume_terminator)
1555 : 139 : unread_char (ch);
1556 : 305 : break;
1557 : : }
1558 : 910 : buf.safe_push (ch);
1559 : : }
1560 : 305 : buf.safe_push ('\0');
1561 : 610 : return xstrdup (buf.address ());
1562 : 305 : }
1563 : :
1564 : : /* Subroutine of read_rtx_code, for parsing zero or more flags. */
1565 : :
1566 : : static void
1567 : 2029 : read_flags (rtx return_rtx)
1568 : : {
1569 : 2369 : while (1)
1570 : : {
1571 : 2369 : int ch = read_char ();
1572 : 2369 : if (ch != '/')
1573 : : {
1574 : 2029 : unread_char (ch);
1575 : 2029 : break;
1576 : : }
1577 : :
1578 : 340 : int flag_char = read_char ();
1579 : 340 : 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 : 57 : case 'i':
1600 : 57 : RTX_FLAG (return_rtx, return_val) = 1;
1601 : 57 : break;
1602 : 0 : default:
1603 : 0 : fatal_with_file_and_line ("unrecognized flag: `%c'", flag_char);
1604 : : }
1605 : : }
1606 : 2029 : }
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 : 2030 : 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 : 2030 : 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 : 2040 : rtx_reader::read_rtx_code (const char *code_name)
1682 : : {
1683 : 2040 : RTX_CODE code;
1684 : 2040 : const char *format_ptr;
1685 : 2040 : struct md_name name;
1686 : 2040 : rtx return_rtx;
1687 : 2040 : int c;
1688 : :
1689 : : /* Linked list structure for making RTXs: */
1690 : 2040 : struct rtx_list
1691 : : {
1692 : : struct rtx_list *next;
1693 : : rtx value; /* Value of this node. */
1694 : : };
1695 : :
1696 : : #ifndef GENERATOR_FILE
1697 : 2040 : long reuse_id = -1;
1698 : : /* Handle reuse_rtx ids e.g. "(0|scratch:DI)". */
1699 : 2040 : 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 : 2040 : 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 : 2030 : 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 : 2030 : return_rtx = rtx_alloc_for_name (code_name);
1741 : 2029 : code = GET_CODE (return_rtx);
1742 : 2029 : format_ptr = GET_RTX_FORMAT (code);
1743 : 2029 : memset (return_rtx, 0, RTX_CODE_SIZE (code));
1744 : 2029 : PUT_CODE (return_rtx, code);
1745 : :
1746 : : #ifndef GENERATOR_FILE
1747 : 2029 : 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 : 2029 : read_flags (return_rtx);
1757 : :
1758 : : /* Read REG_NOTE names for EXPR_LIST and INSN_LIST. */
1759 : 2029 : if ((GET_CODE (return_rtx) == EXPR_LIST
1760 : : || GET_CODE (return_rtx) == INSN_LIST
1761 : 2029 : || 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 : 2029 : c = read_skip_spaces ();
1779 : 2029 : if (c == ':')
1780 : : {
1781 : 966 : file_location loc = read_name (&name);
1782 : 966 : record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string);
1783 : : }
1784 : : else
1785 : 1063 : unread_char (c);
1786 : :
1787 : 2029 : if (INSN_CHAIN_CODE_P (code))
1788 : : {
1789 : 425 : read_name (&name);
1790 : 425 : INSN_UID (return_rtx) = atoi (name.string);
1791 : : }
1792 : :
1793 : : /* Use the format_ptr to parse the various operands of this rtx. */
1794 : 7167 : for (int idx = 0; format_ptr[idx] != 0; idx++)
1795 : 5138 : 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 : 2029 : handle_any_trailing_information (return_rtx);
1800 : :
1801 : 2029 : 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 : 2029 : c = read_skip_spaces ();
1850 : : /* Syntactic sugar for AND and IOR, allowing Lisp-like
1851 : : arbitrary number of arguments for them. */
1852 : 2029 : 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 : 2029 : unread_char (c);
1858 : 2029 : 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 : 2500 : rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
1869 : : {
1870 : 2500 : RTX_CODE code = GET_CODE (return_rtx);
1871 : 2500 : const char *format_ptr = GET_RTX_FORMAT (code);
1872 : 2500 : int c;
1873 : 2500 : struct md_name name;
1874 : :
1875 : 2500 : 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 : 443 : case '0':
1880 : 443 : if (code == REG)
1881 : 0 : ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx);
1882 : : break;
1883 : :
1884 : 1762 : case 'e':
1885 : 1762 : XEXP (return_rtx, idx) = read_nested_rtx ();
1886 : 1762 : 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 : 37 : case 'E':
1906 : 37 : {
1907 : : /* Obstack to store scratch vector in. */
1908 : 37 : struct obstack vector_stack;
1909 : 37 : int list_counter = 0;
1910 : 37 : rtvec return_vec = NULL_RTVEC;
1911 : 37 : rtx saved_rtx = NULL_RTX;
1912 : :
1913 : 37 : require_char_ws ('[');
1914 : :
1915 : : /* Add expressions to a list, while keeping a count. */
1916 : 37 : obstack_init (&vector_stack);
1917 : 140 : while ((c = read_skip_spaces ()) && c != ']')
1918 : : {
1919 : 66 : if (c == EOF)
1920 : 0 : fatal_expected_char (']', c);
1921 : 66 : unread_char (c);
1922 : :
1923 : 66 : rtx value;
1924 : 66 : int repeat_count = 1;
1925 : 66 : 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 : 62 : else if (c == '(')
1942 : 62 : value = read_nested_rtx ();
1943 : : else
1944 : 0 : fatal_with_file_and_line ("unexpected character in vector");
1945 : :
1946 : 380 : for (; repeat_count > 0; repeat_count--)
1947 : : {
1948 : 314 : list_counter++;
1949 : 314 : obstack_ptr_grow (&vector_stack, value);
1950 : : }
1951 : 66 : saved_rtx = value;
1952 : : }
1953 : 37 : if (list_counter > 0)
1954 : : {
1955 : 37 : return_vec = rtvec_alloc (list_counter);
1956 : 37 : 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 : 37 : XVEC (return_rtx, idx) = return_vec;
1962 : 37 : obstack_free (&vector_stack, NULL);
1963 : : /* close bracket gotten */
1964 : : }
1965 : 37 : 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 : 216 : case 'i':
2066 : 216 : case 'n':
2067 : 216 : case 'w':
2068 : 216 : case 'p':
2069 : 216 : case 'L':
2070 : 216 : {
2071 : : /* Can be an iterator or an integer constant. */
2072 : 216 : file_location loc = read_name (&name);
2073 : 216 : record_potential_iterator_use (&ints, loc, return_rtx, idx,
2074 : 216 : name.string);
2075 : 216 : 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 : 2500 : return return_rtx;
2090 : : }
2091 : :
2092 : : /* Read a nested rtx construct from the MD file and return it. */
2093 : :
2094 : : rtx
2095 : 1824 : rtx_reader::read_nested_rtx ()
2096 : : {
2097 : 1824 : struct md_name name;
2098 : 1824 : rtx return_rtx;
2099 : :
2100 : : /* In compact dumps, trailing "(nil)" values can be omitted.
2101 : : Handle such dumps. */
2102 : 1824 : if (peek_char () == ')')
2103 : : return NULL_RTX;
2104 : :
2105 : 1655 : require_char_ws ('(');
2106 : :
2107 : 1655 : read_name (&name);
2108 : 1655 : if (strcmp (name.string, "nil") == 0)
2109 : : return_rtx = NULL;
2110 : : else
2111 : 1549 : return_rtx = read_rtx_code (name.string);
2112 : :
2113 : 1655 : require_char_ws (')');
2114 : :
2115 : 1655 : return_rtx = postprocess (return_rtx);
2116 : :
2117 : 1655 : 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 : 94 : rtx_reader::rtx_reader (bool compact)
2154 : : : md_reader (compact),
2155 : 94 : m_in_call_function_usage (false)
2156 : : {
2157 : : /* Set the global singleton pointer. */
2158 : 94 : rtx_reader_ptr = this;
2159 : :
2160 : 94 : one_time_initialization ();
2161 : 94 : }
2162 : :
2163 : : /* Destructor for class rtx_reader. */
2164 : :
2165 : 93 : rtx_reader::~rtx_reader ()
2166 : : {
2167 : : /* Clear the global singleton pointer. */
2168 : 93 : rtx_reader_ptr = NULL;
2169 : 93 : }
|