xref: /dflybsd-src/contrib/gcc-8.0/gcc/read-rtl.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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