xref: /dflybsd-src/contrib/gcc-4.7/gcc/read-rtl.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* RTL reader for GCC.
2*e4b17023SJohn Marino    Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
3*e4b17023SJohn Marino    2003, 2004, 2005, 2007, 2008, 2010
4*e4b17023SJohn Marino    Free Software Foundation, Inc.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "bconfig.h"
23*e4b17023SJohn Marino 
24*e4b17023SJohn Marino /* Disable rtl checking; it conflicts with the iterator handling.  */
25*e4b17023SJohn Marino #undef ENABLE_RTL_CHECKING
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #include "system.h"
28*e4b17023SJohn Marino #include "coretypes.h"
29*e4b17023SJohn Marino #include "tm.h"
30*e4b17023SJohn Marino #include "rtl.h"
31*e4b17023SJohn Marino #include "obstack.h"
32*e4b17023SJohn Marino #include "hashtab.h"
33*e4b17023SJohn Marino #include "read-md.h"
34*e4b17023SJohn Marino #include "gensupport.h"
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino /* One element in a singly-linked list of (integer, string) pairs.  */
37*e4b17023SJohn Marino struct map_value {
38*e4b17023SJohn Marino   struct map_value *next;
39*e4b17023SJohn Marino   int number;
40*e4b17023SJohn Marino   const char *string;
41*e4b17023SJohn Marino };
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino /* Maps an iterator or attribute name to a list of (integer, string) pairs.
44*e4b17023SJohn Marino    The integers are mode or code values; the strings are either C conditions
45*e4b17023SJohn Marino    or attribute values.  */
46*e4b17023SJohn Marino struct mapping {
47*e4b17023SJohn Marino   /* The name of the iterator or attribute.  */
48*e4b17023SJohn Marino   const char *name;
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino   /* The group (modes or codes) to which the iterator or attribute belongs.  */
51*e4b17023SJohn Marino   struct iterator_group *group;
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino   /* Gives a unique number to the attribute or iterator.  Numbers are
54*e4b17023SJohn Marino      allocated consecutively, starting at 0.  */
55*e4b17023SJohn Marino   int index;
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino   /* The list of (integer, string) pairs.  */
58*e4b17023SJohn Marino   struct map_value *values;
59*e4b17023SJohn Marino };
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino /* A structure for abstracting the common parts of code and mode iterators.  */
62*e4b17023SJohn Marino struct iterator_group {
63*e4b17023SJohn Marino   /* Tables of "mapping" structures, one for attributes and one for iterators.  */
64*e4b17023SJohn Marino   htab_t attrs, iterators;
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino   /* The number of "real" modes or codes (and by extension, the first
67*e4b17023SJohn Marino      number available for use as an iterator placeholder).  */
68*e4b17023SJohn Marino   int num_builtins;
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino   /* Treat the given string as the name of a standard mode or code and
71*e4b17023SJohn Marino      return its integer value.  */
72*e4b17023SJohn Marino   int (*find_builtin) (const char *);
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino   /* Return true if the given rtx uses the given mode or code.  */
75*e4b17023SJohn Marino   bool (*uses_iterator_p) (rtx, int);
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino   /* Make the given rtx use the given mode or code.  */
78*e4b17023SJohn Marino   void (*apply_iterator) (rtx, int);
79*e4b17023SJohn Marino };
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino /* A structure used to pass data from read_rtx to apply_iterator_traverse
82*e4b17023SJohn Marino    via htab_traverse.  */
83*e4b17023SJohn Marino struct iterator_traverse_data {
84*e4b17023SJohn Marino   /* Instruction queue.  */
85*e4b17023SJohn Marino   rtx queue;
86*e4b17023SJohn Marino   /* Attributes seen for modes.  */
87*e4b17023SJohn Marino   struct map_value *mode_maps;
88*e4b17023SJohn Marino   /* The last unknown attribute used as a mode.  */
89*e4b17023SJohn Marino   const char *unknown_mode_attr;
90*e4b17023SJohn Marino };
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino /* If CODE is the number of a code iterator, return a real rtx code that
93*e4b17023SJohn Marino    has the same format.  Return CODE otherwise.  */
94*e4b17023SJohn Marino #define BELLWETHER_CODE(CODE) \
95*e4b17023SJohn Marino   ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE])
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino static int find_mode (const char *);
98*e4b17023SJohn Marino static bool uses_mode_iterator_p (rtx, int);
99*e4b17023SJohn Marino static void apply_mode_iterator (rtx, int);
100*e4b17023SJohn Marino static int find_code (const char *);
101*e4b17023SJohn Marino static bool uses_code_iterator_p (rtx, int);
102*e4b17023SJohn Marino static void apply_code_iterator (rtx, int);
103*e4b17023SJohn Marino static const char *apply_iterator_to_string (const char *, struct mapping *, int);
104*e4b17023SJohn Marino static rtx apply_iterator_to_rtx (rtx, struct mapping *, int,
105*e4b17023SJohn Marino 				  struct map_value *, const char **);
106*e4b17023SJohn Marino static bool uses_iterator_p (rtx, struct mapping *);
107*e4b17023SJohn Marino static const char *add_condition_to_string (const char *, const char *);
108*e4b17023SJohn Marino static void add_condition_to_rtx (rtx, const char *);
109*e4b17023SJohn Marino static int apply_iterator_traverse (void **, void *);
110*e4b17023SJohn Marino static struct mapping *add_mapping (struct iterator_group *, htab_t t,
111*e4b17023SJohn Marino 				    const char *);
112*e4b17023SJohn Marino static struct map_value **add_map_value (struct map_value **,
113*e4b17023SJohn Marino 					 int, const char *);
114*e4b17023SJohn Marino static void initialize_iterators (void);
115*e4b17023SJohn Marino static void read_conditions (void);
116*e4b17023SJohn Marino static void validate_const_int (const char *);
117*e4b17023SJohn Marino static int find_iterator (struct iterator_group *, const char *);
118*e4b17023SJohn Marino static struct mapping *read_mapping (struct iterator_group *, htab_t);
119*e4b17023SJohn Marino static void check_code_iterator (struct mapping *);
120*e4b17023SJohn Marino static rtx read_rtx_code (const char *, struct map_value **);
121*e4b17023SJohn Marino static rtx read_nested_rtx (struct map_value **);
122*e4b17023SJohn Marino static rtx read_rtx_variadic (struct map_value **, rtx);
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino /* The mode and code iterator structures.  */
125*e4b17023SJohn Marino static struct iterator_group modes, codes;
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino /* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE).  */
128*e4b17023SJohn Marino static enum rtx_code *bellwether_codes;
129*e4b17023SJohn Marino 
130*e4b17023SJohn Marino /* Implementations of the iterator_group callbacks for modes.  */
131*e4b17023SJohn Marino 
132*e4b17023SJohn Marino static int
find_mode(const char * name)133*e4b17023SJohn Marino find_mode (const char *name)
134*e4b17023SJohn Marino {
135*e4b17023SJohn Marino   int i;
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino   for (i = 0; i < NUM_MACHINE_MODES; i++)
138*e4b17023SJohn Marino     if (strcmp (GET_MODE_NAME (i), name) == 0)
139*e4b17023SJohn Marino       return i;
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino   fatal_with_file_and_line ("unknown mode `%s'", name);
142*e4b17023SJohn Marino }
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino static bool
uses_mode_iterator_p(rtx x,int mode)145*e4b17023SJohn Marino uses_mode_iterator_p (rtx x, int mode)
146*e4b17023SJohn Marino {
147*e4b17023SJohn Marino   return (int) GET_MODE (x) == mode;
148*e4b17023SJohn Marino }
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino static void
apply_mode_iterator(rtx x,int mode)151*e4b17023SJohn Marino apply_mode_iterator (rtx x, int mode)
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino   PUT_MODE (x, (enum machine_mode) mode);
154*e4b17023SJohn Marino }
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino /* Implementations of the iterator_group callbacks for codes.  */
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino static int
find_code(const char * name)159*e4b17023SJohn Marino find_code (const char *name)
160*e4b17023SJohn Marino {
161*e4b17023SJohn Marino   int i;
162*e4b17023SJohn Marino 
163*e4b17023SJohn Marino   for (i = 0; i < NUM_RTX_CODE; i++)
164*e4b17023SJohn Marino     if (strcmp (GET_RTX_NAME (i), name) == 0)
165*e4b17023SJohn Marino       return i;
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino   fatal_with_file_and_line ("unknown rtx code `%s'", name);
168*e4b17023SJohn Marino }
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino static bool
uses_code_iterator_p(rtx x,int code)171*e4b17023SJohn Marino uses_code_iterator_p (rtx x, int code)
172*e4b17023SJohn Marino {
173*e4b17023SJohn Marino   return (int) GET_CODE (x) == code;
174*e4b17023SJohn Marino }
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino static void
apply_code_iterator(rtx x,int code)177*e4b17023SJohn Marino apply_code_iterator (rtx x, int code)
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   PUT_CODE (x, (enum rtx_code) code);
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino /* Map a code or mode attribute string P to the underlying string for
183*e4b17023SJohn Marino    ITERATOR and VALUE.  */
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino static struct map_value *
map_attr_string(const char * p,struct mapping * iterator,int value)186*e4b17023SJohn Marino map_attr_string (const char *p, struct mapping *iterator, int value)
187*e4b17023SJohn Marino {
188*e4b17023SJohn Marino   const char *attr;
189*e4b17023SJohn Marino   struct mapping *m;
190*e4b17023SJohn Marino   struct map_value *v;
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino   /* If there's a "iterator:" prefix, check whether the iterator name matches.
193*e4b17023SJohn Marino      Set ATTR to the start of the attribute name.  */
194*e4b17023SJohn Marino   attr = strchr (p, ':');
195*e4b17023SJohn Marino   if (attr == 0)
196*e4b17023SJohn Marino     attr = p;
197*e4b17023SJohn Marino   else
198*e4b17023SJohn Marino     {
199*e4b17023SJohn Marino       if (strncmp (p, iterator->name, attr - p) != 0
200*e4b17023SJohn Marino 	  || iterator->name[attr - p] != 0)
201*e4b17023SJohn Marino 	return 0;
202*e4b17023SJohn Marino       attr++;
203*e4b17023SJohn Marino     }
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino   /* Find the attribute specification.  */
206*e4b17023SJohn Marino   m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
207*e4b17023SJohn Marino   if (m == 0)
208*e4b17023SJohn Marino     return 0;
209*e4b17023SJohn Marino 
210*e4b17023SJohn Marino   /* Find the attribute value for VALUE.  */
211*e4b17023SJohn Marino   for (v = m->values; v != 0; v = v->next)
212*e4b17023SJohn Marino     if (v->number == value)
213*e4b17023SJohn Marino       break;
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino   return v;
216*e4b17023SJohn Marino }
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino /* Given an attribute string used as a machine mode, return an index
219*e4b17023SJohn Marino    to store in the machine mode to be translated by
220*e4b17023SJohn Marino    apply_iterator_to_rtx.  */
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino static unsigned int
mode_attr_index(struct map_value ** mode_maps,const char * string)223*e4b17023SJohn Marino mode_attr_index (struct map_value **mode_maps, const char *string)
224*e4b17023SJohn Marino {
225*e4b17023SJohn Marino   char *p;
226*e4b17023SJohn Marino   struct map_value *mv;
227*e4b17023SJohn Marino 
228*e4b17023SJohn Marino   /* Copy the attribute string into permanent storage, without the
229*e4b17023SJohn Marino      angle brackets around it.  */
230*e4b17023SJohn Marino   obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2);
231*e4b17023SJohn Marino   p = XOBFINISH (&string_obstack, char *);
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino   mv = XNEW (struct map_value);
234*e4b17023SJohn Marino   mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
235*e4b17023SJohn Marino   mv->string = p;
236*e4b17023SJohn Marino   mv->next = *mode_maps;
237*e4b17023SJohn Marino   *mode_maps = mv;
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   /* We return a code which we can map back into this string: the
240*e4b17023SJohn Marino      number of machine modes + the number of mode iterators + the index
241*e4b17023SJohn Marino      we just used.  */
242*e4b17023SJohn Marino   return MAX_MACHINE_MODE + htab_elements (modes.iterators) + mv->number;
243*e4b17023SJohn Marino }
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino /* Apply MODE_MAPS to the top level of X, expanding cases where an
246*e4b17023SJohn Marino    attribute is used for a mode.  ITERATOR is the current iterator we are
247*e4b17023SJohn Marino    expanding, and VALUE is the value to which we are expanding it.
248*e4b17023SJohn Marino    This sets *UNKNOWN to true if we find a mode attribute which has not
249*e4b17023SJohn Marino    yet been defined, and does not change it otherwise.  */
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino static void
apply_mode_maps(rtx x,struct map_value * mode_maps,struct mapping * iterator,int value,const char ** unknown)252*e4b17023SJohn Marino apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *iterator,
253*e4b17023SJohn Marino 		 int value, const char **unknown)
254*e4b17023SJohn Marino {
255*e4b17023SJohn Marino   unsigned int offset;
256*e4b17023SJohn Marino   int indx;
257*e4b17023SJohn Marino   struct map_value *pm;
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   offset = MAX_MACHINE_MODE + htab_elements (modes.iterators);
260*e4b17023SJohn Marino   if (GET_MODE (x) < offset)
261*e4b17023SJohn Marino     return;
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   indx = GET_MODE (x) - offset;
264*e4b17023SJohn Marino   for (pm = mode_maps; pm; pm = pm->next)
265*e4b17023SJohn Marino     {
266*e4b17023SJohn Marino       if (pm->number == indx)
267*e4b17023SJohn Marino 	{
268*e4b17023SJohn Marino 	  struct map_value *v;
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino 	  v = map_attr_string (pm->string, iterator, value);
271*e4b17023SJohn Marino 	  if (v)
272*e4b17023SJohn Marino 	    PUT_MODE (x, (enum machine_mode) find_mode (v->string));
273*e4b17023SJohn Marino 	  else
274*e4b17023SJohn Marino 	    *unknown = pm->string;
275*e4b17023SJohn Marino 	  return;
276*e4b17023SJohn Marino 	}
277*e4b17023SJohn Marino     }
278*e4b17023SJohn Marino }
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino /* Given that ITERATOR is being expanded as VALUE, apply the appropriate
281*e4b17023SJohn Marino    string substitutions to STRING.  Return the new string if any changes
282*e4b17023SJohn Marino    were needed, otherwise return STRING itself.  */
283*e4b17023SJohn Marino 
284*e4b17023SJohn Marino static const char *
apply_iterator_to_string(const char * string,struct mapping * iterator,int value)285*e4b17023SJohn Marino apply_iterator_to_string (const char *string, struct mapping *iterator, int value)
286*e4b17023SJohn Marino {
287*e4b17023SJohn Marino   char *base, *copy, *p, *start, *end;
288*e4b17023SJohn Marino   struct map_value *v;
289*e4b17023SJohn Marino 
290*e4b17023SJohn Marino   if (string == 0)
291*e4b17023SJohn Marino     return string;
292*e4b17023SJohn Marino 
293*e4b17023SJohn Marino   base = p = copy = ASTRDUP (string);
294*e4b17023SJohn Marino   while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
295*e4b17023SJohn Marino     {
296*e4b17023SJohn Marino       p = start + 1;
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino       *end = 0;
299*e4b17023SJohn Marino       v = map_attr_string (p, iterator, value);
300*e4b17023SJohn Marino       *end = '>';
301*e4b17023SJohn Marino       if (v == 0)
302*e4b17023SJohn Marino 	continue;
303*e4b17023SJohn Marino 
304*e4b17023SJohn Marino       /* Add everything between the last copied byte and the '<',
305*e4b17023SJohn Marino 	 then add in the attribute value.  */
306*e4b17023SJohn Marino       obstack_grow (&string_obstack, base, start - base);
307*e4b17023SJohn Marino       obstack_grow (&string_obstack, v->string, strlen (v->string));
308*e4b17023SJohn Marino       base = end + 1;
309*e4b17023SJohn Marino     }
310*e4b17023SJohn Marino   if (base != copy)
311*e4b17023SJohn Marino     {
312*e4b17023SJohn Marino       obstack_grow (&string_obstack, base, strlen (base) + 1);
313*e4b17023SJohn Marino       copy = XOBFINISH (&string_obstack, char *);
314*e4b17023SJohn Marino       copy_md_ptr_loc (copy, string);
315*e4b17023SJohn Marino       return copy;
316*e4b17023SJohn Marino     }
317*e4b17023SJohn Marino   return string;
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino /* Return a copy of ORIGINAL in which all uses of ITERATOR have been
321*e4b17023SJohn Marino    replaced by VALUE.  MODE_MAPS holds information about attribute
322*e4b17023SJohn Marino    strings used for modes.  This sets *UNKNOWN_MODE_ATTR to the value of
323*e4b17023SJohn Marino    an unknown mode attribute, and does not change it otherwise.  */
324*e4b17023SJohn Marino 
325*e4b17023SJohn Marino static rtx
apply_iterator_to_rtx(rtx original,struct mapping * iterator,int value,struct map_value * mode_maps,const char ** unknown_mode_attr)326*e4b17023SJohn Marino apply_iterator_to_rtx (rtx original, struct mapping *iterator, int value,
327*e4b17023SJohn Marino 		       struct map_value *mode_maps,
328*e4b17023SJohn Marino 		       const char **unknown_mode_attr)
329*e4b17023SJohn Marino {
330*e4b17023SJohn Marino   struct iterator_group *group;
331*e4b17023SJohn Marino   const char *format_ptr;
332*e4b17023SJohn Marino   int i, j;
333*e4b17023SJohn Marino   rtx x;
334*e4b17023SJohn Marino   enum rtx_code bellwether_code;
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino   if (original == 0)
337*e4b17023SJohn Marino     return original;
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   /* Create a shallow copy of ORIGINAL.  */
340*e4b17023SJohn Marino   bellwether_code = BELLWETHER_CODE (GET_CODE (original));
341*e4b17023SJohn Marino   x = rtx_alloc (bellwether_code);
342*e4b17023SJohn Marino   memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
343*e4b17023SJohn Marino 
344*e4b17023SJohn Marino   /* Change the mode or code itself.  */
345*e4b17023SJohn Marino   group = iterator->group;
346*e4b17023SJohn Marino   if (group->uses_iterator_p (x, iterator->index + group->num_builtins))
347*e4b17023SJohn Marino     group->apply_iterator (x, value);
348*e4b17023SJohn Marino 
349*e4b17023SJohn Marino   if (mode_maps)
350*e4b17023SJohn Marino     apply_mode_maps (x, mode_maps, iterator, value, unknown_mode_attr);
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino   /* Change each string and recursively change each rtx.  */
353*e4b17023SJohn Marino   format_ptr = GET_RTX_FORMAT (bellwether_code);
354*e4b17023SJohn Marino   for (i = 0; format_ptr[i] != 0; i++)
355*e4b17023SJohn Marino     switch (format_ptr[i])
356*e4b17023SJohn Marino       {
357*e4b17023SJohn Marino       case 'T':
358*e4b17023SJohn Marino 	XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i), iterator, value);
359*e4b17023SJohn Marino 	break;
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino       case 'S':
362*e4b17023SJohn Marino       case 's':
363*e4b17023SJohn Marino 	XSTR (x, i) = apply_iterator_to_string (XSTR (x, i), iterator, value);
364*e4b17023SJohn Marino 	break;
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino       case 'e':
367*e4b17023SJohn Marino 	XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value,
368*e4b17023SJohn Marino 					     mode_maps, unknown_mode_attr);
369*e4b17023SJohn Marino 	break;
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino       case 'V':
372*e4b17023SJohn Marino       case 'E':
373*e4b17023SJohn Marino 	if (XVEC (original, i))
374*e4b17023SJohn Marino 	  {
375*e4b17023SJohn Marino 	    XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
376*e4b17023SJohn Marino 	    for (j = 0; j < XVECLEN (x, i); j++)
377*e4b17023SJohn Marino 	      XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j),
378*e4b17023SJohn Marino 							 iterator, value, mode_maps,
379*e4b17023SJohn Marino 							 unknown_mode_attr);
380*e4b17023SJohn Marino 	  }
381*e4b17023SJohn Marino 	break;
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino       default:
384*e4b17023SJohn Marino 	break;
385*e4b17023SJohn Marino       }
386*e4b17023SJohn Marino   return x;
387*e4b17023SJohn Marino }
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino /* Return true if X (or some subexpression of X) uses iterator ITERATOR.  */
390*e4b17023SJohn Marino 
391*e4b17023SJohn Marino static bool
uses_iterator_p(rtx x,struct mapping * iterator)392*e4b17023SJohn Marino uses_iterator_p (rtx x, struct mapping *iterator)
393*e4b17023SJohn Marino {
394*e4b17023SJohn Marino   struct iterator_group *group;
395*e4b17023SJohn Marino   const char *format_ptr;
396*e4b17023SJohn Marino   int i, j;
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino   if (x == 0)
399*e4b17023SJohn Marino     return false;
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino   group = iterator->group;
402*e4b17023SJohn Marino   if (group->uses_iterator_p (x, iterator->index + group->num_builtins))
403*e4b17023SJohn Marino     return true;
404*e4b17023SJohn Marino 
405*e4b17023SJohn Marino   format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x)));
406*e4b17023SJohn Marino   for (i = 0; format_ptr[i] != 0; i++)
407*e4b17023SJohn Marino     switch (format_ptr[i])
408*e4b17023SJohn Marino       {
409*e4b17023SJohn Marino       case 'e':
410*e4b17023SJohn Marino 	if (uses_iterator_p (XEXP (x, i), iterator))
411*e4b17023SJohn Marino 	  return true;
412*e4b17023SJohn Marino 	break;
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino       case 'V':
415*e4b17023SJohn Marino       case 'E':
416*e4b17023SJohn Marino 	if (XVEC (x, i))
417*e4b17023SJohn Marino 	  for (j = 0; j < XVECLEN (x, i); j++)
418*e4b17023SJohn Marino 	    if (uses_iterator_p (XVECEXP (x, i, j), iterator))
419*e4b17023SJohn Marino 	      return true;
420*e4b17023SJohn Marino 	break;
421*e4b17023SJohn Marino 
422*e4b17023SJohn Marino       default:
423*e4b17023SJohn Marino 	break;
424*e4b17023SJohn Marino       }
425*e4b17023SJohn Marino   return false;
426*e4b17023SJohn Marino }
427*e4b17023SJohn Marino 
428*e4b17023SJohn Marino /* Return a condition that must satisfy both ORIGINAL and EXTRA.  If ORIGINAL
429*e4b17023SJohn Marino    has the form "&& ..." (as used in define_insn_and_splits), assume that
430*e4b17023SJohn Marino    EXTRA is already satisfied.  Empty strings are treated like "true".  */
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino static const char *
add_condition_to_string(const char * original,const char * extra)433*e4b17023SJohn Marino add_condition_to_string (const char *original, const char *extra)
434*e4b17023SJohn Marino {
435*e4b17023SJohn Marino   if (original != 0 && original[0] == '&' && original[1] == '&')
436*e4b17023SJohn Marino     return original;
437*e4b17023SJohn Marino   return join_c_conditions (original, extra);
438*e4b17023SJohn Marino }
439*e4b17023SJohn Marino 
440*e4b17023SJohn Marino /* Like add_condition, but applied to all conditions in rtx X.  */
441*e4b17023SJohn Marino 
442*e4b17023SJohn Marino static void
add_condition_to_rtx(rtx x,const char * extra)443*e4b17023SJohn Marino add_condition_to_rtx (rtx x, const char *extra)
444*e4b17023SJohn Marino {
445*e4b17023SJohn Marino   switch (GET_CODE (x))
446*e4b17023SJohn Marino     {
447*e4b17023SJohn Marino     case DEFINE_INSN:
448*e4b17023SJohn Marino     case DEFINE_EXPAND:
449*e4b17023SJohn Marino       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
450*e4b17023SJohn Marino       break;
451*e4b17023SJohn Marino 
452*e4b17023SJohn Marino     case DEFINE_SPLIT:
453*e4b17023SJohn Marino     case DEFINE_PEEPHOLE:
454*e4b17023SJohn Marino     case DEFINE_PEEPHOLE2:
455*e4b17023SJohn Marino     case DEFINE_COND_EXEC:
456*e4b17023SJohn Marino       XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
457*e4b17023SJohn Marino       break;
458*e4b17023SJohn Marino 
459*e4b17023SJohn Marino     case DEFINE_INSN_AND_SPLIT:
460*e4b17023SJohn Marino       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
461*e4b17023SJohn Marino       XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
462*e4b17023SJohn Marino       break;
463*e4b17023SJohn Marino 
464*e4b17023SJohn Marino     default:
465*e4b17023SJohn Marino       break;
466*e4b17023SJohn Marino     }
467*e4b17023SJohn Marino }
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino /* A htab_traverse callback.  Search the EXPR_LIST given by DATA
470*e4b17023SJohn Marino    for rtxes that use the iterator in *SLOT.  Replace each such rtx
471*e4b17023SJohn Marino    with a list of expansions.  */
472*e4b17023SJohn Marino 
473*e4b17023SJohn Marino static int
apply_iterator_traverse(void ** slot,void * data)474*e4b17023SJohn Marino apply_iterator_traverse (void **slot, void *data)
475*e4b17023SJohn Marino {
476*e4b17023SJohn Marino   struct iterator_traverse_data *mtd = (struct iterator_traverse_data *) data;
477*e4b17023SJohn Marino   struct mapping *iterator;
478*e4b17023SJohn Marino   struct map_value *v;
479*e4b17023SJohn Marino   rtx elem, new_elem, original, x;
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino   iterator = (struct mapping *) *slot;
482*e4b17023SJohn Marino   for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
483*e4b17023SJohn Marino     if (uses_iterator_p (XEXP (elem, 0), iterator))
484*e4b17023SJohn Marino       {
485*e4b17023SJohn Marino 	/* For each iterator we expand, we set UNKNOWN_MODE_ATTR to NULL.
486*e4b17023SJohn Marino 	   If apply_iterator_rtx finds an unknown attribute for a mode,
487*e4b17023SJohn Marino 	   it will set it to the attribute.  We want to know whether
488*e4b17023SJohn Marino 	   the attribute is unknown after we have expanded all
489*e4b17023SJohn Marino 	   possible iterators, so setting it to NULL here gives us the
490*e4b17023SJohn Marino 	   right result when the hash table traversal is complete.  */
491*e4b17023SJohn Marino 	mtd->unknown_mode_attr = NULL;
492*e4b17023SJohn Marino 
493*e4b17023SJohn Marino 	original = XEXP (elem, 0);
494*e4b17023SJohn Marino 	for (v = iterator->values; v != 0; v = v->next)
495*e4b17023SJohn Marino 	  {
496*e4b17023SJohn Marino 	    x = apply_iterator_to_rtx (original, iterator, v->number,
497*e4b17023SJohn Marino 				       mtd->mode_maps,
498*e4b17023SJohn Marino 				       &mtd->unknown_mode_attr);
499*e4b17023SJohn Marino 	    add_condition_to_rtx (x, v->string);
500*e4b17023SJohn Marino 	    if (v != iterator->values)
501*e4b17023SJohn Marino 	      {
502*e4b17023SJohn Marino 		/* Insert a new EXPR_LIST node after ELEM and put the
503*e4b17023SJohn Marino 		   new expansion there.  */
504*e4b17023SJohn Marino 		new_elem = rtx_alloc (EXPR_LIST);
505*e4b17023SJohn Marino 		XEXP (new_elem, 1) = XEXP (elem, 1);
506*e4b17023SJohn Marino 		XEXP (elem, 1) = new_elem;
507*e4b17023SJohn Marino 		elem = new_elem;
508*e4b17023SJohn Marino 	      }
509*e4b17023SJohn Marino 	    XEXP (elem, 0) = x;
510*e4b17023SJohn Marino 	  }
511*e4b17023SJohn Marino     }
512*e4b17023SJohn Marino   return 1;
513*e4b17023SJohn Marino }
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino /* Add a new "mapping" structure to hashtable TABLE.  NAME is the name
516*e4b17023SJohn Marino    of the mapping and GROUP is the group to which it belongs.  */
517*e4b17023SJohn Marino 
518*e4b17023SJohn Marino static struct mapping *
add_mapping(struct iterator_group * group,htab_t table,const char * name)519*e4b17023SJohn Marino add_mapping (struct iterator_group *group, htab_t table, const char *name)
520*e4b17023SJohn Marino {
521*e4b17023SJohn Marino   struct mapping *m;
522*e4b17023SJohn Marino   void **slot;
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino   m = XNEW (struct mapping);
525*e4b17023SJohn Marino   m->name = xstrdup (name);
526*e4b17023SJohn Marino   m->group = group;
527*e4b17023SJohn Marino   m->index = htab_elements (table);
528*e4b17023SJohn Marino   m->values = 0;
529*e4b17023SJohn Marino 
530*e4b17023SJohn Marino   slot = htab_find_slot (table, m, INSERT);
531*e4b17023SJohn Marino   if (*slot != 0)
532*e4b17023SJohn Marino     fatal_with_file_and_line ("`%s' already defined", name);
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino   *slot = m;
535*e4b17023SJohn Marino   return m;
536*e4b17023SJohn Marino }
537*e4b17023SJohn Marino 
538*e4b17023SJohn Marino /* Add the pair (NUMBER, STRING) to a list of map_value structures.
539*e4b17023SJohn Marino    END_PTR points to the current null terminator for the list; return
540*e4b17023SJohn Marino    a pointer the new null terminator.  */
541*e4b17023SJohn Marino 
542*e4b17023SJohn Marino static struct map_value **
add_map_value(struct map_value ** end_ptr,int number,const char * string)543*e4b17023SJohn Marino add_map_value (struct map_value **end_ptr, int number, const char *string)
544*e4b17023SJohn Marino {
545*e4b17023SJohn Marino   struct map_value *value;
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino   value = XNEW (struct map_value);
548*e4b17023SJohn Marino   value->next = 0;
549*e4b17023SJohn Marino   value->number = number;
550*e4b17023SJohn Marino   value->string = string;
551*e4b17023SJohn Marino 
552*e4b17023SJohn Marino   *end_ptr = value;
553*e4b17023SJohn Marino   return &value->next;
554*e4b17023SJohn Marino }
555*e4b17023SJohn Marino 
556*e4b17023SJohn Marino /* Do one-time initialization of the mode and code attributes.  */
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino static void
initialize_iterators(void)559*e4b17023SJohn Marino initialize_iterators (void)
560*e4b17023SJohn Marino {
561*e4b17023SJohn Marino   struct mapping *lower, *upper;
562*e4b17023SJohn Marino   struct map_value **lower_ptr, **upper_ptr;
563*e4b17023SJohn Marino   char *copy, *p;
564*e4b17023SJohn Marino   int i;
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino   modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
567*e4b17023SJohn Marino   modes.iterators = htab_create (13, leading_string_hash,
568*e4b17023SJohn Marino 				 leading_string_eq_p, 0);
569*e4b17023SJohn Marino   modes.num_builtins = MAX_MACHINE_MODE;
570*e4b17023SJohn Marino   modes.find_builtin = find_mode;
571*e4b17023SJohn Marino   modes.uses_iterator_p = uses_mode_iterator_p;
572*e4b17023SJohn Marino   modes.apply_iterator = apply_mode_iterator;
573*e4b17023SJohn Marino 
574*e4b17023SJohn Marino   codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
575*e4b17023SJohn Marino   codes.iterators = htab_create (13, leading_string_hash,
576*e4b17023SJohn Marino 				 leading_string_eq_p, 0);
577*e4b17023SJohn Marino   codes.num_builtins = NUM_RTX_CODE;
578*e4b17023SJohn Marino   codes.find_builtin = find_code;
579*e4b17023SJohn Marino   codes.uses_iterator_p = uses_code_iterator_p;
580*e4b17023SJohn Marino   codes.apply_iterator = apply_code_iterator;
581*e4b17023SJohn Marino 
582*e4b17023SJohn Marino   lower = add_mapping (&modes, modes.attrs, "mode");
583*e4b17023SJohn Marino   upper = add_mapping (&modes, modes.attrs, "MODE");
584*e4b17023SJohn Marino   lower_ptr = &lower->values;
585*e4b17023SJohn Marino   upper_ptr = &upper->values;
586*e4b17023SJohn Marino   for (i = 0; i < MAX_MACHINE_MODE; i++)
587*e4b17023SJohn Marino     {
588*e4b17023SJohn Marino       copy = xstrdup (GET_MODE_NAME (i));
589*e4b17023SJohn Marino       for (p = copy; *p != 0; p++)
590*e4b17023SJohn Marino 	*p = TOLOWER (*p);
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino       upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
593*e4b17023SJohn Marino       lower_ptr = add_map_value (lower_ptr, i, copy);
594*e4b17023SJohn Marino     }
595*e4b17023SJohn Marino 
596*e4b17023SJohn Marino   lower = add_mapping (&codes, codes.attrs, "code");
597*e4b17023SJohn Marino   upper = add_mapping (&codes, codes.attrs, "CODE");
598*e4b17023SJohn Marino   lower_ptr = &lower->values;
599*e4b17023SJohn Marino   upper_ptr = &upper->values;
600*e4b17023SJohn Marino   for (i = 0; i < NUM_RTX_CODE; i++)
601*e4b17023SJohn Marino     {
602*e4b17023SJohn Marino       copy = xstrdup (GET_RTX_NAME (i));
603*e4b17023SJohn Marino       for (p = copy; *p != 0; p++)
604*e4b17023SJohn Marino 	*p = TOUPPER (*p);
605*e4b17023SJohn Marino 
606*e4b17023SJohn Marino       lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
607*e4b17023SJohn Marino       upper_ptr = add_map_value (upper_ptr, i, copy);
608*e4b17023SJohn Marino     }
609*e4b17023SJohn Marino }
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino /* Provide a version of a function to read a long long if the system does
612*e4b17023SJohn Marino    not provide one.  */
613*e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
614*e4b17023SJohn Marino HOST_WIDE_INT atoll (const char *);
615*e4b17023SJohn Marino 
616*e4b17023SJohn Marino HOST_WIDE_INT
atoll(const char * p)617*e4b17023SJohn Marino atoll (const char *p)
618*e4b17023SJohn Marino {
619*e4b17023SJohn Marino   int neg = 0;
620*e4b17023SJohn Marino   HOST_WIDE_INT tmp_wide;
621*e4b17023SJohn Marino 
622*e4b17023SJohn Marino   while (ISSPACE (*p))
623*e4b17023SJohn Marino     p++;
624*e4b17023SJohn Marino   if (*p == '-')
625*e4b17023SJohn Marino     neg = 1, p++;
626*e4b17023SJohn Marino   else if (*p == '+')
627*e4b17023SJohn Marino     p++;
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino   tmp_wide = 0;
630*e4b17023SJohn Marino   while (ISDIGIT (*p))
631*e4b17023SJohn Marino     {
632*e4b17023SJohn Marino       HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
633*e4b17023SJohn Marino       if (new_wide < tmp_wide)
634*e4b17023SJohn Marino 	{
635*e4b17023SJohn Marino 	  /* Return INT_MAX equiv on overflow.  */
636*e4b17023SJohn Marino 	  tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
637*e4b17023SJohn Marino 	  break;
638*e4b17023SJohn Marino 	}
639*e4b17023SJohn Marino       tmp_wide = new_wide;
640*e4b17023SJohn Marino       p++;
641*e4b17023SJohn Marino     }
642*e4b17023SJohn Marino 
643*e4b17023SJohn Marino   if (neg)
644*e4b17023SJohn Marino     tmp_wide = -tmp_wide;
645*e4b17023SJohn Marino   return tmp_wide;
646*e4b17023SJohn Marino }
647*e4b17023SJohn Marino #endif
648*e4b17023SJohn Marino 
649*e4b17023SJohn Marino /* Process a define_conditions directive, starting with the optional
650*e4b17023SJohn Marino    space after the "define_conditions".  The directive looks like this:
651*e4b17023SJohn Marino 
652*e4b17023SJohn Marino      (define_conditions [
653*e4b17023SJohn Marino         (number "string")
654*e4b17023SJohn Marino         (number "string")
655*e4b17023SJohn Marino         ...
656*e4b17023SJohn Marino      ])
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino    It's not intended to appear in machine descriptions.  It is
659*e4b17023SJohn Marino    generated by (the program generated by) genconditions.c, and
660*e4b17023SJohn Marino    slipped in at the beginning of the sequence of MD files read by
661*e4b17023SJohn Marino    most of the other generators.  */
662*e4b17023SJohn Marino static void
read_conditions(void)663*e4b17023SJohn Marino read_conditions (void)
664*e4b17023SJohn Marino {
665*e4b17023SJohn Marino   int c;
666*e4b17023SJohn Marino 
667*e4b17023SJohn Marino   c = read_skip_spaces ();
668*e4b17023SJohn Marino   if (c != '[')
669*e4b17023SJohn Marino     fatal_expected_char ('[', c);
670*e4b17023SJohn Marino 
671*e4b17023SJohn Marino   while ( (c = read_skip_spaces ()) != ']')
672*e4b17023SJohn Marino     {
673*e4b17023SJohn Marino       struct md_name name;
674*e4b17023SJohn Marino       char *expr;
675*e4b17023SJohn Marino       int value;
676*e4b17023SJohn Marino 
677*e4b17023SJohn Marino       if (c != '(')
678*e4b17023SJohn Marino 	fatal_expected_char ('(', c);
679*e4b17023SJohn Marino 
680*e4b17023SJohn Marino       read_name (&name);
681*e4b17023SJohn Marino       validate_const_int (name.string);
682*e4b17023SJohn Marino       value = atoi (name.string);
683*e4b17023SJohn Marino 
684*e4b17023SJohn Marino       c = read_skip_spaces ();
685*e4b17023SJohn Marino       if (c != '"')
686*e4b17023SJohn Marino 	fatal_expected_char ('"', c);
687*e4b17023SJohn Marino       expr = read_quoted_string ();
688*e4b17023SJohn Marino 
689*e4b17023SJohn Marino       c = read_skip_spaces ();
690*e4b17023SJohn Marino       if (c != ')')
691*e4b17023SJohn Marino 	fatal_expected_char (')', c);
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino       add_c_test (expr, value);
694*e4b17023SJohn Marino     }
695*e4b17023SJohn Marino }
696*e4b17023SJohn Marino 
697*e4b17023SJohn Marino static void
validate_const_int(const char * string)698*e4b17023SJohn Marino validate_const_int (const char *string)
699*e4b17023SJohn Marino {
700*e4b17023SJohn Marino   const char *cp;
701*e4b17023SJohn Marino   int valid = 1;
702*e4b17023SJohn Marino 
703*e4b17023SJohn Marino   cp = string;
704*e4b17023SJohn Marino   while (*cp && ISSPACE (*cp))
705*e4b17023SJohn Marino     cp++;
706*e4b17023SJohn Marino   if (*cp == '-' || *cp == '+')
707*e4b17023SJohn Marino     cp++;
708*e4b17023SJohn Marino   if (*cp == 0)
709*e4b17023SJohn Marino     valid = 0;
710*e4b17023SJohn Marino   for (; *cp; cp++)
711*e4b17023SJohn Marino     if (! ISDIGIT (*cp))
712*e4b17023SJohn Marino       valid = 0;
713*e4b17023SJohn Marino   if (!valid)
714*e4b17023SJohn Marino     fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string);
715*e4b17023SJohn Marino }
716*e4b17023SJohn Marino 
717*e4b17023SJohn Marino /* Search GROUP for a mode or code called NAME and return its numerical
718*e4b17023SJohn Marino    identifier.  */
719*e4b17023SJohn Marino 
720*e4b17023SJohn Marino static int
find_iterator(struct iterator_group * group,const char * name)721*e4b17023SJohn Marino find_iterator (struct iterator_group *group, const char *name)
722*e4b17023SJohn Marino {
723*e4b17023SJohn Marino   struct mapping *m;
724*e4b17023SJohn Marino 
725*e4b17023SJohn Marino   m = (struct mapping *) htab_find (group->iterators, &name);
726*e4b17023SJohn Marino   if (m != 0)
727*e4b17023SJohn Marino     return m->index + group->num_builtins;
728*e4b17023SJohn Marino   return group->find_builtin (name);
729*e4b17023SJohn Marino }
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino /* Finish reading a declaration of the form:
732*e4b17023SJohn Marino 
733*e4b17023SJohn Marino        (define... <name> [<value1> ... <valuen>])
734*e4b17023SJohn Marino 
735*e4b17023SJohn Marino    from the MD file, where each <valuei> is either a bare symbol name or a
736*e4b17023SJohn Marino    "(<name> <string>)" pair.  The "(define..." part has already been read.
737*e4b17023SJohn Marino 
738*e4b17023SJohn Marino    Represent the declaration as a "mapping" structure; add it to TABLE
739*e4b17023SJohn Marino    (which belongs to GROUP) and return it.  */
740*e4b17023SJohn Marino 
741*e4b17023SJohn Marino static struct mapping *
read_mapping(struct iterator_group * group,htab_t table)742*e4b17023SJohn Marino read_mapping (struct iterator_group *group, htab_t table)
743*e4b17023SJohn Marino {
744*e4b17023SJohn Marino   struct md_name name;
745*e4b17023SJohn Marino   struct mapping *m;
746*e4b17023SJohn Marino   struct map_value **end_ptr;
747*e4b17023SJohn Marino   const char *string;
748*e4b17023SJohn Marino   int number, c;
749*e4b17023SJohn Marino 
750*e4b17023SJohn Marino   /* Read the mapping name and create a structure for it.  */
751*e4b17023SJohn Marino   read_name (&name);
752*e4b17023SJohn Marino   m = add_mapping (group, table, name.string);
753*e4b17023SJohn Marino 
754*e4b17023SJohn Marino   c = read_skip_spaces ();
755*e4b17023SJohn Marino   if (c != '[')
756*e4b17023SJohn Marino     fatal_expected_char ('[', c);
757*e4b17023SJohn Marino 
758*e4b17023SJohn Marino   /* Read each value.  */
759*e4b17023SJohn Marino   end_ptr = &m->values;
760*e4b17023SJohn Marino   c = read_skip_spaces ();
761*e4b17023SJohn Marino   do
762*e4b17023SJohn Marino     {
763*e4b17023SJohn Marino       if (c != '(')
764*e4b17023SJohn Marino 	{
765*e4b17023SJohn Marino 	  /* A bare symbol name that is implicitly paired to an
766*e4b17023SJohn Marino 	     empty string.  */
767*e4b17023SJohn Marino 	  unread_char (c);
768*e4b17023SJohn Marino 	  read_name (&name);
769*e4b17023SJohn Marino 	  string = "";
770*e4b17023SJohn Marino 	}
771*e4b17023SJohn Marino       else
772*e4b17023SJohn Marino 	{
773*e4b17023SJohn Marino 	  /* A "(name string)" pair.  */
774*e4b17023SJohn Marino 	  read_name (&name);
775*e4b17023SJohn Marino 	  string = read_string (false);
776*e4b17023SJohn Marino 	  c = read_skip_spaces ();
777*e4b17023SJohn Marino 	  if (c != ')')
778*e4b17023SJohn Marino 	    fatal_expected_char (')', c);
779*e4b17023SJohn Marino 	}
780*e4b17023SJohn Marino       number = group->find_builtin (name.string);
781*e4b17023SJohn Marino       end_ptr = add_map_value (end_ptr, number, string);
782*e4b17023SJohn Marino       c = read_skip_spaces ();
783*e4b17023SJohn Marino     }
784*e4b17023SJohn Marino   while (c != ']');
785*e4b17023SJohn Marino 
786*e4b17023SJohn Marino   return m;
787*e4b17023SJohn Marino }
788*e4b17023SJohn Marino 
789*e4b17023SJohn Marino /* Check newly-created code iterator ITERATOR to see whether every code has the
790*e4b17023SJohn Marino    same format.  Initialize the iterator's entry in bellwether_codes.  */
791*e4b17023SJohn Marino 
792*e4b17023SJohn Marino static void
check_code_iterator(struct mapping * iterator)793*e4b17023SJohn Marino check_code_iterator (struct mapping *iterator)
794*e4b17023SJohn Marino {
795*e4b17023SJohn Marino   struct map_value *v;
796*e4b17023SJohn Marino   enum rtx_code bellwether;
797*e4b17023SJohn Marino 
798*e4b17023SJohn Marino   bellwether = (enum rtx_code) iterator->values->number;
799*e4b17023SJohn Marino   for (v = iterator->values->next; v != 0; v = v->next)
800*e4b17023SJohn Marino     if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
801*e4b17023SJohn Marino       fatal_with_file_and_line ("code iterator `%s' combines "
802*e4b17023SJohn Marino 				"different rtx formats", iterator->name);
803*e4b17023SJohn Marino 
804*e4b17023SJohn Marino   bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
805*e4b17023SJohn Marino 				 iterator->index + 1);
806*e4b17023SJohn Marino   bellwether_codes[iterator->index] = bellwether;
807*e4b17023SJohn Marino }
808*e4b17023SJohn Marino 
809*e4b17023SJohn Marino /* Read an rtx-related declaration from the MD file, given that it
810*e4b17023SJohn Marino    starts with directive name RTX_NAME.  Return true if it expands to
811*e4b17023SJohn Marino    one or more rtxes (as defined by rtx.def).  When returning true,
812*e4b17023SJohn Marino    store the list of rtxes as an EXPR_LIST in *X.  */
813*e4b17023SJohn Marino 
814*e4b17023SJohn Marino bool
read_rtx(const char * rtx_name,rtx * x)815*e4b17023SJohn Marino read_rtx (const char *rtx_name, rtx *x)
816*e4b17023SJohn Marino {
817*e4b17023SJohn Marino   static rtx queue_head;
818*e4b17023SJohn Marino   struct map_value *mode_maps;
819*e4b17023SJohn Marino   struct iterator_traverse_data mtd;
820*e4b17023SJohn Marino 
821*e4b17023SJohn Marino   /* Do one-time initialization.  */
822*e4b17023SJohn Marino   if (queue_head == 0)
823*e4b17023SJohn Marino     {
824*e4b17023SJohn Marino       initialize_iterators ();
825*e4b17023SJohn Marino       queue_head = rtx_alloc (EXPR_LIST);
826*e4b17023SJohn Marino     }
827*e4b17023SJohn Marino 
828*e4b17023SJohn Marino   /* Handle various rtx-related declarations that aren't themselves
829*e4b17023SJohn Marino      encoded as rtxes.  */
830*e4b17023SJohn Marino   if (strcmp (rtx_name, "define_conditions") == 0)
831*e4b17023SJohn Marino     {
832*e4b17023SJohn Marino       read_conditions ();
833*e4b17023SJohn Marino       return false;
834*e4b17023SJohn Marino     }
835*e4b17023SJohn Marino   if (strcmp (rtx_name, "define_mode_attr") == 0)
836*e4b17023SJohn Marino     {
837*e4b17023SJohn Marino       read_mapping (&modes, modes.attrs);
838*e4b17023SJohn Marino       return false;
839*e4b17023SJohn Marino     }
840*e4b17023SJohn Marino   if (strcmp (rtx_name, "define_mode_iterator") == 0)
841*e4b17023SJohn Marino     {
842*e4b17023SJohn Marino       read_mapping (&modes, modes.iterators);
843*e4b17023SJohn Marino       return false;
844*e4b17023SJohn Marino     }
845*e4b17023SJohn Marino   if (strcmp (rtx_name, "define_code_attr") == 0)
846*e4b17023SJohn Marino     {
847*e4b17023SJohn Marino       read_mapping (&codes, codes.attrs);
848*e4b17023SJohn Marino       return false;
849*e4b17023SJohn Marino     }
850*e4b17023SJohn Marino   if (strcmp (rtx_name, "define_code_iterator") == 0)
851*e4b17023SJohn Marino     {
852*e4b17023SJohn Marino       check_code_iterator (read_mapping (&codes, codes.iterators));
853*e4b17023SJohn Marino       return false;
854*e4b17023SJohn Marino     }
855*e4b17023SJohn Marino 
856*e4b17023SJohn Marino   mode_maps = 0;
857*e4b17023SJohn Marino   XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps);
858*e4b17023SJohn Marino   XEXP (queue_head, 1) = 0;
859*e4b17023SJohn Marino 
860*e4b17023SJohn Marino   mtd.queue = queue_head;
861*e4b17023SJohn Marino   mtd.mode_maps = mode_maps;
862*e4b17023SJohn Marino   mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
863*e4b17023SJohn Marino   htab_traverse (modes.iterators, apply_iterator_traverse, &mtd);
864*e4b17023SJohn Marino   htab_traverse (codes.iterators, apply_iterator_traverse, &mtd);
865*e4b17023SJohn Marino   if (mtd.unknown_mode_attr)
866*e4b17023SJohn Marino     fatal_with_file_and_line ("undefined attribute '%s' used for mode",
867*e4b17023SJohn Marino 			      mtd.unknown_mode_attr);
868*e4b17023SJohn Marino 
869*e4b17023SJohn Marino   *x = queue_head;
870*e4b17023SJohn Marino   return true;
871*e4b17023SJohn Marino }
872*e4b17023SJohn Marino 
873*e4b17023SJohn Marino /* Subroutine of read_rtx and read_nested_rtx.  CODE_NAME is the name of
874*e4b17023SJohn Marino    either an rtx code or a code iterator.  Parse the rest of the rtx and
875*e4b17023SJohn Marino    return it.  MODE_MAPS is as for iterator_traverse_data.  */
876*e4b17023SJohn Marino 
877*e4b17023SJohn Marino static rtx
read_rtx_code(const char * code_name,struct map_value ** mode_maps)878*e4b17023SJohn Marino read_rtx_code (const char *code_name, struct map_value **mode_maps)
879*e4b17023SJohn Marino {
880*e4b17023SJohn Marino   int i;
881*e4b17023SJohn Marino   RTX_CODE real_code, bellwether_code;
882*e4b17023SJohn Marino   const char *format_ptr;
883*e4b17023SJohn Marino   struct md_name name;
884*e4b17023SJohn Marino   rtx return_rtx;
885*e4b17023SJohn Marino   int c;
886*e4b17023SJohn Marino   int tmp_int;
887*e4b17023SJohn Marino   HOST_WIDE_INT tmp_wide;
888*e4b17023SJohn Marino 
889*e4b17023SJohn Marino   /* Linked list structure for making RTXs: */
890*e4b17023SJohn Marino   struct rtx_list
891*e4b17023SJohn Marino     {
892*e4b17023SJohn Marino       struct rtx_list *next;
893*e4b17023SJohn Marino       rtx value;		/* Value of this node.  */
894*e4b17023SJohn Marino     };
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino   real_code = (enum rtx_code) find_iterator (&codes, code_name);
897*e4b17023SJohn Marino   bellwether_code = BELLWETHER_CODE (real_code);
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino   /* If we end up with an insn expression then we free this space below.  */
900*e4b17023SJohn Marino   return_rtx = rtx_alloc (bellwether_code);
901*e4b17023SJohn Marino   format_ptr = GET_RTX_FORMAT (bellwether_code);
902*e4b17023SJohn Marino   PUT_CODE (return_rtx, real_code);
903*e4b17023SJohn Marino 
904*e4b17023SJohn Marino   /* If what follows is `: mode ', read it and
905*e4b17023SJohn Marino      store the mode in the rtx.  */
906*e4b17023SJohn Marino 
907*e4b17023SJohn Marino   i = read_skip_spaces ();
908*e4b17023SJohn Marino   if (i == ':')
909*e4b17023SJohn Marino     {
910*e4b17023SJohn Marino       unsigned int mode;
911*e4b17023SJohn Marino 
912*e4b17023SJohn Marino       read_name (&name);
913*e4b17023SJohn Marino       if (name.string[0] != '<' || name.string[strlen (name.string) - 1] != '>')
914*e4b17023SJohn Marino 	mode = find_iterator (&modes, name.string);
915*e4b17023SJohn Marino       else
916*e4b17023SJohn Marino 	mode = mode_attr_index (mode_maps, name.string);
917*e4b17023SJohn Marino       PUT_MODE (return_rtx, (enum machine_mode) mode);
918*e4b17023SJohn Marino       if (GET_MODE (return_rtx) != mode)
919*e4b17023SJohn Marino 	fatal_with_file_and_line ("mode too large");
920*e4b17023SJohn Marino     }
921*e4b17023SJohn Marino   else
922*e4b17023SJohn Marino     unread_char (i);
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino   for (i = 0; format_ptr[i] != 0; i++)
925*e4b17023SJohn Marino     switch (format_ptr[i])
926*e4b17023SJohn Marino       {
927*e4b17023SJohn Marino 	/* 0 means a field for internal use only.
928*e4b17023SJohn Marino 	   Don't expect it to be present in the input.  */
929*e4b17023SJohn Marino       case '0':
930*e4b17023SJohn Marino 	break;
931*e4b17023SJohn Marino 
932*e4b17023SJohn Marino       case 'e':
933*e4b17023SJohn Marino       case 'u':
934*e4b17023SJohn Marino 	XEXP (return_rtx, i) = read_nested_rtx (mode_maps);
935*e4b17023SJohn Marino 	break;
936*e4b17023SJohn Marino 
937*e4b17023SJohn Marino       case 'V':
938*e4b17023SJohn Marino 	/* 'V' is an optional vector: if a closeparen follows,
939*e4b17023SJohn Marino 	   just store NULL for this element.  */
940*e4b17023SJohn Marino 	c = read_skip_spaces ();
941*e4b17023SJohn Marino 	unread_char (c);
942*e4b17023SJohn Marino 	if (c == ')')
943*e4b17023SJohn Marino 	  {
944*e4b17023SJohn Marino 	    XVEC (return_rtx, i) = 0;
945*e4b17023SJohn Marino 	    break;
946*e4b17023SJohn Marino 	  }
947*e4b17023SJohn Marino 	/* Now process the vector.  */
948*e4b17023SJohn Marino 
949*e4b17023SJohn Marino       case 'E':
950*e4b17023SJohn Marino 	{
951*e4b17023SJohn Marino 	  /* Obstack to store scratch vector in.  */
952*e4b17023SJohn Marino 	  struct obstack vector_stack;
953*e4b17023SJohn Marino 	  int list_counter = 0;
954*e4b17023SJohn Marino 	  rtvec return_vec = NULL_RTVEC;
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino 	  c = read_skip_spaces ();
957*e4b17023SJohn Marino 	  if (c != '[')
958*e4b17023SJohn Marino 	    fatal_expected_char ('[', c);
959*e4b17023SJohn Marino 
960*e4b17023SJohn Marino 	  /* Add expressions to a list, while keeping a count.  */
961*e4b17023SJohn Marino 	  obstack_init (&vector_stack);
962*e4b17023SJohn Marino 	  while ((c = read_skip_spaces ()) && c != ']')
963*e4b17023SJohn Marino 	    {
964*e4b17023SJohn Marino 	      if (c == EOF)
965*e4b17023SJohn Marino 		fatal_expected_char (']', c);
966*e4b17023SJohn Marino 	      unread_char (c);
967*e4b17023SJohn Marino 	      list_counter++;
968*e4b17023SJohn Marino 	      obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps));
969*e4b17023SJohn Marino 	    }
970*e4b17023SJohn Marino 	  if (list_counter > 0)
971*e4b17023SJohn Marino 	    {
972*e4b17023SJohn Marino 	      return_vec = rtvec_alloc (list_counter);
973*e4b17023SJohn Marino 	      memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
974*e4b17023SJohn Marino 		      list_counter * sizeof (rtx));
975*e4b17023SJohn Marino 	    }
976*e4b17023SJohn Marino 	  else if (format_ptr[i] == 'E')
977*e4b17023SJohn Marino 	    fatal_with_file_and_line ("vector must have at least one element");
978*e4b17023SJohn Marino 	  XVEC (return_rtx, i) = return_vec;
979*e4b17023SJohn Marino 	  obstack_free (&vector_stack, NULL);
980*e4b17023SJohn Marino 	  /* close bracket gotten */
981*e4b17023SJohn Marino 	}
982*e4b17023SJohn Marino 	break;
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino       case 'S':
985*e4b17023SJohn Marino       case 'T':
986*e4b17023SJohn Marino       case 's':
987*e4b17023SJohn Marino 	{
988*e4b17023SJohn Marino 	  char *stringbuf;
989*e4b17023SJohn Marino 	  int star_if_braced;
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino 	  c = read_skip_spaces ();
992*e4b17023SJohn Marino 	  unread_char (c);
993*e4b17023SJohn Marino 	  if (c == ')')
994*e4b17023SJohn Marino 	    {
995*e4b17023SJohn Marino 	      /* 'S' fields are optional and should be NULL if no string
996*e4b17023SJohn Marino 		 was given.  Also allow normal 's' and 'T' strings to be
997*e4b17023SJohn Marino 		 omitted, treating them in the same way as empty strings.  */
998*e4b17023SJohn Marino 	      XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : "");
999*e4b17023SJohn Marino 	      break;
1000*e4b17023SJohn Marino 	    }
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino 	  /* The output template slot of a DEFINE_INSN,
1003*e4b17023SJohn Marino 	     DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically
1004*e4b17023SJohn Marino 	     gets a star inserted as its first character, if it is
1005*e4b17023SJohn Marino 	     written with a brace block instead of a string constant.  */
1006*e4b17023SJohn Marino 	  star_if_braced = (format_ptr[i] == 'T');
1007*e4b17023SJohn Marino 
1008*e4b17023SJohn Marino 	  stringbuf = read_string (star_if_braced);
1009*e4b17023SJohn Marino 
1010*e4b17023SJohn Marino 	  /* For insn patterns, we want to provide a default name
1011*e4b17023SJohn Marino 	     based on the file and line, like "*foo.md:12", if the
1012*e4b17023SJohn Marino 	     given name is blank.  These are only for define_insn and
1013*e4b17023SJohn Marino 	     define_insn_and_split, to aid debugging.  */
1014*e4b17023SJohn Marino 	  if (*stringbuf == '\0'
1015*e4b17023SJohn Marino 	      && i == 0
1016*e4b17023SJohn Marino 	      && (GET_CODE (return_rtx) == DEFINE_INSN
1017*e4b17023SJohn Marino 		  || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
1018*e4b17023SJohn Marino 	    {
1019*e4b17023SJohn Marino 	      char line_name[20];
1020*e4b17023SJohn Marino 	      const char *fn = (read_md_filename ? read_md_filename : "rtx");
1021*e4b17023SJohn Marino 	      const char *slash;
1022*e4b17023SJohn Marino 	      for (slash = fn; *slash; slash ++)
1023*e4b17023SJohn Marino 		if (*slash == '/' || *slash == '\\' || *slash == ':')
1024*e4b17023SJohn Marino 		  fn = slash + 1;
1025*e4b17023SJohn Marino 	      obstack_1grow (&string_obstack, '*');
1026*e4b17023SJohn Marino 	      obstack_grow (&string_obstack, fn, strlen (fn));
1027*e4b17023SJohn Marino 	      sprintf (line_name, ":%d", read_md_lineno);
1028*e4b17023SJohn Marino 	      obstack_grow (&string_obstack, line_name, strlen (line_name)+1);
1029*e4b17023SJohn Marino 	      stringbuf = XOBFINISH (&string_obstack, char *);
1030*e4b17023SJohn Marino 	    }
1031*e4b17023SJohn Marino 
1032*e4b17023SJohn Marino 	  if (star_if_braced)
1033*e4b17023SJohn Marino 	    XTMPL (return_rtx, i) = stringbuf;
1034*e4b17023SJohn Marino 	  else
1035*e4b17023SJohn Marino 	    XSTR (return_rtx, i) = stringbuf;
1036*e4b17023SJohn Marino 	}
1037*e4b17023SJohn Marino 	break;
1038*e4b17023SJohn Marino 
1039*e4b17023SJohn Marino       case 'w':
1040*e4b17023SJohn Marino 	read_name (&name);
1041*e4b17023SJohn Marino 	validate_const_int (name.string);
1042*e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
1043*e4b17023SJohn Marino 	tmp_wide = atoi (name.string);
1044*e4b17023SJohn Marino #else
1045*e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
1046*e4b17023SJohn Marino 	tmp_wide = atol (name.string);
1047*e4b17023SJohn Marino #else
1048*e4b17023SJohn Marino 	/* Prefer atoll over atoq, since the former is in the ISO C99 standard.
1049*e4b17023SJohn Marino 	   But prefer not to use our hand-rolled function above either.  */
1050*e4b17023SJohn Marino #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
1051*e4b17023SJohn Marino 	tmp_wide = atoll (name.string);
1052*e4b17023SJohn Marino #else
1053*e4b17023SJohn Marino 	tmp_wide = atoq (name.string);
1054*e4b17023SJohn Marino #endif
1055*e4b17023SJohn Marino #endif
1056*e4b17023SJohn Marino #endif
1057*e4b17023SJohn Marino 	XWINT (return_rtx, i) = tmp_wide;
1058*e4b17023SJohn Marino 	break;
1059*e4b17023SJohn Marino 
1060*e4b17023SJohn Marino       case 'i':
1061*e4b17023SJohn Marino       case 'n':
1062*e4b17023SJohn Marino 	read_name (&name);
1063*e4b17023SJohn Marino 	validate_const_int (name.string);
1064*e4b17023SJohn Marino 	tmp_int = atoi (name.string);
1065*e4b17023SJohn Marino 	XINT (return_rtx, i) = tmp_int;
1066*e4b17023SJohn Marino 	break;
1067*e4b17023SJohn Marino 
1068*e4b17023SJohn Marino       default:
1069*e4b17023SJohn Marino 	gcc_unreachable ();
1070*e4b17023SJohn Marino       }
1071*e4b17023SJohn Marino 
1072*e4b17023SJohn Marino   c = read_skip_spaces ();
1073*e4b17023SJohn Marino   /* Syntactic sugar for AND and IOR, allowing Lisp-like
1074*e4b17023SJohn Marino      arbitrary number of arguments for them.  */
1075*e4b17023SJohn Marino   if (c == '('
1076*e4b17023SJohn Marino       && (GET_CODE (return_rtx) == AND
1077*e4b17023SJohn Marino 	  || GET_CODE (return_rtx) == IOR))
1078*e4b17023SJohn Marino     return read_rtx_variadic (mode_maps, return_rtx);
1079*e4b17023SJohn Marino 
1080*e4b17023SJohn Marino   unread_char (c);
1081*e4b17023SJohn Marino   return return_rtx;
1082*e4b17023SJohn Marino }
1083*e4b17023SJohn Marino 
1084*e4b17023SJohn Marino /* Read a nested rtx construct from the MD file and return it.
1085*e4b17023SJohn Marino    MODE_MAPS is as for iterator_traverse_data.  */
1086*e4b17023SJohn Marino 
1087*e4b17023SJohn Marino static rtx
read_nested_rtx(struct map_value ** mode_maps)1088*e4b17023SJohn Marino read_nested_rtx (struct map_value **mode_maps)
1089*e4b17023SJohn Marino {
1090*e4b17023SJohn Marino   struct md_name name;
1091*e4b17023SJohn Marino   int c;
1092*e4b17023SJohn Marino   rtx return_rtx;
1093*e4b17023SJohn Marino 
1094*e4b17023SJohn Marino   c = read_skip_spaces ();
1095*e4b17023SJohn Marino   if (c != '(')
1096*e4b17023SJohn Marino     fatal_expected_char ('(', c);
1097*e4b17023SJohn Marino 
1098*e4b17023SJohn Marino   read_name (&name);
1099*e4b17023SJohn Marino   if (strcmp (name.string, "nil") == 0)
1100*e4b17023SJohn Marino     return_rtx = NULL;
1101*e4b17023SJohn Marino   else
1102*e4b17023SJohn Marino     return_rtx = read_rtx_code (name.string, mode_maps);
1103*e4b17023SJohn Marino 
1104*e4b17023SJohn Marino   c = read_skip_spaces ();
1105*e4b17023SJohn Marino   if (c != ')')
1106*e4b17023SJohn Marino     fatal_expected_char (')', c);
1107*e4b17023SJohn Marino 
1108*e4b17023SJohn Marino   return return_rtx;
1109*e4b17023SJohn Marino }
1110*e4b17023SJohn Marino 
1111*e4b17023SJohn Marino /* Mutually recursive subroutine of read_rtx which reads
1112*e4b17023SJohn Marino    (thing x1 x2 x3 ...) and produces RTL as if
1113*e4b17023SJohn Marino    (thing x1 (thing x2 (thing x3 ...)))  had been written.
1114*e4b17023SJohn Marino    When called, FORM is (thing x1 x2), and the file position
1115*e4b17023SJohn Marino    is just past the leading parenthesis of x3.  Only works
1116*e4b17023SJohn Marino    for THINGs which are dyadic expressions, e.g. AND, IOR.  */
1117*e4b17023SJohn Marino static rtx
read_rtx_variadic(struct map_value ** mode_maps,rtx form)1118*e4b17023SJohn Marino read_rtx_variadic (struct map_value **mode_maps, rtx form)
1119*e4b17023SJohn Marino {
1120*e4b17023SJohn Marino   char c = '(';
1121*e4b17023SJohn Marino   rtx p = form, q;
1122*e4b17023SJohn Marino 
1123*e4b17023SJohn Marino   do
1124*e4b17023SJohn Marino     {
1125*e4b17023SJohn Marino       unread_char (c);
1126*e4b17023SJohn Marino 
1127*e4b17023SJohn Marino       q = rtx_alloc (GET_CODE (p));
1128*e4b17023SJohn Marino       PUT_MODE (q, GET_MODE (p));
1129*e4b17023SJohn Marino 
1130*e4b17023SJohn Marino       XEXP (q, 0) = XEXP (p, 1);
1131*e4b17023SJohn Marino       XEXP (q, 1) = read_nested_rtx (mode_maps);
1132*e4b17023SJohn Marino 
1133*e4b17023SJohn Marino       XEXP (p, 1) = q;
1134*e4b17023SJohn Marino       p = q;
1135*e4b17023SJohn Marino       c = read_skip_spaces ();
1136*e4b17023SJohn Marino     }
1137*e4b17023SJohn Marino   while (c == '(');
1138*e4b17023SJohn Marino   unread_char (c);
1139*e4b17023SJohn Marino   return form;
1140*e4b17023SJohn Marino }
1141