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