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