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