xref: /openbsd/gnu/gcc/gcc/read-rtl.c (revision 404b540a)
1*404b540aSrobert /* RTL reader for GCC.
2*404b540aSrobert    Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
3*404b540aSrobert    2003, 2004, 2005
4*404b540aSrobert    Free Software Foundation, Inc.
5*404b540aSrobert 
6*404b540aSrobert This file is part of GCC.
7*404b540aSrobert 
8*404b540aSrobert GCC is free software; you can redistribute it and/or modify it under
9*404b540aSrobert the terms of the GNU General Public License as published by the Free
10*404b540aSrobert Software Foundation; either version 2, or (at your option) any later
11*404b540aSrobert version.
12*404b540aSrobert 
13*404b540aSrobert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*404b540aSrobert WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*404b540aSrobert FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*404b540aSrobert for more details.
17*404b540aSrobert 
18*404b540aSrobert You should have received a copy of the GNU General Public License
19*404b540aSrobert along with GCC; see the file COPYING.  If not, write to the Free
20*404b540aSrobert Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21*404b540aSrobert 02110-1301, USA.  */
22*404b540aSrobert 
23*404b540aSrobert #include "bconfig.h"
24*404b540aSrobert 
25*404b540aSrobert /* Disable rtl checking; it conflicts with the macro handling.  */
26*404b540aSrobert #undef ENABLE_RTL_CHECKING
27*404b540aSrobert 
28*404b540aSrobert #include "system.h"
29*404b540aSrobert #include "coretypes.h"
30*404b540aSrobert #include "tm.h"
31*404b540aSrobert #include "rtl.h"
32*404b540aSrobert #include "obstack.h"
33*404b540aSrobert #include "hashtab.h"
34*404b540aSrobert #include "gensupport.h"
35*404b540aSrobert 
36*404b540aSrobert static htab_t md_constants;
37*404b540aSrobert 
38*404b540aSrobert /* One element in a singly-linked list of (integer, string) pairs.  */
39*404b540aSrobert struct map_value {
40*404b540aSrobert   struct map_value *next;
41*404b540aSrobert   int number;
42*404b540aSrobert   const char *string;
43*404b540aSrobert };
44*404b540aSrobert 
45*404b540aSrobert /* Maps a macro or attribute name to a list of (integer, string) pairs.
46*404b540aSrobert    The integers are mode or code values; the strings are either C conditions
47*404b540aSrobert    or attribute values.  */
48*404b540aSrobert struct mapping {
49*404b540aSrobert   /* The name of the macro or attribute.  */
50*404b540aSrobert   const char *name;
51*404b540aSrobert 
52*404b540aSrobert   /* The group (modes or codes) to which the macro or attribute belongs.  */
53*404b540aSrobert   struct macro_group *group;
54*404b540aSrobert 
55*404b540aSrobert   /* Gives a unique number to the attribute or macro.  Numbers are
56*404b540aSrobert      allocated consecutively, starting at 0.  */
57*404b540aSrobert   int index;
58*404b540aSrobert 
59*404b540aSrobert   /* The list of (integer, string) pairs.  */
60*404b540aSrobert   struct map_value *values;
61*404b540aSrobert };
62*404b540aSrobert 
63*404b540aSrobert /* A structure for abstracting the common parts of code and mode macros.  */
64*404b540aSrobert struct macro_group {
65*404b540aSrobert   /* Tables of "mapping" structures, one for attributes and one for macros.  */
66*404b540aSrobert   htab_t attrs, macros;
67*404b540aSrobert 
68*404b540aSrobert   /* The number of "real" modes or codes (and by extension, the first
69*404b540aSrobert      number available for use as a macro placeholder).  */
70*404b540aSrobert   int num_builtins;
71*404b540aSrobert 
72*404b540aSrobert   /* Treat the given string as the name of a standard mode or code and
73*404b540aSrobert      return its integer value.  Use the given file for error reporting.  */
74*404b540aSrobert   int (*find_builtin) (const char *, FILE *);
75*404b540aSrobert 
76*404b540aSrobert   /* Return true if the given rtx uses the given mode or code.  */
77*404b540aSrobert   bool (*uses_macro_p) (rtx, int);
78*404b540aSrobert 
79*404b540aSrobert   /* Make the given rtx use the given mode or code.  */
80*404b540aSrobert   void (*apply_macro) (rtx, int);
81*404b540aSrobert };
82*404b540aSrobert 
83*404b540aSrobert /* Associates PTR (which can be a string, etc.) with the file location
84*404b540aSrobert    specified by FILENAME and LINENO.  */
85*404b540aSrobert struct ptr_loc {
86*404b540aSrobert   const void *ptr;
87*404b540aSrobert   const char *filename;
88*404b540aSrobert   int lineno;
89*404b540aSrobert };
90*404b540aSrobert 
91*404b540aSrobert /* A structure used to pass data from read_rtx to apply_macro_traverse
92*404b540aSrobert    via htab_traverse.  */
93*404b540aSrobert struct macro_traverse_data {
94*404b540aSrobert   /* Instruction queue.  */
95*404b540aSrobert   rtx queue;
96*404b540aSrobert   /* Attributes seen for modes.  */
97*404b540aSrobert   struct map_value *mode_maps;
98*404b540aSrobert   /* Input file.  */
99*404b540aSrobert   FILE *infile;
100*404b540aSrobert   /* The last unknown attribute used as a mode.  */
101*404b540aSrobert   const char *unknown_mode_attr;
102*404b540aSrobert };
103*404b540aSrobert 
104*404b540aSrobert /* If CODE is the number of a code macro, return a real rtx code that
105*404b540aSrobert    has the same format.  Return CODE otherwise.  */
106*404b540aSrobert #define BELLWETHER_CODE(CODE) \
107*404b540aSrobert   ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE])
108*404b540aSrobert 
109*404b540aSrobert static void fatal_with_file_and_line (FILE *, const char *, ...)
110*404b540aSrobert   ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
111*404b540aSrobert static void fatal_expected_char (FILE *, int, int) ATTRIBUTE_NORETURN;
112*404b540aSrobert static int find_mode (const char *, FILE *);
113*404b540aSrobert static bool uses_mode_macro_p (rtx, int);
114*404b540aSrobert static void apply_mode_macro (rtx, int);
115*404b540aSrobert static int find_code (const char *, FILE *);
116*404b540aSrobert static bool uses_code_macro_p (rtx, int);
117*404b540aSrobert static void apply_code_macro (rtx, int);
118*404b540aSrobert static const char *apply_macro_to_string (const char *, struct mapping *, int);
119*404b540aSrobert static rtx apply_macro_to_rtx (rtx, struct mapping *, int,
120*404b540aSrobert 			       struct map_value *, FILE *, const char **);
121*404b540aSrobert static bool uses_macro_p (rtx, struct mapping *);
122*404b540aSrobert static const char *add_condition_to_string (const char *, const char *);
123*404b540aSrobert static void add_condition_to_rtx (rtx, const char *);
124*404b540aSrobert static int apply_macro_traverse (void **, void *);
125*404b540aSrobert static struct mapping *add_mapping (struct macro_group *, htab_t t,
126*404b540aSrobert 				    const char *, FILE *);
127*404b540aSrobert static struct map_value **add_map_value (struct map_value **,
128*404b540aSrobert 					 int, const char *);
129*404b540aSrobert static void initialize_macros (void);
130*404b540aSrobert static void read_name (char *, FILE *);
131*404b540aSrobert static hashval_t leading_ptr_hash (const void *);
132*404b540aSrobert static int leading_ptr_eq_p (const void *, const void *);
133*404b540aSrobert static void set_rtx_ptr_loc (const void *, const char *, int);
134*404b540aSrobert static const struct ptr_loc *get_rtx_ptr_loc (const void *);
135*404b540aSrobert static char *read_string (FILE *, int);
136*404b540aSrobert static char *read_quoted_string (FILE *);
137*404b540aSrobert static char *read_braced_string (FILE *);
138*404b540aSrobert static void read_escape (FILE *);
139*404b540aSrobert static hashval_t def_hash (const void *);
140*404b540aSrobert static int def_name_eq_p (const void *, const void *);
141*404b540aSrobert static void read_constants (FILE *infile, char *tmp_char);
142*404b540aSrobert static void read_conditions (FILE *infile, char *tmp_char);
143*404b540aSrobert static void validate_const_int (FILE *, const char *);
144*404b540aSrobert static int find_macro (struct macro_group *, const char *, FILE *);
145*404b540aSrobert static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
146*404b540aSrobert static void check_code_macro (struct mapping *, FILE *);
147*404b540aSrobert static rtx read_rtx_1 (FILE *, struct map_value **);
148*404b540aSrobert static rtx read_rtx_variadic (FILE *, struct map_value **, rtx);
149*404b540aSrobert 
150*404b540aSrobert /* The mode and code macro structures.  */
151*404b540aSrobert static struct macro_group modes, codes;
152*404b540aSrobert 
153*404b540aSrobert /* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE).  */
154*404b540aSrobert static enum rtx_code *bellwether_codes;
155*404b540aSrobert 
156*404b540aSrobert /* Obstack used for allocating RTL strings.  */
157*404b540aSrobert static struct obstack string_obstack;
158*404b540aSrobert 
159*404b540aSrobert /* A table of ptr_locs, hashed on the PTR field.  */
160*404b540aSrobert static htab_t ptr_locs;
161*404b540aSrobert 
162*404b540aSrobert /* An obstack for the above.  Plain xmalloc is a bit heavyweight for a
163*404b540aSrobert    small structure like ptr_loc.  */
164*404b540aSrobert static struct obstack ptr_loc_obstack;
165*404b540aSrobert 
166*404b540aSrobert /* A hash table of triples (A, B, C), where each of A, B and C is a condition
167*404b540aSrobert    and A is equivalent to "B && C".  This is used to keep track of the source
168*404b540aSrobert    of conditions that are made up of separate rtx strings (such as the split
169*404b540aSrobert    condition of a define_insn_and_split).  */
170*404b540aSrobert static htab_t joined_conditions;
171*404b540aSrobert 
172*404b540aSrobert /* An obstack for allocating joined_conditions entries.  */
173*404b540aSrobert static struct obstack joined_conditions_obstack;
174*404b540aSrobert 
175*404b540aSrobert /* Subroutines of read_rtx.  */
176*404b540aSrobert 
177*404b540aSrobert /* The current line number for the file.  */
178*404b540aSrobert int read_rtx_lineno = 1;
179*404b540aSrobert 
180*404b540aSrobert /* The filename for error reporting.  */
181*404b540aSrobert const char *read_rtx_filename = "<unknown>";
182*404b540aSrobert 
183*404b540aSrobert static void
fatal_with_file_and_line(FILE * infile,const char * msg,...)184*404b540aSrobert fatal_with_file_and_line (FILE *infile, const char *msg, ...)
185*404b540aSrobert {
186*404b540aSrobert   char context[64];
187*404b540aSrobert   size_t i;
188*404b540aSrobert   int c;
189*404b540aSrobert   va_list ap;
190*404b540aSrobert 
191*404b540aSrobert   va_start (ap, msg);
192*404b540aSrobert 
193*404b540aSrobert   fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
194*404b540aSrobert   vfprintf (stderr, msg, ap);
195*404b540aSrobert   putc ('\n', stderr);
196*404b540aSrobert 
197*404b540aSrobert   /* Gather some following context.  */
198*404b540aSrobert   for (i = 0; i < sizeof (context)-1; ++i)
199*404b540aSrobert     {
200*404b540aSrobert       c = getc (infile);
201*404b540aSrobert       if (c == EOF)
202*404b540aSrobert 	break;
203*404b540aSrobert       if (c == '\r' || c == '\n')
204*404b540aSrobert 	break;
205*404b540aSrobert       context[i] = c;
206*404b540aSrobert     }
207*404b540aSrobert   context[i] = '\0';
208*404b540aSrobert 
209*404b540aSrobert   fprintf (stderr, "%s:%d: following context is `%s'\n",
210*404b540aSrobert 	   read_rtx_filename, read_rtx_lineno, context);
211*404b540aSrobert 
212*404b540aSrobert   va_end (ap);
213*404b540aSrobert   exit (1);
214*404b540aSrobert }
215*404b540aSrobert 
216*404b540aSrobert /* Dump code after printing a message.  Used when read_rtx finds
217*404b540aSrobert    invalid data.  */
218*404b540aSrobert 
219*404b540aSrobert static void
fatal_expected_char(FILE * infile,int expected_c,int actual_c)220*404b540aSrobert fatal_expected_char (FILE *infile, int expected_c, int actual_c)
221*404b540aSrobert {
222*404b540aSrobert   fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
223*404b540aSrobert 			    expected_c, actual_c);
224*404b540aSrobert }
225*404b540aSrobert 
226*404b540aSrobert /* Implementations of the macro_group callbacks for modes.  */
227*404b540aSrobert 
228*404b540aSrobert static int
find_mode(const char * name,FILE * infile)229*404b540aSrobert find_mode (const char *name, FILE *infile)
230*404b540aSrobert {
231*404b540aSrobert   int i;
232*404b540aSrobert 
233*404b540aSrobert   for (i = 0; i < NUM_MACHINE_MODES; i++)
234*404b540aSrobert     if (strcmp (GET_MODE_NAME (i), name) == 0)
235*404b540aSrobert       return i;
236*404b540aSrobert 
237*404b540aSrobert   fatal_with_file_and_line (infile, "unknown mode `%s'", name);
238*404b540aSrobert }
239*404b540aSrobert 
240*404b540aSrobert static bool
uses_mode_macro_p(rtx x,int mode)241*404b540aSrobert uses_mode_macro_p (rtx x, int mode)
242*404b540aSrobert {
243*404b540aSrobert   return (int) GET_MODE (x) == mode;
244*404b540aSrobert }
245*404b540aSrobert 
246*404b540aSrobert static void
apply_mode_macro(rtx x,int mode)247*404b540aSrobert apply_mode_macro (rtx x, int mode)
248*404b540aSrobert {
249*404b540aSrobert   PUT_MODE (x, (enum machine_mode) mode);
250*404b540aSrobert }
251*404b540aSrobert 
252*404b540aSrobert /* Implementations of the macro_group callbacks for codes.  */
253*404b540aSrobert 
254*404b540aSrobert static int
find_code(const char * name,FILE * infile)255*404b540aSrobert find_code (const char *name, FILE *infile)
256*404b540aSrobert {
257*404b540aSrobert   int i;
258*404b540aSrobert 
259*404b540aSrobert   for (i = 0; i < NUM_RTX_CODE; i++)
260*404b540aSrobert     if (strcmp (GET_RTX_NAME (i), name) == 0)
261*404b540aSrobert       return i;
262*404b540aSrobert 
263*404b540aSrobert   fatal_with_file_and_line (infile, "unknown rtx code `%s'", name);
264*404b540aSrobert }
265*404b540aSrobert 
266*404b540aSrobert static bool
uses_code_macro_p(rtx x,int code)267*404b540aSrobert uses_code_macro_p (rtx x, int code)
268*404b540aSrobert {
269*404b540aSrobert   return (int) GET_CODE (x) == code;
270*404b540aSrobert }
271*404b540aSrobert 
272*404b540aSrobert static void
apply_code_macro(rtx x,int code)273*404b540aSrobert apply_code_macro (rtx x, int code)
274*404b540aSrobert {
275*404b540aSrobert   PUT_CODE (x, (enum rtx_code) code);
276*404b540aSrobert }
277*404b540aSrobert 
278*404b540aSrobert /* Map a code or mode attribute string P to the underlying string for
279*404b540aSrobert    MACRO and VALUE.  */
280*404b540aSrobert 
281*404b540aSrobert static struct map_value *
map_attr_string(const char * p,struct mapping * macro,int value)282*404b540aSrobert map_attr_string (const char *p, struct mapping *macro, int value)
283*404b540aSrobert {
284*404b540aSrobert   const char *attr;
285*404b540aSrobert   struct mapping *m;
286*404b540aSrobert   struct map_value *v;
287*404b540aSrobert 
288*404b540aSrobert   /* If there's a "macro:" prefix, check whether the macro name matches.
289*404b540aSrobert      Set ATTR to the start of the attribute name.  */
290*404b540aSrobert   attr = strchr (p, ':');
291*404b540aSrobert   if (attr == 0)
292*404b540aSrobert     attr = p;
293*404b540aSrobert   else
294*404b540aSrobert     {
295*404b540aSrobert       if (strncmp (p, macro->name, attr - p) != 0
296*404b540aSrobert 	  || macro->name[attr - p] != 0)
297*404b540aSrobert 	return 0;
298*404b540aSrobert       attr++;
299*404b540aSrobert     }
300*404b540aSrobert 
301*404b540aSrobert   /* Find the attribute specification.  */
302*404b540aSrobert   m = (struct mapping *) htab_find (macro->group->attrs, &attr);
303*404b540aSrobert   if (m == 0)
304*404b540aSrobert     return 0;
305*404b540aSrobert 
306*404b540aSrobert   /* Find the attribute value for VALUE.  */
307*404b540aSrobert   for (v = m->values; v != 0; v = v->next)
308*404b540aSrobert     if (v->number == value)
309*404b540aSrobert       break;
310*404b540aSrobert 
311*404b540aSrobert   return v;
312*404b540aSrobert }
313*404b540aSrobert 
314*404b540aSrobert /* Given an attribute string used as a machine mode, return an index
315*404b540aSrobert    to store in the machine mode to be translated by
316*404b540aSrobert    apply_macro_to_rtx.  */
317*404b540aSrobert 
318*404b540aSrobert static unsigned int
mode_attr_index(struct map_value ** mode_maps,const char * string)319*404b540aSrobert mode_attr_index (struct map_value **mode_maps, const char *string)
320*404b540aSrobert {
321*404b540aSrobert   char *p;
322*404b540aSrobert   struct map_value *mv;
323*404b540aSrobert 
324*404b540aSrobert   /* Copy the attribute string into permanent storage, without the
325*404b540aSrobert      angle brackets around it.  */
326*404b540aSrobert   obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2);
327*404b540aSrobert   p = XOBFINISH (&string_obstack, char *);
328*404b540aSrobert 
329*404b540aSrobert   mv = XNEW (struct map_value);
330*404b540aSrobert   mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
331*404b540aSrobert   mv->string = p;
332*404b540aSrobert   mv->next = *mode_maps;
333*404b540aSrobert   *mode_maps = mv;
334*404b540aSrobert 
335*404b540aSrobert   /* We return a code which we can map back into this string: the
336*404b540aSrobert      number of machine modes + the number of mode macros + the index
337*404b540aSrobert      we just used.  */
338*404b540aSrobert   return MAX_MACHINE_MODE + htab_elements (modes.macros) + mv->number;
339*404b540aSrobert }
340*404b540aSrobert 
341*404b540aSrobert /* Apply MODE_MAPS to the top level of X, expanding cases where an
342*404b540aSrobert    attribute is used for a mode.  MACRO is the current macro we are
343*404b540aSrobert    expanding, and VALUE is the value to which we are expanding it.
344*404b540aSrobert    INFILE is used for error messages.  This sets *UNKNOWN to true if
345*404b540aSrobert    we find a mode attribute which has not yet been defined, and does
346*404b540aSrobert    not change it otherwise.  */
347*404b540aSrobert 
348*404b540aSrobert static void
apply_mode_maps(rtx x,struct map_value * mode_maps,struct mapping * macro,int value,FILE * infile,const char ** unknown)349*404b540aSrobert apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *macro,
350*404b540aSrobert 		 int value, FILE *infile, const char **unknown)
351*404b540aSrobert {
352*404b540aSrobert   unsigned int offset;
353*404b540aSrobert   int indx;
354*404b540aSrobert   struct map_value *pm;
355*404b540aSrobert 
356*404b540aSrobert   offset = MAX_MACHINE_MODE + htab_elements (modes.macros);
357*404b540aSrobert   if (GET_MODE (x) < offset)
358*404b540aSrobert     return;
359*404b540aSrobert 
360*404b540aSrobert   indx = GET_MODE (x) - offset;
361*404b540aSrobert   for (pm = mode_maps; pm; pm = pm->next)
362*404b540aSrobert     {
363*404b540aSrobert       if (pm->number == indx)
364*404b540aSrobert 	{
365*404b540aSrobert 	  struct map_value *v;
366*404b540aSrobert 
367*404b540aSrobert 	  v = map_attr_string (pm->string, macro, value);
368*404b540aSrobert 	  if (v)
369*404b540aSrobert 	    PUT_MODE (x, (enum machine_mode) find_mode (v->string, infile));
370*404b540aSrobert 	  else
371*404b540aSrobert 	    *unknown = pm->string;
372*404b540aSrobert 	  return;
373*404b540aSrobert 	}
374*404b540aSrobert     }
375*404b540aSrobert }
376*404b540aSrobert 
377*404b540aSrobert /* Given that MACRO is being expanded as VALUE, apply the appropriate
378*404b540aSrobert    string substitutions to STRING.  Return the new string if any changes
379*404b540aSrobert    were needed, otherwise return STRING itself.  */
380*404b540aSrobert 
381*404b540aSrobert static const char *
apply_macro_to_string(const char * string,struct mapping * macro,int value)382*404b540aSrobert apply_macro_to_string (const char *string, struct mapping *macro, int value)
383*404b540aSrobert {
384*404b540aSrobert   char *base, *copy, *p, *start, *end;
385*404b540aSrobert   struct map_value *v;
386*404b540aSrobert 
387*404b540aSrobert   if (string == 0)
388*404b540aSrobert     return string;
389*404b540aSrobert 
390*404b540aSrobert   base = p = copy = ASTRDUP (string);
391*404b540aSrobert   while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
392*404b540aSrobert     {
393*404b540aSrobert       p = start + 1;
394*404b540aSrobert 
395*404b540aSrobert       *end = 0;
396*404b540aSrobert       v = map_attr_string (p, macro, value);
397*404b540aSrobert       *end = '>';
398*404b540aSrobert       if (v == 0)
399*404b540aSrobert 	continue;
400*404b540aSrobert 
401*404b540aSrobert       /* Add everything between the last copied byte and the '<',
402*404b540aSrobert 	 then add in the attribute value.  */
403*404b540aSrobert       obstack_grow (&string_obstack, base, start - base);
404*404b540aSrobert       obstack_grow (&string_obstack, v->string, strlen (v->string));
405*404b540aSrobert       base = end + 1;
406*404b540aSrobert     }
407*404b540aSrobert   if (base != copy)
408*404b540aSrobert     {
409*404b540aSrobert       obstack_grow (&string_obstack, base, strlen (base) + 1);
410*404b540aSrobert       copy = XOBFINISH (&string_obstack, char *);
411*404b540aSrobert       copy_rtx_ptr_loc (copy, string);
412*404b540aSrobert       return copy;
413*404b540aSrobert     }
414*404b540aSrobert   return string;
415*404b540aSrobert }
416*404b540aSrobert 
417*404b540aSrobert /* Return a copy of ORIGINAL in which all uses of MACRO have been
418*404b540aSrobert    replaced by VALUE.  MODE_MAPS holds information about attribute
419*404b540aSrobert    strings used for modes.  INFILE is used for error messages.  This
420*404b540aSrobert    sets *UNKNOWN_MODE_ATTR to the value of an unknown mode attribute,
421*404b540aSrobert    and does not change it otherwise.  */
422*404b540aSrobert 
423*404b540aSrobert static rtx
apply_macro_to_rtx(rtx original,struct mapping * macro,int value,struct map_value * mode_maps,FILE * infile,const char ** unknown_mode_attr)424*404b540aSrobert apply_macro_to_rtx (rtx original, struct mapping *macro, int value,
425*404b540aSrobert 		    struct map_value *mode_maps, FILE *infile,
426*404b540aSrobert 		    const char **unknown_mode_attr)
427*404b540aSrobert {
428*404b540aSrobert   struct macro_group *group;
429*404b540aSrobert   const char *format_ptr;
430*404b540aSrobert   int i, j;
431*404b540aSrobert   rtx x;
432*404b540aSrobert   enum rtx_code bellwether_code;
433*404b540aSrobert 
434*404b540aSrobert   if (original == 0)
435*404b540aSrobert     return original;
436*404b540aSrobert 
437*404b540aSrobert   /* Create a shallow copy of ORIGINAL.  */
438*404b540aSrobert   bellwether_code = BELLWETHER_CODE (GET_CODE (original));
439*404b540aSrobert   x = rtx_alloc (bellwether_code);
440*404b540aSrobert   memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
441*404b540aSrobert 
442*404b540aSrobert   /* Change the mode or code itself.  */
443*404b540aSrobert   group = macro->group;
444*404b540aSrobert   if (group->uses_macro_p (x, macro->index + group->num_builtins))
445*404b540aSrobert     group->apply_macro (x, value);
446*404b540aSrobert 
447*404b540aSrobert   if (mode_maps)
448*404b540aSrobert     apply_mode_maps (x, mode_maps, macro, value, infile, unknown_mode_attr);
449*404b540aSrobert 
450*404b540aSrobert   /* Change each string and recursively change each rtx.  */
451*404b540aSrobert   format_ptr = GET_RTX_FORMAT (bellwether_code);
452*404b540aSrobert   for (i = 0; format_ptr[i] != 0; i++)
453*404b540aSrobert     switch (format_ptr[i])
454*404b540aSrobert       {
455*404b540aSrobert       case 'T':
456*404b540aSrobert 	XTMPL (x, i) = apply_macro_to_string (XTMPL (x, i), macro, value);
457*404b540aSrobert 	break;
458*404b540aSrobert 
459*404b540aSrobert       case 'S':
460*404b540aSrobert       case 's':
461*404b540aSrobert 	XSTR (x, i) = apply_macro_to_string (XSTR (x, i), macro, value);
462*404b540aSrobert 	break;
463*404b540aSrobert 
464*404b540aSrobert       case 'e':
465*404b540aSrobert 	XEXP (x, i) = apply_macro_to_rtx (XEXP (x, i), macro, value,
466*404b540aSrobert 					  mode_maps, infile,
467*404b540aSrobert 					  unknown_mode_attr);
468*404b540aSrobert 	break;
469*404b540aSrobert 
470*404b540aSrobert       case 'V':
471*404b540aSrobert       case 'E':
472*404b540aSrobert 	if (XVEC (original, i))
473*404b540aSrobert 	  {
474*404b540aSrobert 	    XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
475*404b540aSrobert 	    for (j = 0; j < XVECLEN (x, i); j++)
476*404b540aSrobert 	      XVECEXP (x, i, j) = apply_macro_to_rtx (XVECEXP (original, i, j),
477*404b540aSrobert 						      macro, value, mode_maps,
478*404b540aSrobert 						      infile,
479*404b540aSrobert 						      unknown_mode_attr);
480*404b540aSrobert 	  }
481*404b540aSrobert 	break;
482*404b540aSrobert 
483*404b540aSrobert       default:
484*404b540aSrobert 	break;
485*404b540aSrobert       }
486*404b540aSrobert   return x;
487*404b540aSrobert }
488*404b540aSrobert 
489*404b540aSrobert /* Return true if X (or some subexpression of X) uses macro MACRO.  */
490*404b540aSrobert 
491*404b540aSrobert static bool
uses_macro_p(rtx x,struct mapping * macro)492*404b540aSrobert uses_macro_p (rtx x, struct mapping *macro)
493*404b540aSrobert {
494*404b540aSrobert   struct macro_group *group;
495*404b540aSrobert   const char *format_ptr;
496*404b540aSrobert   int i, j;
497*404b540aSrobert 
498*404b540aSrobert   if (x == 0)
499*404b540aSrobert     return false;
500*404b540aSrobert 
501*404b540aSrobert   group = macro->group;
502*404b540aSrobert   if (group->uses_macro_p (x, macro->index + group->num_builtins))
503*404b540aSrobert     return true;
504*404b540aSrobert 
505*404b540aSrobert   format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x)));
506*404b540aSrobert   for (i = 0; format_ptr[i] != 0; i++)
507*404b540aSrobert     switch (format_ptr[i])
508*404b540aSrobert       {
509*404b540aSrobert       case 'e':
510*404b540aSrobert 	if (uses_macro_p (XEXP (x, i), macro))
511*404b540aSrobert 	  return true;
512*404b540aSrobert 	break;
513*404b540aSrobert 
514*404b540aSrobert       case 'V':
515*404b540aSrobert       case 'E':
516*404b540aSrobert 	if (XVEC (x, i))
517*404b540aSrobert 	  for (j = 0; j < XVECLEN (x, i); j++)
518*404b540aSrobert 	    if (uses_macro_p (XVECEXP (x, i, j), macro))
519*404b540aSrobert 	      return true;
520*404b540aSrobert 	break;
521*404b540aSrobert 
522*404b540aSrobert       default:
523*404b540aSrobert 	break;
524*404b540aSrobert       }
525*404b540aSrobert   return false;
526*404b540aSrobert }
527*404b540aSrobert 
528*404b540aSrobert /* Return a condition that must satisfy both ORIGINAL and EXTRA.  If ORIGINAL
529*404b540aSrobert    has the form "&& ..." (as used in define_insn_and_splits), assume that
530*404b540aSrobert    EXTRA is already satisfied.  Empty strings are treated like "true".  */
531*404b540aSrobert 
532*404b540aSrobert static const char *
add_condition_to_string(const char * original,const char * extra)533*404b540aSrobert add_condition_to_string (const char *original, const char *extra)
534*404b540aSrobert {
535*404b540aSrobert   if (original != 0 && original[0] == '&' && original[1] == '&')
536*404b540aSrobert     return original;
537*404b540aSrobert   return join_c_conditions (original, extra);
538*404b540aSrobert }
539*404b540aSrobert 
540*404b540aSrobert /* Like add_condition, but applied to all conditions in rtx X.  */
541*404b540aSrobert 
542*404b540aSrobert static void
add_condition_to_rtx(rtx x,const char * extra)543*404b540aSrobert add_condition_to_rtx (rtx x, const char *extra)
544*404b540aSrobert {
545*404b540aSrobert   switch (GET_CODE (x))
546*404b540aSrobert     {
547*404b540aSrobert     case DEFINE_INSN:
548*404b540aSrobert     case DEFINE_EXPAND:
549*404b540aSrobert       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
550*404b540aSrobert       break;
551*404b540aSrobert 
552*404b540aSrobert     case DEFINE_SPLIT:
553*404b540aSrobert     case DEFINE_PEEPHOLE:
554*404b540aSrobert     case DEFINE_PEEPHOLE2:
555*404b540aSrobert     case DEFINE_COND_EXEC:
556*404b540aSrobert       XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
557*404b540aSrobert       break;
558*404b540aSrobert 
559*404b540aSrobert     case DEFINE_INSN_AND_SPLIT:
560*404b540aSrobert       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
561*404b540aSrobert       XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
562*404b540aSrobert       break;
563*404b540aSrobert 
564*404b540aSrobert     default:
565*404b540aSrobert       break;
566*404b540aSrobert     }
567*404b540aSrobert }
568*404b540aSrobert 
569*404b540aSrobert /* A htab_traverse callback.  Search the EXPR_LIST given by DATA
570*404b540aSrobert    for rtxes that use the macro in *SLOT.  Replace each such rtx
571*404b540aSrobert    with a list of expansions.  */
572*404b540aSrobert 
573*404b540aSrobert static int
apply_macro_traverse(void ** slot,void * data)574*404b540aSrobert apply_macro_traverse (void **slot, void *data)
575*404b540aSrobert {
576*404b540aSrobert   struct macro_traverse_data *mtd = (struct macro_traverse_data *) data;
577*404b540aSrobert   struct mapping *macro;
578*404b540aSrobert   struct map_value *v;
579*404b540aSrobert   rtx elem, new_elem, original, x;
580*404b540aSrobert 
581*404b540aSrobert   macro = (struct mapping *) *slot;
582*404b540aSrobert   for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
583*404b540aSrobert     if (uses_macro_p (XEXP (elem, 0), macro))
584*404b540aSrobert       {
585*404b540aSrobert 	/* For each macro we expand, we set UNKNOWN_MODE_ATTR to NULL.
586*404b540aSrobert 	   If apply_macro_rtx finds an unknown attribute for a mode,
587*404b540aSrobert 	   it will set it to the attribute.  We want to know whether
588*404b540aSrobert 	   the attribute is unknown after we have expanded all
589*404b540aSrobert 	   possible macros, so setting it to NULL here gives us the
590*404b540aSrobert 	   right result when the hash table traversal is complete.  */
591*404b540aSrobert 	mtd->unknown_mode_attr = NULL;
592*404b540aSrobert 
593*404b540aSrobert 	original = XEXP (elem, 0);
594*404b540aSrobert 	for (v = macro->values; v != 0; v = v->next)
595*404b540aSrobert 	  {
596*404b540aSrobert 	    x = apply_macro_to_rtx (original, macro, v->number,
597*404b540aSrobert 				    mtd->mode_maps, mtd->infile,
598*404b540aSrobert 				    &mtd->unknown_mode_attr);
599*404b540aSrobert 	    add_condition_to_rtx (x, v->string);
600*404b540aSrobert 	    if (v != macro->values)
601*404b540aSrobert 	      {
602*404b540aSrobert 		/* Insert a new EXPR_LIST node after ELEM and put the
603*404b540aSrobert 		   new expansion there.  */
604*404b540aSrobert 		new_elem = rtx_alloc (EXPR_LIST);
605*404b540aSrobert 		XEXP (new_elem, 1) = XEXP (elem, 1);
606*404b540aSrobert 		XEXP (elem, 1) = new_elem;
607*404b540aSrobert 		elem = new_elem;
608*404b540aSrobert 	      }
609*404b540aSrobert 	    XEXP (elem, 0) = x;
610*404b540aSrobert 	  }
611*404b540aSrobert     }
612*404b540aSrobert   return 1;
613*404b540aSrobert }
614*404b540aSrobert 
615*404b540aSrobert /* Add a new "mapping" structure to hashtable TABLE.  NAME is the name
616*404b540aSrobert    of the mapping, GROUP is the group to which it belongs, and INFILE
617*404b540aSrobert    is the file that defined the mapping.  */
618*404b540aSrobert 
619*404b540aSrobert static struct mapping *
add_mapping(struct macro_group * group,htab_t table,const char * name,FILE * infile)620*404b540aSrobert add_mapping (struct macro_group *group, htab_t table,
621*404b540aSrobert 	     const char *name, FILE *infile)
622*404b540aSrobert {
623*404b540aSrobert   struct mapping *m;
624*404b540aSrobert   void **slot;
625*404b540aSrobert 
626*404b540aSrobert   m = XNEW (struct mapping);
627*404b540aSrobert   m->name = xstrdup (name);
628*404b540aSrobert   m->group = group;
629*404b540aSrobert   m->index = htab_elements (table);
630*404b540aSrobert   m->values = 0;
631*404b540aSrobert 
632*404b540aSrobert   slot = htab_find_slot (table, m, INSERT);
633*404b540aSrobert   if (*slot != 0)
634*404b540aSrobert     fatal_with_file_and_line (infile, "`%s' already defined", name);
635*404b540aSrobert 
636*404b540aSrobert   *slot = m;
637*404b540aSrobert   return m;
638*404b540aSrobert }
639*404b540aSrobert 
640*404b540aSrobert /* Add the pair (NUMBER, STRING) to a list of map_value structures.
641*404b540aSrobert    END_PTR points to the current null terminator for the list; return
642*404b540aSrobert    a pointer the new null terminator.  */
643*404b540aSrobert 
644*404b540aSrobert static struct map_value **
add_map_value(struct map_value ** end_ptr,int number,const char * string)645*404b540aSrobert add_map_value (struct map_value **end_ptr, int number, const char *string)
646*404b540aSrobert {
647*404b540aSrobert   struct map_value *value;
648*404b540aSrobert 
649*404b540aSrobert   value = XNEW (struct map_value);
650*404b540aSrobert   value->next = 0;
651*404b540aSrobert   value->number = number;
652*404b540aSrobert   value->string = string;
653*404b540aSrobert 
654*404b540aSrobert   *end_ptr = value;
655*404b540aSrobert   return &value->next;
656*404b540aSrobert }
657*404b540aSrobert 
658*404b540aSrobert /* Do one-time initialization of the mode and code attributes.  */
659*404b540aSrobert 
660*404b540aSrobert static void
initialize_macros(void)661*404b540aSrobert initialize_macros (void)
662*404b540aSrobert {
663*404b540aSrobert   struct mapping *lower, *upper;
664*404b540aSrobert   struct map_value **lower_ptr, **upper_ptr;
665*404b540aSrobert   char *copy, *p;
666*404b540aSrobert   int i;
667*404b540aSrobert 
668*404b540aSrobert   modes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
669*404b540aSrobert   modes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
670*404b540aSrobert   modes.num_builtins = MAX_MACHINE_MODE;
671*404b540aSrobert   modes.find_builtin = find_mode;
672*404b540aSrobert   modes.uses_macro_p = uses_mode_macro_p;
673*404b540aSrobert   modes.apply_macro = apply_mode_macro;
674*404b540aSrobert 
675*404b540aSrobert   codes.attrs = htab_create (13, def_hash, def_name_eq_p, 0);
676*404b540aSrobert   codes.macros = htab_create (13, def_hash, def_name_eq_p, 0);
677*404b540aSrobert   codes.num_builtins = NUM_RTX_CODE;
678*404b540aSrobert   codes.find_builtin = find_code;
679*404b540aSrobert   codes.uses_macro_p = uses_code_macro_p;
680*404b540aSrobert   codes.apply_macro = apply_code_macro;
681*404b540aSrobert 
682*404b540aSrobert   lower = add_mapping (&modes, modes.attrs, "mode", 0);
683*404b540aSrobert   upper = add_mapping (&modes, modes.attrs, "MODE", 0);
684*404b540aSrobert   lower_ptr = &lower->values;
685*404b540aSrobert   upper_ptr = &upper->values;
686*404b540aSrobert   for (i = 0; i < MAX_MACHINE_MODE; i++)
687*404b540aSrobert     {
688*404b540aSrobert       copy = xstrdup (GET_MODE_NAME (i));
689*404b540aSrobert       for (p = copy; *p != 0; p++)
690*404b540aSrobert 	*p = TOLOWER (*p);
691*404b540aSrobert 
692*404b540aSrobert       upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
693*404b540aSrobert       lower_ptr = add_map_value (lower_ptr, i, copy);
694*404b540aSrobert     }
695*404b540aSrobert 
696*404b540aSrobert   lower = add_mapping (&codes, codes.attrs, "code", 0);
697*404b540aSrobert   upper = add_mapping (&codes, codes.attrs, "CODE", 0);
698*404b540aSrobert   lower_ptr = &lower->values;
699*404b540aSrobert   upper_ptr = &upper->values;
700*404b540aSrobert   for (i = 0; i < NUM_RTX_CODE; i++)
701*404b540aSrobert     {
702*404b540aSrobert       copy = xstrdup (GET_RTX_NAME (i));
703*404b540aSrobert       for (p = copy; *p != 0; p++)
704*404b540aSrobert 	*p = TOUPPER (*p);
705*404b540aSrobert 
706*404b540aSrobert       lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
707*404b540aSrobert       upper_ptr = add_map_value (upper_ptr, i, copy);
708*404b540aSrobert     }
709*404b540aSrobert }
710*404b540aSrobert 
711*404b540aSrobert /* Return a hash value for the pointer pointed to by DEF.  */
712*404b540aSrobert 
713*404b540aSrobert static hashval_t
leading_ptr_hash(const void * def)714*404b540aSrobert leading_ptr_hash (const void *def)
715*404b540aSrobert {
716*404b540aSrobert   return htab_hash_pointer (*(const void *const *) def);
717*404b540aSrobert }
718*404b540aSrobert 
719*404b540aSrobert /* Return true if DEF1 and DEF2 are pointers to the same pointer.  */
720*404b540aSrobert 
721*404b540aSrobert static int
leading_ptr_eq_p(const void * def1,const void * def2)722*404b540aSrobert leading_ptr_eq_p (const void *def1, const void *def2)
723*404b540aSrobert {
724*404b540aSrobert   return *(const void *const *) def1 == *(const void *const *) def2;
725*404b540aSrobert }
726*404b540aSrobert 
727*404b540aSrobert /* Associate PTR with the file position given by FILENAME and LINENO.  */
728*404b540aSrobert 
729*404b540aSrobert static void
set_rtx_ptr_loc(const void * ptr,const char * filename,int lineno)730*404b540aSrobert set_rtx_ptr_loc (const void *ptr, const char *filename, int lineno)
731*404b540aSrobert {
732*404b540aSrobert   struct ptr_loc *loc;
733*404b540aSrobert 
734*404b540aSrobert   loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack,
735*404b540aSrobert 					  sizeof (struct ptr_loc));
736*404b540aSrobert   loc->ptr = ptr;
737*404b540aSrobert   loc->filename = filename;
738*404b540aSrobert   loc->lineno = lineno;
739*404b540aSrobert   *htab_find_slot (ptr_locs, loc, INSERT) = loc;
740*404b540aSrobert }
741*404b540aSrobert 
742*404b540aSrobert /* Return the position associated with pointer PTR.  Return null if no
743*404b540aSrobert    position was set.  */
744*404b540aSrobert 
745*404b540aSrobert static const struct ptr_loc *
get_rtx_ptr_loc(const void * ptr)746*404b540aSrobert get_rtx_ptr_loc (const void *ptr)
747*404b540aSrobert {
748*404b540aSrobert   return (const struct ptr_loc *) htab_find (ptr_locs, &ptr);
749*404b540aSrobert }
750*404b540aSrobert 
751*404b540aSrobert /* Associate NEW_PTR with the same file position as OLD_PTR.  */
752*404b540aSrobert 
753*404b540aSrobert void
copy_rtx_ptr_loc(const void * new_ptr,const void * old_ptr)754*404b540aSrobert copy_rtx_ptr_loc (const void *new_ptr, const void *old_ptr)
755*404b540aSrobert {
756*404b540aSrobert   const struct ptr_loc *loc = get_rtx_ptr_loc (old_ptr);
757*404b540aSrobert   if (loc != 0)
758*404b540aSrobert     set_rtx_ptr_loc (new_ptr, loc->filename, loc->lineno);
759*404b540aSrobert }
760*404b540aSrobert 
761*404b540aSrobert /* If PTR is associated with a known file position, print a #line
762*404b540aSrobert    directive for it.  */
763*404b540aSrobert 
764*404b540aSrobert void
print_rtx_ptr_loc(const void * ptr)765*404b540aSrobert print_rtx_ptr_loc (const void *ptr)
766*404b540aSrobert {
767*404b540aSrobert   const struct ptr_loc *loc = get_rtx_ptr_loc (ptr);
768*404b540aSrobert   if (loc != 0)
769*404b540aSrobert     printf ("#line %d \"%s\"\n", loc->lineno, loc->filename);
770*404b540aSrobert }
771*404b540aSrobert 
772*404b540aSrobert /* Return a condition that satisfies both COND1 and COND2.  Either string
773*404b540aSrobert    may be null or empty.  */
774*404b540aSrobert 
775*404b540aSrobert const char *
join_c_conditions(const char * cond1,const char * cond2)776*404b540aSrobert join_c_conditions (const char *cond1, const char *cond2)
777*404b540aSrobert {
778*404b540aSrobert   char *result;
779*404b540aSrobert   const void **entry;
780*404b540aSrobert 
781*404b540aSrobert   if (cond1 == 0 || cond1[0] == 0)
782*404b540aSrobert     return cond2;
783*404b540aSrobert 
784*404b540aSrobert   if (cond2 == 0 || cond2[0] == 0)
785*404b540aSrobert     return cond1;
786*404b540aSrobert 
787*404b540aSrobert   result = concat ("(", cond1, ") && (", cond2, ")", NULL);
788*404b540aSrobert   obstack_ptr_grow (&joined_conditions_obstack, result);
789*404b540aSrobert   obstack_ptr_grow (&joined_conditions_obstack, cond1);
790*404b540aSrobert   obstack_ptr_grow (&joined_conditions_obstack, cond2);
791*404b540aSrobert   entry = XOBFINISH (&joined_conditions_obstack, const void **);
792*404b540aSrobert   *htab_find_slot (joined_conditions, entry, INSERT) = entry;
793*404b540aSrobert   return result;
794*404b540aSrobert }
795*404b540aSrobert 
796*404b540aSrobert /* Print condition COND, wrapped in brackets.  If COND was created by
797*404b540aSrobert    join_c_conditions, recursively invoke this function for the original
798*404b540aSrobert    conditions and join the result with "&&".  Otherwise print a #line
799*404b540aSrobert    directive for COND if its original file position is known.  */
800*404b540aSrobert 
801*404b540aSrobert void
print_c_condition(const char * cond)802*404b540aSrobert print_c_condition (const char *cond)
803*404b540aSrobert {
804*404b540aSrobert   const char **halves = (const char **) htab_find (joined_conditions, &cond);
805*404b540aSrobert   if (halves != 0)
806*404b540aSrobert     {
807*404b540aSrobert       printf ("(");
808*404b540aSrobert       print_c_condition (halves[1]);
809*404b540aSrobert       printf (" && ");
810*404b540aSrobert       print_c_condition (halves[2]);
811*404b540aSrobert       printf (")");
812*404b540aSrobert     }
813*404b540aSrobert   else
814*404b540aSrobert     {
815*404b540aSrobert       putc ('\n', stdout);
816*404b540aSrobert       print_rtx_ptr_loc (cond);
817*404b540aSrobert       printf ("(%s)", cond);
818*404b540aSrobert     }
819*404b540aSrobert }
820*404b540aSrobert 
821*404b540aSrobert /* Read chars from INFILE until a non-whitespace char
822*404b540aSrobert    and return that.  Comments, both Lisp style and C style,
823*404b540aSrobert    are treated as whitespace.
824*404b540aSrobert    Tools such as genflags use this function.  */
825*404b540aSrobert 
826*404b540aSrobert int
read_skip_spaces(FILE * infile)827*404b540aSrobert read_skip_spaces (FILE *infile)
828*404b540aSrobert {
829*404b540aSrobert   int c;
830*404b540aSrobert 
831*404b540aSrobert   while (1)
832*404b540aSrobert     {
833*404b540aSrobert       c = getc (infile);
834*404b540aSrobert       switch (c)
835*404b540aSrobert 	{
836*404b540aSrobert 	case '\n':
837*404b540aSrobert 	  read_rtx_lineno++;
838*404b540aSrobert 	  break;
839*404b540aSrobert 
840*404b540aSrobert 	case ' ': case '\t': case '\f': case '\r':
841*404b540aSrobert 	  break;
842*404b540aSrobert 
843*404b540aSrobert 	case ';':
844*404b540aSrobert 	  do
845*404b540aSrobert 	    c = getc (infile);
846*404b540aSrobert 	  while (c != '\n' && c != EOF);
847*404b540aSrobert 	  read_rtx_lineno++;
848*404b540aSrobert 	  break;
849*404b540aSrobert 
850*404b540aSrobert 	case '/':
851*404b540aSrobert 	  {
852*404b540aSrobert 	    int prevc;
853*404b540aSrobert 	    c = getc (infile);
854*404b540aSrobert 	    if (c != '*')
855*404b540aSrobert 	      fatal_expected_char (infile, '*', c);
856*404b540aSrobert 
857*404b540aSrobert 	    prevc = 0;
858*404b540aSrobert 	    while ((c = getc (infile)) && c != EOF)
859*404b540aSrobert 	      {
860*404b540aSrobert 		if (c == '\n')
861*404b540aSrobert 		   read_rtx_lineno++;
862*404b540aSrobert 	        else if (prevc == '*' && c == '/')
863*404b540aSrobert 		  break;
864*404b540aSrobert 	        prevc = c;
865*404b540aSrobert 	      }
866*404b540aSrobert 	  }
867*404b540aSrobert 	  break;
868*404b540aSrobert 
869*404b540aSrobert 	default:
870*404b540aSrobert 	  return c;
871*404b540aSrobert 	}
872*404b540aSrobert     }
873*404b540aSrobert }
874*404b540aSrobert 
875*404b540aSrobert /* Read an rtx code name into the buffer STR[].
876*404b540aSrobert    It is terminated by any of the punctuation chars of rtx printed syntax.  */
877*404b540aSrobert 
878*404b540aSrobert static void
read_name(char * str,FILE * infile)879*404b540aSrobert read_name (char *str, FILE *infile)
880*404b540aSrobert {
881*404b540aSrobert   char *p;
882*404b540aSrobert   int c;
883*404b540aSrobert 
884*404b540aSrobert   c = read_skip_spaces (infile);
885*404b540aSrobert 
886*404b540aSrobert   p = str;
887*404b540aSrobert   while (1)
888*404b540aSrobert     {
889*404b540aSrobert       if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r' || c == EOF)
890*404b540aSrobert 	break;
891*404b540aSrobert       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
892*404b540aSrobert 	  || c == '(' || c == '[')
893*404b540aSrobert 	{
894*404b540aSrobert 	  ungetc (c, infile);
895*404b540aSrobert 	  break;
896*404b540aSrobert 	}
897*404b540aSrobert       *p++ = c;
898*404b540aSrobert       c = getc (infile);
899*404b540aSrobert     }
900*404b540aSrobert   if (p == str)
901*404b540aSrobert     fatal_with_file_and_line (infile, "missing name or number");
902*404b540aSrobert   if (c == '\n')
903*404b540aSrobert     read_rtx_lineno++;
904*404b540aSrobert 
905*404b540aSrobert   *p = 0;
906*404b540aSrobert 
907*404b540aSrobert   if (md_constants)
908*404b540aSrobert     {
909*404b540aSrobert       /* Do constant expansion.  */
910*404b540aSrobert       struct md_constant *def;
911*404b540aSrobert 
912*404b540aSrobert       p = str;
913*404b540aSrobert       do
914*404b540aSrobert 	{
915*404b540aSrobert 	  struct md_constant tmp_def;
916*404b540aSrobert 
917*404b540aSrobert 	  tmp_def.name = p;
918*404b540aSrobert 	  def = (struct md_constant *) htab_find (md_constants, &tmp_def);
919*404b540aSrobert 	  if (def)
920*404b540aSrobert 	    p = def->value;
921*404b540aSrobert 	} while (def);
922*404b540aSrobert       if (p != str)
923*404b540aSrobert 	strcpy (str, p);
924*404b540aSrobert     }
925*404b540aSrobert }
926*404b540aSrobert 
927*404b540aSrobert /* Subroutine of the string readers.  Handles backslash escapes.
928*404b540aSrobert    Caller has read the backslash, but not placed it into the obstack.  */
929*404b540aSrobert static void
read_escape(FILE * infile)930*404b540aSrobert read_escape (FILE *infile)
931*404b540aSrobert {
932*404b540aSrobert   int c = getc (infile);
933*404b540aSrobert 
934*404b540aSrobert   switch (c)
935*404b540aSrobert     {
936*404b540aSrobert       /* Backslash-newline is replaced by nothing, as in C.  */
937*404b540aSrobert     case '\n':
938*404b540aSrobert       read_rtx_lineno++;
939*404b540aSrobert       return;
940*404b540aSrobert 
941*404b540aSrobert       /* \" \' \\ are replaced by the second character.  */
942*404b540aSrobert     case '\\':
943*404b540aSrobert     case '"':
944*404b540aSrobert     case '\'':
945*404b540aSrobert       break;
946*404b540aSrobert 
947*404b540aSrobert       /* Standard C string escapes:
948*404b540aSrobert 	 \a \b \f \n \r \t \v
949*404b540aSrobert 	 \[0-7] \x
950*404b540aSrobert 	 all are passed through to the output string unmolested.
951*404b540aSrobert 	 In normal use these wind up in a string constant processed
952*404b540aSrobert 	 by the C compiler, which will translate them appropriately.
953*404b540aSrobert 	 We do not bother checking that \[0-7] are followed by up to
954*404b540aSrobert 	 two octal digits, or that \x is followed by N hex digits.
955*404b540aSrobert 	 \? \u \U are left out because they are not in traditional C.  */
956*404b540aSrobert     case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
957*404b540aSrobert     case '0': case '1': case '2': case '3': case '4': case '5': case '6':
958*404b540aSrobert     case '7': case 'x':
959*404b540aSrobert       obstack_1grow (&string_obstack, '\\');
960*404b540aSrobert       break;
961*404b540aSrobert 
962*404b540aSrobert       /* \; makes stuff for a C string constant containing
963*404b540aSrobert 	 newline and tab.  */
964*404b540aSrobert     case ';':
965*404b540aSrobert       obstack_grow (&string_obstack, "\\n\\t", 4);
966*404b540aSrobert       return;
967*404b540aSrobert 
968*404b540aSrobert       /* pass anything else through, but issue a warning.  */
969*404b540aSrobert     default:
970*404b540aSrobert       fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
971*404b540aSrobert 	       read_rtx_filename, read_rtx_lineno, c);
972*404b540aSrobert       obstack_1grow (&string_obstack, '\\');
973*404b540aSrobert       break;
974*404b540aSrobert     }
975*404b540aSrobert 
976*404b540aSrobert   obstack_1grow (&string_obstack, c);
977*404b540aSrobert }
978*404b540aSrobert 
979*404b540aSrobert 
980*404b540aSrobert /* Read a double-quoted string onto the obstack.  Caller has scanned
981*404b540aSrobert    the leading quote.  */
982*404b540aSrobert static char *
read_quoted_string(FILE * infile)983*404b540aSrobert read_quoted_string (FILE *infile)
984*404b540aSrobert {
985*404b540aSrobert   int c;
986*404b540aSrobert 
987*404b540aSrobert   while (1)
988*404b540aSrobert     {
989*404b540aSrobert       c = getc (infile); /* Read the string  */
990*404b540aSrobert       if (c == '\n')
991*404b540aSrobert 	read_rtx_lineno++;
992*404b540aSrobert       else if (c == '\\')
993*404b540aSrobert 	{
994*404b540aSrobert 	  read_escape (infile);
995*404b540aSrobert 	  continue;
996*404b540aSrobert 	}
997*404b540aSrobert       else if (c == '"' || c == EOF)
998*404b540aSrobert 	break;
999*404b540aSrobert 
1000*404b540aSrobert       obstack_1grow (&string_obstack, c);
1001*404b540aSrobert     }
1002*404b540aSrobert 
1003*404b540aSrobert   obstack_1grow (&string_obstack, 0);
1004*404b540aSrobert   return XOBFINISH (&string_obstack, char *);
1005*404b540aSrobert }
1006*404b540aSrobert 
1007*404b540aSrobert /* Read a braced string (a la Tcl) onto the string obstack.  Caller
1008*404b540aSrobert    has scanned the leading brace.  Note that unlike quoted strings,
1009*404b540aSrobert    the outermost braces _are_ included in the string constant.  */
1010*404b540aSrobert static char *
read_braced_string(FILE * infile)1011*404b540aSrobert read_braced_string (FILE *infile)
1012*404b540aSrobert {
1013*404b540aSrobert   int c;
1014*404b540aSrobert   int brace_depth = 1;  /* caller-processed */
1015*404b540aSrobert   unsigned long starting_read_rtx_lineno = read_rtx_lineno;
1016*404b540aSrobert 
1017*404b540aSrobert   obstack_1grow (&string_obstack, '{');
1018*404b540aSrobert   while (brace_depth)
1019*404b540aSrobert     {
1020*404b540aSrobert       c = getc (infile); /* Read the string  */
1021*404b540aSrobert 
1022*404b540aSrobert       if (c == '\n')
1023*404b540aSrobert 	read_rtx_lineno++;
1024*404b540aSrobert       else if (c == '{')
1025*404b540aSrobert 	brace_depth++;
1026*404b540aSrobert       else if (c == '}')
1027*404b540aSrobert 	brace_depth--;
1028*404b540aSrobert       else if (c == '\\')
1029*404b540aSrobert 	{
1030*404b540aSrobert 	  read_escape (infile);
1031*404b540aSrobert 	  continue;
1032*404b540aSrobert 	}
1033*404b540aSrobert       else if (c == EOF)
1034*404b540aSrobert 	fatal_with_file_and_line
1035*404b540aSrobert 	  (infile, "missing closing } for opening brace on line %lu",
1036*404b540aSrobert 	   starting_read_rtx_lineno);
1037*404b540aSrobert 
1038*404b540aSrobert       obstack_1grow (&string_obstack, c);
1039*404b540aSrobert     }
1040*404b540aSrobert 
1041*404b540aSrobert   obstack_1grow (&string_obstack, 0);
1042*404b540aSrobert   return XOBFINISH (&string_obstack, char *);
1043*404b540aSrobert }
1044*404b540aSrobert 
1045*404b540aSrobert /* Read some kind of string constant.  This is the high-level routine
1046*404b540aSrobert    used by read_rtx.  It handles surrounding parentheses, leading star,
1047*404b540aSrobert    and dispatch to the appropriate string constant reader.  */
1048*404b540aSrobert 
1049*404b540aSrobert static char *
read_string(FILE * infile,int star_if_braced)1050*404b540aSrobert read_string (FILE *infile, int star_if_braced)
1051*404b540aSrobert {
1052*404b540aSrobert   char *stringbuf;
1053*404b540aSrobert   int saw_paren = 0;
1054*404b540aSrobert   int c, old_lineno;
1055*404b540aSrobert 
1056*404b540aSrobert   c = read_skip_spaces (infile);
1057*404b540aSrobert   if (c == '(')
1058*404b540aSrobert     {
1059*404b540aSrobert       saw_paren = 1;
1060*404b540aSrobert       c = read_skip_spaces (infile);
1061*404b540aSrobert     }
1062*404b540aSrobert 
1063*404b540aSrobert   old_lineno = read_rtx_lineno;
1064*404b540aSrobert   if (c == '"')
1065*404b540aSrobert     stringbuf = read_quoted_string (infile);
1066*404b540aSrobert   else if (c == '{')
1067*404b540aSrobert     {
1068*404b540aSrobert       if (star_if_braced)
1069*404b540aSrobert 	obstack_1grow (&string_obstack, '*');
1070*404b540aSrobert       stringbuf = read_braced_string (infile);
1071*404b540aSrobert     }
1072*404b540aSrobert   else
1073*404b540aSrobert     fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
1074*404b540aSrobert 
1075*404b540aSrobert   if (saw_paren)
1076*404b540aSrobert     {
1077*404b540aSrobert       c = read_skip_spaces (infile);
1078*404b540aSrobert       if (c != ')')
1079*404b540aSrobert 	fatal_expected_char (infile, ')', c);
1080*404b540aSrobert     }
1081*404b540aSrobert 
1082*404b540aSrobert   set_rtx_ptr_loc (stringbuf, read_rtx_filename, old_lineno);
1083*404b540aSrobert   return stringbuf;
1084*404b540aSrobert }
1085*404b540aSrobert 
1086*404b540aSrobert /* Provide a version of a function to read a long long if the system does
1087*404b540aSrobert    not provide one.  */
1088*404b540aSrobert #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
1089*404b540aSrobert HOST_WIDE_INT atoll (const char *);
1090*404b540aSrobert 
1091*404b540aSrobert HOST_WIDE_INT
atoll(const char * p)1092*404b540aSrobert atoll (const char *p)
1093*404b540aSrobert {
1094*404b540aSrobert   int neg = 0;
1095*404b540aSrobert   HOST_WIDE_INT tmp_wide;
1096*404b540aSrobert 
1097*404b540aSrobert   while (ISSPACE (*p))
1098*404b540aSrobert     p++;
1099*404b540aSrobert   if (*p == '-')
1100*404b540aSrobert     neg = 1, p++;
1101*404b540aSrobert   else if (*p == '+')
1102*404b540aSrobert     p++;
1103*404b540aSrobert 
1104*404b540aSrobert   tmp_wide = 0;
1105*404b540aSrobert   while (ISDIGIT (*p))
1106*404b540aSrobert     {
1107*404b540aSrobert       HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
1108*404b540aSrobert       if (new_wide < tmp_wide)
1109*404b540aSrobert 	{
1110*404b540aSrobert 	  /* Return INT_MAX equiv on overflow.  */
1111*404b540aSrobert 	  tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
1112*404b540aSrobert 	  break;
1113*404b540aSrobert 	}
1114*404b540aSrobert       tmp_wide = new_wide;
1115*404b540aSrobert       p++;
1116*404b540aSrobert     }
1117*404b540aSrobert 
1118*404b540aSrobert   if (neg)
1119*404b540aSrobert     tmp_wide = -tmp_wide;
1120*404b540aSrobert   return tmp_wide;
1121*404b540aSrobert }
1122*404b540aSrobert #endif
1123*404b540aSrobert 
1124*404b540aSrobert /* Given an object that starts with a char * name field, return a hash
1125*404b540aSrobert    code for its name.  */
1126*404b540aSrobert static hashval_t
def_hash(const void * def)1127*404b540aSrobert def_hash (const void *def)
1128*404b540aSrobert {
1129*404b540aSrobert   unsigned result, i;
1130*404b540aSrobert   const char *string = *(const char *const *) def;
1131*404b540aSrobert 
1132*404b540aSrobert   for (result = i = 0; *string++ != '\0'; i++)
1133*404b540aSrobert     result += ((unsigned char) *string << (i % CHAR_BIT));
1134*404b540aSrobert   return result;
1135*404b540aSrobert }
1136*404b540aSrobert 
1137*404b540aSrobert /* Given two objects that start with char * name fields, return true if
1138*404b540aSrobert    they have the same name.  */
1139*404b540aSrobert static int
def_name_eq_p(const void * def1,const void * def2)1140*404b540aSrobert def_name_eq_p (const void *def1, const void *def2)
1141*404b540aSrobert {
1142*404b540aSrobert   return ! strcmp (*(const char *const *) def1,
1143*404b540aSrobert 		   *(const char *const *) def2);
1144*404b540aSrobert }
1145*404b540aSrobert 
1146*404b540aSrobert /* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer suitable
1147*404b540aSrobert    to read a name or number into.  Process a define_constants directive,
1148*404b540aSrobert    starting with the optional space after the "define_constants".  */
1149*404b540aSrobert static void
read_constants(FILE * infile,char * tmp_char)1150*404b540aSrobert read_constants (FILE *infile, char *tmp_char)
1151*404b540aSrobert {
1152*404b540aSrobert   int c;
1153*404b540aSrobert   htab_t defs;
1154*404b540aSrobert 
1155*404b540aSrobert   c = read_skip_spaces (infile);
1156*404b540aSrobert   if (c != '[')
1157*404b540aSrobert     fatal_expected_char (infile, '[', c);
1158*404b540aSrobert   defs = md_constants;
1159*404b540aSrobert   if (! defs)
1160*404b540aSrobert     defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
1161*404b540aSrobert   /* Disable constant expansion during definition processing.  */
1162*404b540aSrobert   md_constants = 0;
1163*404b540aSrobert   while ( (c = read_skip_spaces (infile)) != ']')
1164*404b540aSrobert     {
1165*404b540aSrobert       struct md_constant *def;
1166*404b540aSrobert       void **entry_ptr;
1167*404b540aSrobert 
1168*404b540aSrobert       if (c != '(')
1169*404b540aSrobert 	fatal_expected_char (infile, '(', c);
1170*404b540aSrobert       def = XNEW (struct md_constant);
1171*404b540aSrobert       def->name = tmp_char;
1172*404b540aSrobert       read_name (tmp_char, infile);
1173*404b540aSrobert       entry_ptr = htab_find_slot (defs, def, INSERT);
1174*404b540aSrobert       if (! *entry_ptr)
1175*404b540aSrobert 	def->name = xstrdup (tmp_char);
1176*404b540aSrobert       c = read_skip_spaces (infile);
1177*404b540aSrobert       ungetc (c, infile);
1178*404b540aSrobert       read_name (tmp_char, infile);
1179*404b540aSrobert       if (! *entry_ptr)
1180*404b540aSrobert 	{
1181*404b540aSrobert 	  def->value = xstrdup (tmp_char);
1182*404b540aSrobert 	  *entry_ptr = def;
1183*404b540aSrobert 	}
1184*404b540aSrobert       else
1185*404b540aSrobert 	{
1186*404b540aSrobert 	  def = (struct md_constant *) *entry_ptr;
1187*404b540aSrobert 	  if (strcmp (def->value, tmp_char))
1188*404b540aSrobert 	    fatal_with_file_and_line (infile,
1189*404b540aSrobert 				      "redefinition of %s, was %s, now %s",
1190*404b540aSrobert 				      def->name, def->value, tmp_char);
1191*404b540aSrobert 	}
1192*404b540aSrobert       c = read_skip_spaces (infile);
1193*404b540aSrobert       if (c != ')')
1194*404b540aSrobert 	fatal_expected_char (infile, ')', c);
1195*404b540aSrobert     }
1196*404b540aSrobert   md_constants = defs;
1197*404b540aSrobert   c = read_skip_spaces (infile);
1198*404b540aSrobert   if (c != ')')
1199*404b540aSrobert     fatal_expected_char (infile, ')', c);
1200*404b540aSrobert }
1201*404b540aSrobert 
1202*404b540aSrobert /* For every constant definition, call CALLBACK with two arguments:
1203*404b540aSrobert    a pointer a pointer to the constant definition and INFO.
1204*404b540aSrobert    Stops when CALLBACK returns zero.  */
1205*404b540aSrobert void
traverse_md_constants(htab_trav callback,void * info)1206*404b540aSrobert traverse_md_constants (htab_trav callback, void *info)
1207*404b540aSrobert {
1208*404b540aSrobert   if (md_constants)
1209*404b540aSrobert     htab_traverse (md_constants, callback, info);
1210*404b540aSrobert }
1211*404b540aSrobert 
1212*404b540aSrobert /* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer
1213*404b540aSrobert    suitable to read a name or number into.  Process a
1214*404b540aSrobert    define_conditions directive, starting with the optional space after
1215*404b540aSrobert    the "define_conditions".  The directive looks like this:
1216*404b540aSrobert 
1217*404b540aSrobert      (define_conditions [
1218*404b540aSrobert         (number "string")
1219*404b540aSrobert         (number "string")
1220*404b540aSrobert         ...
1221*404b540aSrobert      ])
1222*404b540aSrobert 
1223*404b540aSrobert    It's not intended to appear in machine descriptions.  It is
1224*404b540aSrobert    generated by (the program generated by) genconditions.c, and
1225*404b540aSrobert    slipped in at the beginning of the sequence of MD files read by
1226*404b540aSrobert    most of the other generators.  */
1227*404b540aSrobert static void
read_conditions(FILE * infile,char * tmp_char)1228*404b540aSrobert read_conditions (FILE *infile, char *tmp_char)
1229*404b540aSrobert {
1230*404b540aSrobert   int c;
1231*404b540aSrobert 
1232*404b540aSrobert   c = read_skip_spaces (infile);
1233*404b540aSrobert   if (c != '[')
1234*404b540aSrobert     fatal_expected_char (infile, '[', c);
1235*404b540aSrobert 
1236*404b540aSrobert   while ( (c = read_skip_spaces (infile)) != ']')
1237*404b540aSrobert     {
1238*404b540aSrobert       char *expr;
1239*404b540aSrobert       int value;
1240*404b540aSrobert 
1241*404b540aSrobert       if (c != '(')
1242*404b540aSrobert 	fatal_expected_char (infile, '(', c);
1243*404b540aSrobert 
1244*404b540aSrobert       read_name (tmp_char, infile);
1245*404b540aSrobert       validate_const_int (infile, tmp_char);
1246*404b540aSrobert       value = atoi (tmp_char);
1247*404b540aSrobert 
1248*404b540aSrobert       c = read_skip_spaces (infile);
1249*404b540aSrobert       if (c != '"')
1250*404b540aSrobert 	fatal_expected_char (infile, '"', c);
1251*404b540aSrobert       expr = read_quoted_string (infile);
1252*404b540aSrobert 
1253*404b540aSrobert       c = read_skip_spaces (infile);
1254*404b540aSrobert       if (c != ')')
1255*404b540aSrobert 	fatal_expected_char (infile, ')', c);
1256*404b540aSrobert 
1257*404b540aSrobert       add_c_test (expr, value);
1258*404b540aSrobert     }
1259*404b540aSrobert   c = read_skip_spaces (infile);
1260*404b540aSrobert   if (c != ')')
1261*404b540aSrobert     fatal_expected_char (infile, ')', c);
1262*404b540aSrobert }
1263*404b540aSrobert 
1264*404b540aSrobert static void
validate_const_int(FILE * infile,const char * string)1265*404b540aSrobert validate_const_int (FILE *infile, const char *string)
1266*404b540aSrobert {
1267*404b540aSrobert   const char *cp;
1268*404b540aSrobert   int valid = 1;
1269*404b540aSrobert 
1270*404b540aSrobert   cp = string;
1271*404b540aSrobert   while (*cp && ISSPACE (*cp))
1272*404b540aSrobert     cp++;
1273*404b540aSrobert   if (*cp == '-' || *cp == '+')
1274*404b540aSrobert     cp++;
1275*404b540aSrobert   if (*cp == 0)
1276*404b540aSrobert     valid = 0;
1277*404b540aSrobert   for (; *cp; cp++)
1278*404b540aSrobert     if (! ISDIGIT (*cp))
1279*404b540aSrobert       valid = 0;
1280*404b540aSrobert   if (!valid)
1281*404b540aSrobert     fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
1282*404b540aSrobert }
1283*404b540aSrobert 
1284*404b540aSrobert /* Search GROUP for a mode or code called NAME and return its numerical
1285*404b540aSrobert    identifier.  INFILE is the file that contained NAME.  */
1286*404b540aSrobert 
1287*404b540aSrobert static int
find_macro(struct macro_group * group,const char * name,FILE * infile)1288*404b540aSrobert find_macro (struct macro_group *group, const char *name, FILE *infile)
1289*404b540aSrobert {
1290*404b540aSrobert   struct mapping *m;
1291*404b540aSrobert 
1292*404b540aSrobert   m = (struct mapping *) htab_find (group->macros, &name);
1293*404b540aSrobert   if (m != 0)
1294*404b540aSrobert     return m->index + group->num_builtins;
1295*404b540aSrobert   return group->find_builtin (name, infile);
1296*404b540aSrobert }
1297*404b540aSrobert 
1298*404b540aSrobert /* Finish reading a declaration of the form:
1299*404b540aSrobert 
1300*404b540aSrobert        (define... <name> [<value1> ... <valuen>])
1301*404b540aSrobert 
1302*404b540aSrobert    from INFILE, where each <valuei> is either a bare symbol name or a
1303*404b540aSrobert    "(<name> <string>)" pair.  The "(define..." part has already been read.
1304*404b540aSrobert 
1305*404b540aSrobert    Represent the declaration as a "mapping" structure; add it to TABLE
1306*404b540aSrobert    (which belongs to GROUP) and return it.  */
1307*404b540aSrobert 
1308*404b540aSrobert static struct mapping *
read_mapping(struct macro_group * group,htab_t table,FILE * infile)1309*404b540aSrobert read_mapping (struct macro_group *group, htab_t table, FILE *infile)
1310*404b540aSrobert {
1311*404b540aSrobert   char tmp_char[256];
1312*404b540aSrobert   struct mapping *m;
1313*404b540aSrobert   struct map_value **end_ptr;
1314*404b540aSrobert   const char *string;
1315*404b540aSrobert   int number, c;
1316*404b540aSrobert 
1317*404b540aSrobert   /* Read the mapping name and create a structure for it.  */
1318*404b540aSrobert   read_name (tmp_char, infile);
1319*404b540aSrobert   m = add_mapping (group, table, tmp_char, infile);
1320*404b540aSrobert 
1321*404b540aSrobert   c = read_skip_spaces (infile);
1322*404b540aSrobert   if (c != '[')
1323*404b540aSrobert     fatal_expected_char (infile, '[', c);
1324*404b540aSrobert 
1325*404b540aSrobert   /* Read each value.  */
1326*404b540aSrobert   end_ptr = &m->values;
1327*404b540aSrobert   c = read_skip_spaces (infile);
1328*404b540aSrobert   do
1329*404b540aSrobert     {
1330*404b540aSrobert       if (c != '(')
1331*404b540aSrobert 	{
1332*404b540aSrobert 	  /* A bare symbol name that is implicitly paired to an
1333*404b540aSrobert 	     empty string.  */
1334*404b540aSrobert 	  ungetc (c, infile);
1335*404b540aSrobert 	  read_name (tmp_char, infile);
1336*404b540aSrobert 	  string = "";
1337*404b540aSrobert 	}
1338*404b540aSrobert       else
1339*404b540aSrobert 	{
1340*404b540aSrobert 	  /* A "(name string)" pair.  */
1341*404b540aSrobert 	  read_name (tmp_char, infile);
1342*404b540aSrobert 	  string = read_string (infile, false);
1343*404b540aSrobert 	  c = read_skip_spaces (infile);
1344*404b540aSrobert 	  if (c != ')')
1345*404b540aSrobert 	    fatal_expected_char (infile, ')', c);
1346*404b540aSrobert 	}
1347*404b540aSrobert       number = group->find_builtin (tmp_char, infile);
1348*404b540aSrobert       end_ptr = add_map_value (end_ptr, number, string);
1349*404b540aSrobert       c = read_skip_spaces (infile);
1350*404b540aSrobert     }
1351*404b540aSrobert   while (c != ']');
1352*404b540aSrobert 
1353*404b540aSrobert   c = read_skip_spaces (infile);
1354*404b540aSrobert   if (c != ')')
1355*404b540aSrobert     fatal_expected_char (infile, ')', c);
1356*404b540aSrobert 
1357*404b540aSrobert   return m;
1358*404b540aSrobert }
1359*404b540aSrobert 
1360*404b540aSrobert /* Check newly-created code macro MACRO to see whether every code has the
1361*404b540aSrobert    same format.  Initialize the macro's entry in bellwether_codes.  */
1362*404b540aSrobert 
1363*404b540aSrobert static void
check_code_macro(struct mapping * macro,FILE * infile)1364*404b540aSrobert check_code_macro (struct mapping *macro, FILE *infile)
1365*404b540aSrobert {
1366*404b540aSrobert   struct map_value *v;
1367*404b540aSrobert   enum rtx_code bellwether;
1368*404b540aSrobert 
1369*404b540aSrobert   bellwether = (enum rtx_code) macro->values->number;
1370*404b540aSrobert   for (v = macro->values->next; v != 0; v = v->next)
1371*404b540aSrobert     if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
1372*404b540aSrobert       fatal_with_file_and_line (infile, "code macro `%s' combines "
1373*404b540aSrobert 				"different rtx formats", macro->name);
1374*404b540aSrobert 
1375*404b540aSrobert   bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
1376*404b540aSrobert 				 macro->index + 1);
1377*404b540aSrobert   bellwether_codes[macro->index] = bellwether;
1378*404b540aSrobert }
1379*404b540aSrobert 
1380*404b540aSrobert /* Read an rtx in printed representation from INFILE and store its
1381*404b540aSrobert    core representation in *X.  Also store the line number of the
1382*404b540aSrobert    opening '(' in *LINENO.  Return true on success or false if the
1383*404b540aSrobert    end of file has been reached.
1384*404b540aSrobert 
1385*404b540aSrobert    read_rtx is not used in the compiler proper, but rather in
1386*404b540aSrobert    the utilities gen*.c that construct C code from machine descriptions.  */
1387*404b540aSrobert 
1388*404b540aSrobert bool
read_rtx(FILE * infile,rtx * x,int * lineno)1389*404b540aSrobert read_rtx (FILE *infile, rtx *x, int *lineno)
1390*404b540aSrobert {
1391*404b540aSrobert   static rtx queue_head, queue_next;
1392*404b540aSrobert   static int queue_lineno;
1393*404b540aSrobert   int c;
1394*404b540aSrobert 
1395*404b540aSrobert   /* Do one-time initialization.  */
1396*404b540aSrobert   if (queue_head == 0)
1397*404b540aSrobert     {
1398*404b540aSrobert       initialize_macros ();
1399*404b540aSrobert       obstack_init (&string_obstack);
1400*404b540aSrobert       queue_head = rtx_alloc (EXPR_LIST);
1401*404b540aSrobert       ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1402*404b540aSrobert       obstack_init (&ptr_loc_obstack);
1403*404b540aSrobert       joined_conditions = htab_create (161, leading_ptr_hash,
1404*404b540aSrobert 				       leading_ptr_eq_p, 0);
1405*404b540aSrobert       obstack_init (&joined_conditions_obstack);
1406*404b540aSrobert     }
1407*404b540aSrobert 
1408*404b540aSrobert   if (queue_next == 0)
1409*404b540aSrobert     {
1410*404b540aSrobert       struct map_value *mode_maps;
1411*404b540aSrobert       struct macro_traverse_data mtd;
1412*404b540aSrobert       rtx from_file;
1413*404b540aSrobert 
1414*404b540aSrobert       c = read_skip_spaces (infile);
1415*404b540aSrobert       if (c == EOF)
1416*404b540aSrobert 	return false;
1417*404b540aSrobert       ungetc (c, infile);
1418*404b540aSrobert 
1419*404b540aSrobert       queue_lineno = read_rtx_lineno;
1420*404b540aSrobert       mode_maps = 0;
1421*404b540aSrobert       from_file = read_rtx_1 (infile, &mode_maps);
1422*404b540aSrobert       if (from_file == 0)
1423*404b540aSrobert 	return false;  /* This confuses a top level (nil) with end of
1424*404b540aSrobert 			  file, but a top level (nil) would have
1425*404b540aSrobert 			  crashed our caller anyway.  */
1426*404b540aSrobert 
1427*404b540aSrobert       queue_next = queue_head;
1428*404b540aSrobert       XEXP (queue_next, 0) = from_file;
1429*404b540aSrobert       XEXP (queue_next, 1) = 0;
1430*404b540aSrobert 
1431*404b540aSrobert       mtd.queue = queue_next;
1432*404b540aSrobert       mtd.mode_maps = mode_maps;
1433*404b540aSrobert       mtd.infile = infile;
1434*404b540aSrobert       mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
1435*404b540aSrobert       htab_traverse (modes.macros, apply_macro_traverse, &mtd);
1436*404b540aSrobert       htab_traverse (codes.macros, apply_macro_traverse, &mtd);
1437*404b540aSrobert       if (mtd.unknown_mode_attr)
1438*404b540aSrobert 	fatal_with_file_and_line (infile,
1439*404b540aSrobert 				  "undefined attribute '%s' used for mode",
1440*404b540aSrobert 				  mtd.unknown_mode_attr);
1441*404b540aSrobert     }
1442*404b540aSrobert 
1443*404b540aSrobert   *x = XEXP (queue_next, 0);
1444*404b540aSrobert   *lineno = queue_lineno;
1445*404b540aSrobert   queue_next = XEXP (queue_next, 1);
1446*404b540aSrobert 
1447*404b540aSrobert   return true;
1448*404b540aSrobert }
1449*404b540aSrobert 
1450*404b540aSrobert /* Subroutine of read_rtx that reads one construct from INFILE but
1451*404b540aSrobert    doesn't apply any macros.  */
1452*404b540aSrobert 
1453*404b540aSrobert static rtx
read_rtx_1(FILE * infile,struct map_value ** mode_maps)1454*404b540aSrobert read_rtx_1 (FILE *infile, struct map_value **mode_maps)
1455*404b540aSrobert {
1456*404b540aSrobert   int i;
1457*404b540aSrobert   RTX_CODE real_code, bellwether_code;
1458*404b540aSrobert   const char *format_ptr;
1459*404b540aSrobert   /* tmp_char is a buffer used for reading decimal integers
1460*404b540aSrobert      and names of rtx types and machine modes.
1461*404b540aSrobert      Therefore, 256 must be enough.  */
1462*404b540aSrobert   char tmp_char[256];
1463*404b540aSrobert   rtx return_rtx;
1464*404b540aSrobert   int c;
1465*404b540aSrobert   int tmp_int;
1466*404b540aSrobert   HOST_WIDE_INT tmp_wide;
1467*404b540aSrobert 
1468*404b540aSrobert   /* Linked list structure for making RTXs: */
1469*404b540aSrobert   struct rtx_list
1470*404b540aSrobert     {
1471*404b540aSrobert       struct rtx_list *next;
1472*404b540aSrobert       rtx value;		/* Value of this node.  */
1473*404b540aSrobert     };
1474*404b540aSrobert 
1475*404b540aSrobert  again:
1476*404b540aSrobert   c = read_skip_spaces (infile); /* Should be open paren.  */
1477*404b540aSrobert 
1478*404b540aSrobert   if (c == EOF)
1479*404b540aSrobert     return 0;
1480*404b540aSrobert 
1481*404b540aSrobert   if (c != '(')
1482*404b540aSrobert     fatal_expected_char (infile, '(', c);
1483*404b540aSrobert 
1484*404b540aSrobert   read_name (tmp_char, infile);
1485*404b540aSrobert   if (strcmp (tmp_char, "nil") == 0)
1486*404b540aSrobert     {
1487*404b540aSrobert       /* (nil) stands for an expression that isn't there.  */
1488*404b540aSrobert       c = read_skip_spaces (infile);
1489*404b540aSrobert       if (c != ')')
1490*404b540aSrobert 	fatal_expected_char (infile, ')', c);
1491*404b540aSrobert       return 0;
1492*404b540aSrobert     }
1493*404b540aSrobert   if (strcmp (tmp_char, "define_constants") == 0)
1494*404b540aSrobert     {
1495*404b540aSrobert       read_constants (infile, tmp_char);
1496*404b540aSrobert       goto again;
1497*404b540aSrobert     }
1498*404b540aSrobert   if (strcmp (tmp_char, "define_conditions") == 0)
1499*404b540aSrobert     {
1500*404b540aSrobert       read_conditions (infile, tmp_char);
1501*404b540aSrobert       goto again;
1502*404b540aSrobert     }
1503*404b540aSrobert   if (strcmp (tmp_char, "define_mode_attr") == 0)
1504*404b540aSrobert     {
1505*404b540aSrobert       read_mapping (&modes, modes.attrs, infile);
1506*404b540aSrobert       goto again;
1507*404b540aSrobert     }
1508*404b540aSrobert   if (strcmp (tmp_char, "define_mode_macro") == 0)
1509*404b540aSrobert     {
1510*404b540aSrobert       read_mapping (&modes, modes.macros, infile);
1511*404b540aSrobert       goto again;
1512*404b540aSrobert     }
1513*404b540aSrobert   if (strcmp (tmp_char, "define_code_attr") == 0)
1514*404b540aSrobert     {
1515*404b540aSrobert       read_mapping (&codes, codes.attrs, infile);
1516*404b540aSrobert       goto again;
1517*404b540aSrobert     }
1518*404b540aSrobert   if (strcmp (tmp_char, "define_code_macro") == 0)
1519*404b540aSrobert     {
1520*404b540aSrobert       check_code_macro (read_mapping (&codes, codes.macros, infile), infile);
1521*404b540aSrobert       goto again;
1522*404b540aSrobert     }
1523*404b540aSrobert   real_code = (enum rtx_code) find_macro (&codes, tmp_char, infile);
1524*404b540aSrobert   bellwether_code = BELLWETHER_CODE (real_code);
1525*404b540aSrobert 
1526*404b540aSrobert   /* If we end up with an insn expression then we free this space below.  */
1527*404b540aSrobert   return_rtx = rtx_alloc (bellwether_code);
1528*404b540aSrobert   format_ptr = GET_RTX_FORMAT (bellwether_code);
1529*404b540aSrobert   PUT_CODE (return_rtx, real_code);
1530*404b540aSrobert 
1531*404b540aSrobert   /* If what follows is `: mode ', read it and
1532*404b540aSrobert      store the mode in the rtx.  */
1533*404b540aSrobert 
1534*404b540aSrobert   i = read_skip_spaces (infile);
1535*404b540aSrobert   if (i == ':')
1536*404b540aSrobert     {
1537*404b540aSrobert       unsigned int mode;
1538*404b540aSrobert 
1539*404b540aSrobert       read_name (tmp_char, infile);
1540*404b540aSrobert       if (tmp_char[0] != '<' || tmp_char[strlen (tmp_char) - 1] != '>')
1541*404b540aSrobert 	mode = find_macro (&modes, tmp_char, infile);
1542*404b540aSrobert       else
1543*404b540aSrobert 	mode = mode_attr_index (mode_maps, tmp_char);
1544*404b540aSrobert       PUT_MODE (return_rtx, (enum machine_mode) mode);
1545*404b540aSrobert       if (GET_MODE (return_rtx) != mode)
1546*404b540aSrobert 	fatal_with_file_and_line (infile, "mode too large");
1547*404b540aSrobert     }
1548*404b540aSrobert   else
1549*404b540aSrobert     ungetc (i, infile);
1550*404b540aSrobert 
1551*404b540aSrobert   for (i = 0; format_ptr[i] != 0; i++)
1552*404b540aSrobert     switch (format_ptr[i])
1553*404b540aSrobert       {
1554*404b540aSrobert 	/* 0 means a field for internal use only.
1555*404b540aSrobert 	   Don't expect it to be present in the input.  */
1556*404b540aSrobert       case '0':
1557*404b540aSrobert 	break;
1558*404b540aSrobert 
1559*404b540aSrobert       case 'e':
1560*404b540aSrobert       case 'u':
1561*404b540aSrobert 	XEXP (return_rtx, i) = read_rtx_1 (infile, mode_maps);
1562*404b540aSrobert 	break;
1563*404b540aSrobert 
1564*404b540aSrobert       case 'V':
1565*404b540aSrobert 	/* 'V' is an optional vector: if a closeparen follows,
1566*404b540aSrobert 	   just store NULL for this element.  */
1567*404b540aSrobert 	c = read_skip_spaces (infile);
1568*404b540aSrobert 	ungetc (c, infile);
1569*404b540aSrobert 	if (c == ')')
1570*404b540aSrobert 	  {
1571*404b540aSrobert 	    XVEC (return_rtx, i) = 0;
1572*404b540aSrobert 	    break;
1573*404b540aSrobert 	  }
1574*404b540aSrobert 	/* Now process the vector.  */
1575*404b540aSrobert 
1576*404b540aSrobert       case 'E':
1577*404b540aSrobert 	{
1578*404b540aSrobert 	  /* Obstack to store scratch vector in.  */
1579*404b540aSrobert 	  struct obstack vector_stack;
1580*404b540aSrobert 	  int list_counter = 0;
1581*404b540aSrobert 	  rtvec return_vec = NULL_RTVEC;
1582*404b540aSrobert 
1583*404b540aSrobert 	  c = read_skip_spaces (infile);
1584*404b540aSrobert 	  if (c != '[')
1585*404b540aSrobert 	    fatal_expected_char (infile, '[', c);
1586*404b540aSrobert 
1587*404b540aSrobert 	  /* Add expressions to a list, while keeping a count.  */
1588*404b540aSrobert 	  obstack_init (&vector_stack);
1589*404b540aSrobert 	  while ((c = read_skip_spaces (infile)) && c != ']')
1590*404b540aSrobert 	    {
1591*404b540aSrobert 	      ungetc (c, infile);
1592*404b540aSrobert 	      list_counter++;
1593*404b540aSrobert 	      obstack_ptr_grow (&vector_stack, read_rtx_1 (infile, mode_maps));
1594*404b540aSrobert 	    }
1595*404b540aSrobert 	  if (list_counter > 0)
1596*404b540aSrobert 	    {
1597*404b540aSrobert 	      return_vec = rtvec_alloc (list_counter);
1598*404b540aSrobert 	      memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
1599*404b540aSrobert 		      list_counter * sizeof (rtx));
1600*404b540aSrobert 	    }
1601*404b540aSrobert 	  else if (format_ptr[i] == 'E')
1602*404b540aSrobert 	    fatal_with_file_and_line (infile,
1603*404b540aSrobert 				      "vector must have at least one element");
1604*404b540aSrobert 	  XVEC (return_rtx, i) = return_vec;
1605*404b540aSrobert 	  obstack_free (&vector_stack, NULL);
1606*404b540aSrobert 	  /* close bracket gotten */
1607*404b540aSrobert 	}
1608*404b540aSrobert 	break;
1609*404b540aSrobert 
1610*404b540aSrobert       case 'S':
1611*404b540aSrobert       case 'T':
1612*404b540aSrobert       case 's':
1613*404b540aSrobert 	{
1614*404b540aSrobert 	  char *stringbuf;
1615*404b540aSrobert 	  int star_if_braced;
1616*404b540aSrobert 
1617*404b540aSrobert 	  c = read_skip_spaces (infile);
1618*404b540aSrobert 	  ungetc (c, infile);
1619*404b540aSrobert 	  if (c == ')')
1620*404b540aSrobert 	    {
1621*404b540aSrobert 	      /* 'S' fields are optional and should be NULL if no string
1622*404b540aSrobert 		 was given.  Also allow normal 's' and 'T' strings to be
1623*404b540aSrobert 		 omitted, treating them in the same way as empty strings.  */
1624*404b540aSrobert 	      XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : "");
1625*404b540aSrobert 	      break;
1626*404b540aSrobert 	    }
1627*404b540aSrobert 
1628*404b540aSrobert 	  /* The output template slot of a DEFINE_INSN,
1629*404b540aSrobert 	     DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically
1630*404b540aSrobert 	     gets a star inserted as its first character, if it is
1631*404b540aSrobert 	     written with a brace block instead of a string constant.  */
1632*404b540aSrobert 	  star_if_braced = (format_ptr[i] == 'T');
1633*404b540aSrobert 
1634*404b540aSrobert 	  stringbuf = read_string (infile, star_if_braced);
1635*404b540aSrobert 
1636*404b540aSrobert 	  /* For insn patterns, we want to provide a default name
1637*404b540aSrobert 	     based on the file and line, like "*foo.md:12", if the
1638*404b540aSrobert 	     given name is blank.  These are only for define_insn and
1639*404b540aSrobert 	     define_insn_and_split, to aid debugging.  */
1640*404b540aSrobert 	  if (*stringbuf == '\0'
1641*404b540aSrobert 	      && i == 0
1642*404b540aSrobert 	      && (GET_CODE (return_rtx) == DEFINE_INSN
1643*404b540aSrobert 		  || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
1644*404b540aSrobert 	    {
1645*404b540aSrobert 	      char line_name[20];
1646*404b540aSrobert 	      const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
1647*404b540aSrobert 	      const char *slash;
1648*404b540aSrobert 	      for (slash = fn; *slash; slash ++)
1649*404b540aSrobert 		if (*slash == '/' || *slash == '\\' || *slash == ':')
1650*404b540aSrobert 		  fn = slash + 1;
1651*404b540aSrobert 	      obstack_1grow (&string_obstack, '*');
1652*404b540aSrobert 	      obstack_grow (&string_obstack, fn, strlen (fn));
1653*404b540aSrobert 	      sprintf (line_name, ":%d", read_rtx_lineno);
1654*404b540aSrobert 	      obstack_grow (&string_obstack, line_name, strlen (line_name)+1);
1655*404b540aSrobert 	      stringbuf = XOBFINISH (&string_obstack, char *);
1656*404b540aSrobert 	    }
1657*404b540aSrobert 
1658*404b540aSrobert 	  if (star_if_braced)
1659*404b540aSrobert 	    XTMPL (return_rtx, i) = stringbuf;
1660*404b540aSrobert 	  else
1661*404b540aSrobert 	    XSTR (return_rtx, i) = stringbuf;
1662*404b540aSrobert 	}
1663*404b540aSrobert 	break;
1664*404b540aSrobert 
1665*404b540aSrobert       case 'w':
1666*404b540aSrobert 	read_name (tmp_char, infile);
1667*404b540aSrobert 	validate_const_int (infile, tmp_char);
1668*404b540aSrobert #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
1669*404b540aSrobert 	tmp_wide = atoi (tmp_char);
1670*404b540aSrobert #else
1671*404b540aSrobert #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
1672*404b540aSrobert 	tmp_wide = atol (tmp_char);
1673*404b540aSrobert #else
1674*404b540aSrobert 	/* Prefer atoll over atoq, since the former is in the ISO C99 standard.
1675*404b540aSrobert 	   But prefer not to use our hand-rolled function above either.  */
1676*404b540aSrobert #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
1677*404b540aSrobert 	tmp_wide = atoll (tmp_char);
1678*404b540aSrobert #else
1679*404b540aSrobert 	tmp_wide = atoq (tmp_char);
1680*404b540aSrobert #endif
1681*404b540aSrobert #endif
1682*404b540aSrobert #endif
1683*404b540aSrobert 	XWINT (return_rtx, i) = tmp_wide;
1684*404b540aSrobert 	break;
1685*404b540aSrobert 
1686*404b540aSrobert       case 'i':
1687*404b540aSrobert       case 'n':
1688*404b540aSrobert 	read_name (tmp_char, infile);
1689*404b540aSrobert 	validate_const_int (infile, tmp_char);
1690*404b540aSrobert 	tmp_int = atoi (tmp_char);
1691*404b540aSrobert 	XINT (return_rtx, i) = tmp_int;
1692*404b540aSrobert 	break;
1693*404b540aSrobert 
1694*404b540aSrobert       default:
1695*404b540aSrobert 	gcc_unreachable ();
1696*404b540aSrobert       }
1697*404b540aSrobert 
1698*404b540aSrobert   c = read_skip_spaces (infile);
1699*404b540aSrobert   if (c != ')')
1700*404b540aSrobert     {
1701*404b540aSrobert       /* Syntactic sugar for AND and IOR, allowing Lisp-like
1702*404b540aSrobert 	 arbitrary number of arguments for them.  */
1703*404b540aSrobert       if (c == '(' && (GET_CODE (return_rtx) == AND
1704*404b540aSrobert 		       || GET_CODE (return_rtx) == IOR))
1705*404b540aSrobert 	return read_rtx_variadic (infile, mode_maps, return_rtx);
1706*404b540aSrobert       else
1707*404b540aSrobert 	fatal_expected_char (infile, ')', c);
1708*404b540aSrobert     }
1709*404b540aSrobert 
1710*404b540aSrobert   return return_rtx;
1711*404b540aSrobert }
1712*404b540aSrobert 
1713*404b540aSrobert /* Mutually recursive subroutine of read_rtx which reads
1714*404b540aSrobert    (thing x1 x2 x3 ...) and produces RTL as if
1715*404b540aSrobert    (thing x1 (thing x2 (thing x3 ...)))  had been written.
1716*404b540aSrobert    When called, FORM is (thing x1 x2), and the file position
1717*404b540aSrobert    is just past the leading parenthesis of x3.  Only works
1718*404b540aSrobert    for THINGs which are dyadic expressions, e.g. AND, IOR.  */
1719*404b540aSrobert static rtx
read_rtx_variadic(FILE * infile,struct map_value ** mode_maps,rtx form)1720*404b540aSrobert read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form)
1721*404b540aSrobert {
1722*404b540aSrobert   char c = '(';
1723*404b540aSrobert   rtx p = form, q;
1724*404b540aSrobert 
1725*404b540aSrobert   do
1726*404b540aSrobert     {
1727*404b540aSrobert       ungetc (c, infile);
1728*404b540aSrobert 
1729*404b540aSrobert       q = rtx_alloc (GET_CODE (p));
1730*404b540aSrobert       PUT_MODE (q, GET_MODE (p));
1731*404b540aSrobert 
1732*404b540aSrobert       XEXP (q, 0) = XEXP (p, 1);
1733*404b540aSrobert       XEXP (q, 1) = read_rtx_1 (infile, mode_maps);
1734*404b540aSrobert 
1735*404b540aSrobert       XEXP (p, 1) = q;
1736*404b540aSrobert       p = q;
1737*404b540aSrobert       c = read_skip_spaces (infile);
1738*404b540aSrobert     }
1739*404b540aSrobert   while (c == '(');
1740*404b540aSrobert 
1741*404b540aSrobert   if (c != ')')
1742*404b540aSrobert     fatal_expected_char (infile, ')', c);
1743*404b540aSrobert 
1744*404b540aSrobert   return form;
1745*404b540aSrobert }
1746