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