1*c87b03e5Sespie /* RTL reader for GNU C Compiler.
2*c87b03e5Sespie Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002
3*c87b03e5Sespie Free Software Foundation, Inc.
4*c87b03e5Sespie
5*c87b03e5Sespie This file is part of GCC.
6*c87b03e5Sespie
7*c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it under
8*c87b03e5Sespie the terms of the GNU General Public License as published by the Free
9*c87b03e5Sespie Software Foundation; either version 2, or (at your option) any later
10*c87b03e5Sespie version.
11*c87b03e5Sespie
12*c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*c87b03e5Sespie WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*c87b03e5Sespie FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*c87b03e5Sespie for more details.
16*c87b03e5Sespie
17*c87b03e5Sespie You should have received a copy of the GNU General Public License
18*c87b03e5Sespie along with GCC; see the file COPYING. If not, write to the Free
19*c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20*c87b03e5Sespie 02111-1307, USA. */
21*c87b03e5Sespie
22*c87b03e5Sespie #include "hconfig.h"
23*c87b03e5Sespie #include "system.h"
24*c87b03e5Sespie #include "rtl.h"
25*c87b03e5Sespie #include "obstack.h"
26*c87b03e5Sespie #include "hashtab.h"
27*c87b03e5Sespie
28*c87b03e5Sespie static htab_t md_constants;
29*c87b03e5Sespie
30*c87b03e5Sespie static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
31*c87b03e5Sespie ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
32*c87b03e5Sespie static void fatal_expected_char PARAMS ((FILE *, int, int)) ATTRIBUTE_NORETURN;
33*c87b03e5Sespie static void read_name PARAMS ((char *, FILE *));
34*c87b03e5Sespie static char *read_string PARAMS ((struct obstack *, FILE *, int));
35*c87b03e5Sespie static char *read_quoted_string PARAMS ((struct obstack *, FILE *));
36*c87b03e5Sespie static char *read_braced_string PARAMS ((struct obstack *, FILE *));
37*c87b03e5Sespie static void read_escape PARAMS ((struct obstack *, FILE *));
38*c87b03e5Sespie static hashval_t def_hash PARAMS ((const void *));
39*c87b03e5Sespie static int def_name_eq_p PARAMS ((const void *, const void *));
40*c87b03e5Sespie static void read_constants PARAMS ((FILE *infile, char *tmp_char));
41*c87b03e5Sespie static void validate_const_int PARAMS ((FILE *, const char *));
42*c87b03e5Sespie
43*c87b03e5Sespie /* Subroutines of read_rtx. */
44*c87b03e5Sespie
45*c87b03e5Sespie /* The current line number for the file. */
46*c87b03e5Sespie int read_rtx_lineno = 1;
47*c87b03e5Sespie
48*c87b03e5Sespie /* The filename for aborting with file and line. */
49*c87b03e5Sespie const char *read_rtx_filename = "<unknown>";
50*c87b03e5Sespie
51*c87b03e5Sespie static void
fatal_with_file_and_line(FILE * infile,const char * msg,...)52*c87b03e5Sespie fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
53*c87b03e5Sespie {
54*c87b03e5Sespie char context[64];
55*c87b03e5Sespie size_t i;
56*c87b03e5Sespie int c;
57*c87b03e5Sespie
58*c87b03e5Sespie VA_OPEN (ap, msg);
59*c87b03e5Sespie VA_FIXEDARG (ap, FILE *, infile);
60*c87b03e5Sespie VA_FIXEDARG (ap, const char *, msg);
61*c87b03e5Sespie
62*c87b03e5Sespie fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
63*c87b03e5Sespie vfprintf (stderr, msg, ap);
64*c87b03e5Sespie putc ('\n', stderr);
65*c87b03e5Sespie
66*c87b03e5Sespie /* Gather some following context. */
67*c87b03e5Sespie for (i = 0; i < sizeof (context)-1; ++i)
68*c87b03e5Sespie {
69*c87b03e5Sespie c = getc (infile);
70*c87b03e5Sespie if (c == EOF)
71*c87b03e5Sespie break;
72*c87b03e5Sespie if (c == '\r' || c == '\n')
73*c87b03e5Sespie break;
74*c87b03e5Sespie context[i] = c;
75*c87b03e5Sespie }
76*c87b03e5Sespie context[i] = '\0';
77*c87b03e5Sespie
78*c87b03e5Sespie fprintf (stderr, "%s:%d: following context is `%s'\n",
79*c87b03e5Sespie read_rtx_filename, read_rtx_lineno, context);
80*c87b03e5Sespie
81*c87b03e5Sespie VA_CLOSE (ap);
82*c87b03e5Sespie exit (1);
83*c87b03e5Sespie }
84*c87b03e5Sespie
85*c87b03e5Sespie /* Dump code after printing a message. Used when read_rtx finds
86*c87b03e5Sespie invalid data. */
87*c87b03e5Sespie
88*c87b03e5Sespie static void
fatal_expected_char(infile,expected_c,actual_c)89*c87b03e5Sespie fatal_expected_char (infile, expected_c, actual_c)
90*c87b03e5Sespie FILE *infile;
91*c87b03e5Sespie int expected_c, actual_c;
92*c87b03e5Sespie {
93*c87b03e5Sespie fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
94*c87b03e5Sespie expected_c, actual_c);
95*c87b03e5Sespie }
96*c87b03e5Sespie
97*c87b03e5Sespie /* Read chars from INFILE until a non-whitespace char
98*c87b03e5Sespie and return that. Comments, both Lisp style and C style,
99*c87b03e5Sespie are treated as whitespace.
100*c87b03e5Sespie Tools such as genflags use this function. */
101*c87b03e5Sespie
102*c87b03e5Sespie int
read_skip_spaces(infile)103*c87b03e5Sespie read_skip_spaces (infile)
104*c87b03e5Sespie FILE *infile;
105*c87b03e5Sespie {
106*c87b03e5Sespie int c;
107*c87b03e5Sespie
108*c87b03e5Sespie while (1)
109*c87b03e5Sespie {
110*c87b03e5Sespie c = getc (infile);
111*c87b03e5Sespie switch (c)
112*c87b03e5Sespie {
113*c87b03e5Sespie case '\n':
114*c87b03e5Sespie read_rtx_lineno++;
115*c87b03e5Sespie break;
116*c87b03e5Sespie
117*c87b03e5Sespie case ' ': case '\t': case '\f': case '\r':
118*c87b03e5Sespie break;
119*c87b03e5Sespie
120*c87b03e5Sespie case ';':
121*c87b03e5Sespie do
122*c87b03e5Sespie c = getc (infile);
123*c87b03e5Sespie while (c != '\n' && c != EOF);
124*c87b03e5Sespie read_rtx_lineno++;
125*c87b03e5Sespie break;
126*c87b03e5Sespie
127*c87b03e5Sespie case '/':
128*c87b03e5Sespie {
129*c87b03e5Sespie int prevc;
130*c87b03e5Sespie c = getc (infile);
131*c87b03e5Sespie if (c != '*')
132*c87b03e5Sespie fatal_expected_char (infile, '*', c);
133*c87b03e5Sespie
134*c87b03e5Sespie prevc = 0;
135*c87b03e5Sespie while ((c = getc (infile)) && c != EOF)
136*c87b03e5Sespie {
137*c87b03e5Sespie if (c == '\n')
138*c87b03e5Sespie read_rtx_lineno++;
139*c87b03e5Sespie else if (prevc == '*' && c == '/')
140*c87b03e5Sespie break;
141*c87b03e5Sespie prevc = c;
142*c87b03e5Sespie }
143*c87b03e5Sespie }
144*c87b03e5Sespie break;
145*c87b03e5Sespie
146*c87b03e5Sespie default:
147*c87b03e5Sespie return c;
148*c87b03e5Sespie }
149*c87b03e5Sespie }
150*c87b03e5Sespie }
151*c87b03e5Sespie
152*c87b03e5Sespie /* Read an rtx code name into the buffer STR[].
153*c87b03e5Sespie It is terminated by any of the punctuation chars of rtx printed syntax. */
154*c87b03e5Sespie
155*c87b03e5Sespie static void
read_name(str,infile)156*c87b03e5Sespie read_name (str, infile)
157*c87b03e5Sespie char *str;
158*c87b03e5Sespie FILE *infile;
159*c87b03e5Sespie {
160*c87b03e5Sespie char *p;
161*c87b03e5Sespie int c;
162*c87b03e5Sespie
163*c87b03e5Sespie c = read_skip_spaces (infile);
164*c87b03e5Sespie
165*c87b03e5Sespie p = str;
166*c87b03e5Sespie while (1)
167*c87b03e5Sespie {
168*c87b03e5Sespie if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r')
169*c87b03e5Sespie break;
170*c87b03e5Sespie if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
171*c87b03e5Sespie || c == '(' || c == '[')
172*c87b03e5Sespie {
173*c87b03e5Sespie ungetc (c, infile);
174*c87b03e5Sespie break;
175*c87b03e5Sespie }
176*c87b03e5Sespie *p++ = c;
177*c87b03e5Sespie c = getc (infile);
178*c87b03e5Sespie }
179*c87b03e5Sespie if (p == str)
180*c87b03e5Sespie fatal_with_file_and_line (infile, "missing name or number");
181*c87b03e5Sespie if (c == '\n')
182*c87b03e5Sespie read_rtx_lineno++;
183*c87b03e5Sespie
184*c87b03e5Sespie *p = 0;
185*c87b03e5Sespie
186*c87b03e5Sespie if (md_constants)
187*c87b03e5Sespie {
188*c87b03e5Sespie /* Do constant expansion. */
189*c87b03e5Sespie struct md_constant *def;
190*c87b03e5Sespie
191*c87b03e5Sespie p = str;
192*c87b03e5Sespie do
193*c87b03e5Sespie {
194*c87b03e5Sespie struct md_constant tmp_def;
195*c87b03e5Sespie
196*c87b03e5Sespie tmp_def.name = p;
197*c87b03e5Sespie def = htab_find (md_constants, &tmp_def);
198*c87b03e5Sespie if (def)
199*c87b03e5Sespie p = def->value;
200*c87b03e5Sespie } while (def);
201*c87b03e5Sespie if (p != str)
202*c87b03e5Sespie strcpy (str, p);
203*c87b03e5Sespie }
204*c87b03e5Sespie }
205*c87b03e5Sespie
206*c87b03e5Sespie /* Subroutine of the string readers. Handles backslash escapes.
207*c87b03e5Sespie Caller has read the backslash, but not placed it into the obstack. */
208*c87b03e5Sespie static void
read_escape(ob,infile)209*c87b03e5Sespie read_escape (ob, infile)
210*c87b03e5Sespie struct obstack *ob;
211*c87b03e5Sespie FILE *infile;
212*c87b03e5Sespie {
213*c87b03e5Sespie int c = getc (infile);
214*c87b03e5Sespie
215*c87b03e5Sespie switch (c)
216*c87b03e5Sespie {
217*c87b03e5Sespie /* Backslash-newline is replaced by nothing, as in C. */
218*c87b03e5Sespie case '\n':
219*c87b03e5Sespie read_rtx_lineno++;
220*c87b03e5Sespie return;
221*c87b03e5Sespie
222*c87b03e5Sespie /* \" \' \\ are replaced by the second character. */
223*c87b03e5Sespie case '\\':
224*c87b03e5Sespie case '"':
225*c87b03e5Sespie case '\'':
226*c87b03e5Sespie break;
227*c87b03e5Sespie
228*c87b03e5Sespie /* Standard C string escapes:
229*c87b03e5Sespie \a \b \f \n \r \t \v
230*c87b03e5Sespie \[0-7] \x
231*c87b03e5Sespie all are passed through to the output string unmolested.
232*c87b03e5Sespie In normal use these wind up in a string constant processed
233*c87b03e5Sespie by the C compiler, which will translate them appropriately.
234*c87b03e5Sespie We do not bother checking that \[0-7] are followed by up to
235*c87b03e5Sespie two octal digits, or that \x is followed by N hex digits.
236*c87b03e5Sespie \? \u \U are left out because they are not in traditional C. */
237*c87b03e5Sespie case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
238*c87b03e5Sespie case '0': case '1': case '2': case '3': case '4': case '5': case '6':
239*c87b03e5Sespie case '7': case 'x':
240*c87b03e5Sespie obstack_1grow (ob, '\\');
241*c87b03e5Sespie break;
242*c87b03e5Sespie
243*c87b03e5Sespie /* \; makes stuff for a C string constant containing
244*c87b03e5Sespie newline and tab. */
245*c87b03e5Sespie case ';':
246*c87b03e5Sespie obstack_grow (ob, "\\n\\t", 4);
247*c87b03e5Sespie return;
248*c87b03e5Sespie
249*c87b03e5Sespie /* pass anything else through, but issue a warning. */
250*c87b03e5Sespie default:
251*c87b03e5Sespie fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
252*c87b03e5Sespie read_rtx_filename, read_rtx_lineno, c);
253*c87b03e5Sespie obstack_1grow (ob, '\\');
254*c87b03e5Sespie break;
255*c87b03e5Sespie }
256*c87b03e5Sespie
257*c87b03e5Sespie obstack_1grow (ob, c);
258*c87b03e5Sespie }
259*c87b03e5Sespie
260*c87b03e5Sespie
261*c87b03e5Sespie /* Read a double-quoted string onto the obstack. Caller has scanned
262*c87b03e5Sespie the leading quote. */
263*c87b03e5Sespie static char *
read_quoted_string(ob,infile)264*c87b03e5Sespie read_quoted_string (ob, infile)
265*c87b03e5Sespie struct obstack *ob;
266*c87b03e5Sespie FILE *infile;
267*c87b03e5Sespie {
268*c87b03e5Sespie int c;
269*c87b03e5Sespie
270*c87b03e5Sespie while (1)
271*c87b03e5Sespie {
272*c87b03e5Sespie c = getc (infile); /* Read the string */
273*c87b03e5Sespie if (c == '\n')
274*c87b03e5Sespie read_rtx_lineno++;
275*c87b03e5Sespie else if (c == '\\')
276*c87b03e5Sespie {
277*c87b03e5Sespie read_escape (ob, infile);
278*c87b03e5Sespie continue;
279*c87b03e5Sespie }
280*c87b03e5Sespie else if (c == '"')
281*c87b03e5Sespie break;
282*c87b03e5Sespie
283*c87b03e5Sespie obstack_1grow (ob, c);
284*c87b03e5Sespie }
285*c87b03e5Sespie
286*c87b03e5Sespie obstack_1grow (ob, 0);
287*c87b03e5Sespie return obstack_finish (ob);
288*c87b03e5Sespie }
289*c87b03e5Sespie
290*c87b03e5Sespie /* Read a braced string (a la Tcl) onto the obstack. Caller has
291*c87b03e5Sespie scanned the leading brace. Note that unlike quoted strings,
292*c87b03e5Sespie the outermost braces _are_ included in the string constant. */
293*c87b03e5Sespie static char *
read_braced_string(ob,infile)294*c87b03e5Sespie read_braced_string (ob, infile)
295*c87b03e5Sespie struct obstack *ob;
296*c87b03e5Sespie FILE *infile;
297*c87b03e5Sespie {
298*c87b03e5Sespie int c;
299*c87b03e5Sespie int brace_depth = 1; /* caller-processed */
300*c87b03e5Sespie
301*c87b03e5Sespie obstack_1grow (ob, '{');
302*c87b03e5Sespie while (brace_depth)
303*c87b03e5Sespie {
304*c87b03e5Sespie c = getc (infile); /* Read the string */
305*c87b03e5Sespie if (c == '\n')
306*c87b03e5Sespie read_rtx_lineno++;
307*c87b03e5Sespie else if (c == '{')
308*c87b03e5Sespie brace_depth++;
309*c87b03e5Sespie else if (c == '}')
310*c87b03e5Sespie brace_depth--;
311*c87b03e5Sespie else if (c == '\\')
312*c87b03e5Sespie {
313*c87b03e5Sespie read_escape (ob, infile);
314*c87b03e5Sespie continue;
315*c87b03e5Sespie }
316*c87b03e5Sespie
317*c87b03e5Sespie obstack_1grow (ob, c);
318*c87b03e5Sespie }
319*c87b03e5Sespie
320*c87b03e5Sespie obstack_1grow (ob, 0);
321*c87b03e5Sespie return obstack_finish (ob);
322*c87b03e5Sespie }
323*c87b03e5Sespie
324*c87b03e5Sespie /* Read some kind of string constant. This is the high-level routine
325*c87b03e5Sespie used by read_rtx. It handles surrounding parentheses, leading star,
326*c87b03e5Sespie and dispatch to the appropriate string constant reader. */
327*c87b03e5Sespie
328*c87b03e5Sespie static char *
read_string(ob,infile,star_if_braced)329*c87b03e5Sespie read_string (ob, infile, star_if_braced)
330*c87b03e5Sespie struct obstack *ob;
331*c87b03e5Sespie FILE *infile;
332*c87b03e5Sespie int star_if_braced;
333*c87b03e5Sespie {
334*c87b03e5Sespie char *stringbuf;
335*c87b03e5Sespie int saw_paren = 0;
336*c87b03e5Sespie int c;
337*c87b03e5Sespie
338*c87b03e5Sespie c = read_skip_spaces (infile);
339*c87b03e5Sespie if (c == '(')
340*c87b03e5Sespie {
341*c87b03e5Sespie saw_paren = 1;
342*c87b03e5Sespie c = read_skip_spaces (infile);
343*c87b03e5Sespie }
344*c87b03e5Sespie
345*c87b03e5Sespie if (c == '"')
346*c87b03e5Sespie stringbuf = read_quoted_string (ob, infile);
347*c87b03e5Sespie else if (c == '{')
348*c87b03e5Sespie {
349*c87b03e5Sespie if (star_if_braced)
350*c87b03e5Sespie obstack_1grow (ob, '*');
351*c87b03e5Sespie stringbuf = read_braced_string (ob, infile);
352*c87b03e5Sespie }
353*c87b03e5Sespie else
354*c87b03e5Sespie fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
355*c87b03e5Sespie
356*c87b03e5Sespie if (saw_paren)
357*c87b03e5Sespie {
358*c87b03e5Sespie c = read_skip_spaces (infile);
359*c87b03e5Sespie if (c != ')')
360*c87b03e5Sespie fatal_expected_char (infile, ')', c);
361*c87b03e5Sespie }
362*c87b03e5Sespie
363*c87b03e5Sespie return stringbuf;
364*c87b03e5Sespie }
365*c87b03e5Sespie
366*c87b03e5Sespie /* Provide a version of a function to read a long long if the system does
367*c87b03e5Sespie not provide one. */
368*c87b03e5Sespie #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
369*c87b03e5Sespie HOST_WIDE_INT
atoll(p)370*c87b03e5Sespie atoll (p)
371*c87b03e5Sespie const char *p;
372*c87b03e5Sespie {
373*c87b03e5Sespie int neg = 0;
374*c87b03e5Sespie HOST_WIDE_INT tmp_wide;
375*c87b03e5Sespie
376*c87b03e5Sespie while (ISSPACE (*p))
377*c87b03e5Sespie p++;
378*c87b03e5Sespie if (*p == '-')
379*c87b03e5Sespie neg = 1, p++;
380*c87b03e5Sespie else if (*p == '+')
381*c87b03e5Sespie p++;
382*c87b03e5Sespie
383*c87b03e5Sespie tmp_wide = 0;
384*c87b03e5Sespie while (ISDIGIT (*p))
385*c87b03e5Sespie {
386*c87b03e5Sespie HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
387*c87b03e5Sespie if (new_wide < tmp_wide)
388*c87b03e5Sespie {
389*c87b03e5Sespie /* Return INT_MAX equiv on overflow. */
390*c87b03e5Sespie tmp_wide = (~(unsigned HOST_WIDE_INT) 0) >> 1;
391*c87b03e5Sespie break;
392*c87b03e5Sespie }
393*c87b03e5Sespie tmp_wide = new_wide;
394*c87b03e5Sespie p++;
395*c87b03e5Sespie }
396*c87b03e5Sespie
397*c87b03e5Sespie if (neg)
398*c87b03e5Sespie tmp_wide = -tmp_wide;
399*c87b03e5Sespie return tmp_wide;
400*c87b03e5Sespie }
401*c87b03e5Sespie #endif
402*c87b03e5Sespie
403*c87b03e5Sespie /* Given a constant definition, return a hash code for its name. */
404*c87b03e5Sespie static hashval_t
def_hash(def)405*c87b03e5Sespie def_hash (def)
406*c87b03e5Sespie const void *def;
407*c87b03e5Sespie {
408*c87b03e5Sespie unsigned result, i;
409*c87b03e5Sespie const char *string = ((const struct md_constant *) def)->name;
410*c87b03e5Sespie
411*c87b03e5Sespie for (result = i = 0;*string++ != '\0'; i++)
412*c87b03e5Sespie result += ((unsigned char) *string << (i % CHAR_BIT));
413*c87b03e5Sespie return result;
414*c87b03e5Sespie }
415*c87b03e5Sespie
416*c87b03e5Sespie /* Given two constant definitions, return true if they have the same name. */
417*c87b03e5Sespie static int
def_name_eq_p(def1,def2)418*c87b03e5Sespie def_name_eq_p (def1, def2)
419*c87b03e5Sespie const void *def1, *def2;
420*c87b03e5Sespie {
421*c87b03e5Sespie return ! strcmp (((const struct md_constant *) def1)->name,
422*c87b03e5Sespie ((const struct md_constant *) def2)->name);
423*c87b03e5Sespie }
424*c87b03e5Sespie
425*c87b03e5Sespie /* INFILE is a FILE pointer to read text from. TMP_CHAR is a buffer suitable
426*c87b03e5Sespie to read a name or number into. Process a define_constants directive,
427*c87b03e5Sespie starting with the optional space after the "define_constants". */
428*c87b03e5Sespie static void
read_constants(infile,tmp_char)429*c87b03e5Sespie read_constants (infile, tmp_char)
430*c87b03e5Sespie FILE *infile;
431*c87b03e5Sespie char *tmp_char;
432*c87b03e5Sespie {
433*c87b03e5Sespie int c;
434*c87b03e5Sespie htab_t defs;
435*c87b03e5Sespie
436*c87b03e5Sespie c = read_skip_spaces (infile);
437*c87b03e5Sespie if (c != '[')
438*c87b03e5Sespie fatal_expected_char (infile, '[', c);
439*c87b03e5Sespie defs = md_constants;
440*c87b03e5Sespie if (! defs)
441*c87b03e5Sespie defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
442*c87b03e5Sespie /* Disable constant expansion during definition processing. */
443*c87b03e5Sespie md_constants = 0;
444*c87b03e5Sespie while ( (c = read_skip_spaces (infile)) != ']')
445*c87b03e5Sespie {
446*c87b03e5Sespie struct md_constant *def;
447*c87b03e5Sespie void **entry_ptr;
448*c87b03e5Sespie
449*c87b03e5Sespie if (c != '(')
450*c87b03e5Sespie fatal_expected_char (infile, '(', c);
451*c87b03e5Sespie def = xmalloc (sizeof (struct md_constant));
452*c87b03e5Sespie def->name = tmp_char;
453*c87b03e5Sespie read_name (tmp_char, infile);
454*c87b03e5Sespie entry_ptr = htab_find_slot (defs, def, TRUE);
455*c87b03e5Sespie if (! *entry_ptr)
456*c87b03e5Sespie def->name = xstrdup (tmp_char);
457*c87b03e5Sespie c = read_skip_spaces (infile);
458*c87b03e5Sespie ungetc (c, infile);
459*c87b03e5Sespie read_name (tmp_char, infile);
460*c87b03e5Sespie if (! *entry_ptr)
461*c87b03e5Sespie {
462*c87b03e5Sespie def->value = xstrdup (tmp_char);
463*c87b03e5Sespie *entry_ptr = def;
464*c87b03e5Sespie }
465*c87b03e5Sespie else
466*c87b03e5Sespie {
467*c87b03e5Sespie def = *entry_ptr;
468*c87b03e5Sespie if (strcmp (def->value, tmp_char))
469*c87b03e5Sespie fatal_with_file_and_line (infile,
470*c87b03e5Sespie "redefinition of %s, was %s, now %s",
471*c87b03e5Sespie def->name, def->value, tmp_char);
472*c87b03e5Sespie }
473*c87b03e5Sespie c = read_skip_spaces (infile);
474*c87b03e5Sespie if (c != ')')
475*c87b03e5Sespie fatal_expected_char (infile, ')', c);
476*c87b03e5Sespie }
477*c87b03e5Sespie md_constants = defs;
478*c87b03e5Sespie c = read_skip_spaces (infile);
479*c87b03e5Sespie if (c != ')')
480*c87b03e5Sespie fatal_expected_char (infile, ')', c);
481*c87b03e5Sespie }
482*c87b03e5Sespie
483*c87b03e5Sespie /* For every constant definition, call CALLBACK with two arguments:
484*c87b03e5Sespie a pointer a pointer to the constant definition and INFO.
485*c87b03e5Sespie Stops when CALLBACK returns zero. */
486*c87b03e5Sespie void
traverse_md_constants(callback,info)487*c87b03e5Sespie traverse_md_constants (callback, info)
488*c87b03e5Sespie htab_trav callback;
489*c87b03e5Sespie void *info;
490*c87b03e5Sespie {
491*c87b03e5Sespie if (md_constants)
492*c87b03e5Sespie htab_traverse (md_constants, callback, info);
493*c87b03e5Sespie }
494*c87b03e5Sespie
495*c87b03e5Sespie static void
validate_const_int(infile,string)496*c87b03e5Sespie validate_const_int (infile, string)
497*c87b03e5Sespie FILE *infile;
498*c87b03e5Sespie const char *string;
499*c87b03e5Sespie {
500*c87b03e5Sespie const char *cp;
501*c87b03e5Sespie int valid = 1;
502*c87b03e5Sespie
503*c87b03e5Sespie cp = string;
504*c87b03e5Sespie while (*cp && ISSPACE (*cp))
505*c87b03e5Sespie cp++;
506*c87b03e5Sespie if (*cp == '-' || *cp == '+')
507*c87b03e5Sespie cp++;
508*c87b03e5Sespie if (*cp == 0)
509*c87b03e5Sespie valid = 0;
510*c87b03e5Sespie for (; *cp; cp++)
511*c87b03e5Sespie if (! ISDIGIT (*cp))
512*c87b03e5Sespie valid = 0;
513*c87b03e5Sespie if (!valid)
514*c87b03e5Sespie fatal_with_file_and_line (infile, "invalid decimal constant \"%s\"\n", string);
515*c87b03e5Sespie }
516*c87b03e5Sespie
517*c87b03e5Sespie /* Read an rtx in printed representation from INFILE
518*c87b03e5Sespie and return an actual rtx in core constructed accordingly.
519*c87b03e5Sespie read_rtx is not used in the compiler proper, but rather in
520*c87b03e5Sespie the utilities gen*.c that construct C code from machine descriptions. */
521*c87b03e5Sespie
522*c87b03e5Sespie rtx
read_rtx(infile)523*c87b03e5Sespie read_rtx (infile)
524*c87b03e5Sespie FILE *infile;
525*c87b03e5Sespie {
526*c87b03e5Sespie int i, j;
527*c87b03e5Sespie RTX_CODE tmp_code;
528*c87b03e5Sespie const char *format_ptr;
529*c87b03e5Sespie /* tmp_char is a buffer used for reading decimal integers
530*c87b03e5Sespie and names of rtx types and machine modes.
531*c87b03e5Sespie Therefore, 256 must be enough. */
532*c87b03e5Sespie char tmp_char[256];
533*c87b03e5Sespie rtx return_rtx;
534*c87b03e5Sespie int c;
535*c87b03e5Sespie int tmp_int;
536*c87b03e5Sespie HOST_WIDE_INT tmp_wide;
537*c87b03e5Sespie
538*c87b03e5Sespie /* Obstack used for allocating RTL objects. */
539*c87b03e5Sespie static struct obstack rtl_obstack;
540*c87b03e5Sespie static int initialized;
541*c87b03e5Sespie
542*c87b03e5Sespie /* Linked list structure for making RTXs: */
543*c87b03e5Sespie struct rtx_list
544*c87b03e5Sespie {
545*c87b03e5Sespie struct rtx_list *next;
546*c87b03e5Sespie rtx value; /* Value of this node. */
547*c87b03e5Sespie };
548*c87b03e5Sespie
549*c87b03e5Sespie if (!initialized) {
550*c87b03e5Sespie obstack_init (&rtl_obstack);
551*c87b03e5Sespie initialized = 1;
552*c87b03e5Sespie }
553*c87b03e5Sespie
554*c87b03e5Sespie again:
555*c87b03e5Sespie c = read_skip_spaces (infile); /* Should be open paren. */
556*c87b03e5Sespie if (c != '(')
557*c87b03e5Sespie fatal_expected_char (infile, '(', c);
558*c87b03e5Sespie
559*c87b03e5Sespie read_name (tmp_char, infile);
560*c87b03e5Sespie
561*c87b03e5Sespie tmp_code = UNKNOWN;
562*c87b03e5Sespie
563*c87b03e5Sespie if (! strcmp (tmp_char, "define_constants"))
564*c87b03e5Sespie {
565*c87b03e5Sespie read_constants (infile, tmp_char);
566*c87b03e5Sespie goto again;
567*c87b03e5Sespie }
568*c87b03e5Sespie for (i = 0; i < NUM_RTX_CODE; i++)
569*c87b03e5Sespie if (! strcmp (tmp_char, GET_RTX_NAME (i)))
570*c87b03e5Sespie {
571*c87b03e5Sespie tmp_code = (RTX_CODE) i; /* get value for name */
572*c87b03e5Sespie break;
573*c87b03e5Sespie }
574*c87b03e5Sespie
575*c87b03e5Sespie if (tmp_code == UNKNOWN)
576*c87b03e5Sespie fatal_with_file_and_line (infile, "unknown rtx code `%s'", tmp_char);
577*c87b03e5Sespie
578*c87b03e5Sespie /* (NIL) stands for an expression that isn't there. */
579*c87b03e5Sespie if (tmp_code == NIL)
580*c87b03e5Sespie {
581*c87b03e5Sespie /* Discard the closeparen. */
582*c87b03e5Sespie while ((c = getc (infile)) && c != ')')
583*c87b03e5Sespie ;
584*c87b03e5Sespie
585*c87b03e5Sespie return 0;
586*c87b03e5Sespie }
587*c87b03e5Sespie
588*c87b03e5Sespie /* If we end up with an insn expression then we free this space below. */
589*c87b03e5Sespie return_rtx = rtx_alloc (tmp_code);
590*c87b03e5Sespie format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
591*c87b03e5Sespie
592*c87b03e5Sespie /* If what follows is `: mode ', read it and
593*c87b03e5Sespie store the mode in the rtx. */
594*c87b03e5Sespie
595*c87b03e5Sespie i = read_skip_spaces (infile);
596*c87b03e5Sespie if (i == ':')
597*c87b03e5Sespie {
598*c87b03e5Sespie read_name (tmp_char, infile);
599*c87b03e5Sespie for (j = 0; j < NUM_MACHINE_MODES; j++)
600*c87b03e5Sespie if (! strcmp (GET_MODE_NAME (j), tmp_char))
601*c87b03e5Sespie break;
602*c87b03e5Sespie
603*c87b03e5Sespie if (j == MAX_MACHINE_MODE)
604*c87b03e5Sespie fatal_with_file_and_line (infile, "unknown mode `%s'", tmp_char);
605*c87b03e5Sespie
606*c87b03e5Sespie PUT_MODE (return_rtx, (enum machine_mode) j);
607*c87b03e5Sespie }
608*c87b03e5Sespie else
609*c87b03e5Sespie ungetc (i, infile);
610*c87b03e5Sespie
611*c87b03e5Sespie for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
612*c87b03e5Sespie switch (*format_ptr++)
613*c87b03e5Sespie {
614*c87b03e5Sespie /* 0 means a field for internal use only.
615*c87b03e5Sespie Don't expect it to be present in the input. */
616*c87b03e5Sespie case '0':
617*c87b03e5Sespie break;
618*c87b03e5Sespie
619*c87b03e5Sespie case 'e':
620*c87b03e5Sespie case 'u':
621*c87b03e5Sespie XEXP (return_rtx, i) = read_rtx (infile);
622*c87b03e5Sespie break;
623*c87b03e5Sespie
624*c87b03e5Sespie case 'V':
625*c87b03e5Sespie /* 'V' is an optional vector: if a closeparen follows,
626*c87b03e5Sespie just store NULL for this element. */
627*c87b03e5Sespie c = read_skip_spaces (infile);
628*c87b03e5Sespie ungetc (c, infile);
629*c87b03e5Sespie if (c == ')')
630*c87b03e5Sespie {
631*c87b03e5Sespie XVEC (return_rtx, i) = 0;
632*c87b03e5Sespie break;
633*c87b03e5Sespie }
634*c87b03e5Sespie /* Now process the vector. */
635*c87b03e5Sespie
636*c87b03e5Sespie case 'E':
637*c87b03e5Sespie {
638*c87b03e5Sespie /* Obstack to store scratch vector in. */
639*c87b03e5Sespie struct obstack vector_stack;
640*c87b03e5Sespie int list_counter = 0;
641*c87b03e5Sespie rtvec return_vec = NULL_RTVEC;
642*c87b03e5Sespie
643*c87b03e5Sespie c = read_skip_spaces (infile);
644*c87b03e5Sespie if (c != '[')
645*c87b03e5Sespie fatal_expected_char (infile, '[', c);
646*c87b03e5Sespie
647*c87b03e5Sespie /* add expressions to a list, while keeping a count */
648*c87b03e5Sespie obstack_init (&vector_stack);
649*c87b03e5Sespie while ((c = read_skip_spaces (infile)) && c != ']')
650*c87b03e5Sespie {
651*c87b03e5Sespie ungetc (c, infile);
652*c87b03e5Sespie list_counter++;
653*c87b03e5Sespie obstack_ptr_grow (&vector_stack, (PTR) read_rtx (infile));
654*c87b03e5Sespie }
655*c87b03e5Sespie if (list_counter > 0)
656*c87b03e5Sespie {
657*c87b03e5Sespie return_vec = rtvec_alloc (list_counter);
658*c87b03e5Sespie memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
659*c87b03e5Sespie list_counter * sizeof (rtx));
660*c87b03e5Sespie }
661*c87b03e5Sespie XVEC (return_rtx, i) = return_vec;
662*c87b03e5Sespie obstack_free (&vector_stack, NULL);
663*c87b03e5Sespie /* close bracket gotten */
664*c87b03e5Sespie }
665*c87b03e5Sespie break;
666*c87b03e5Sespie
667*c87b03e5Sespie case 'S':
668*c87b03e5Sespie /* 'S' is an optional string: if a closeparen follows,
669*c87b03e5Sespie just store NULL for this element. */
670*c87b03e5Sespie c = read_skip_spaces (infile);
671*c87b03e5Sespie ungetc (c, infile);
672*c87b03e5Sespie if (c == ')')
673*c87b03e5Sespie {
674*c87b03e5Sespie XSTR (return_rtx, i) = 0;
675*c87b03e5Sespie break;
676*c87b03e5Sespie }
677*c87b03e5Sespie
678*c87b03e5Sespie case 'T':
679*c87b03e5Sespie case 's':
680*c87b03e5Sespie {
681*c87b03e5Sespie char *stringbuf;
682*c87b03e5Sespie
683*c87b03e5Sespie /* The output template slot of a DEFINE_INSN,
684*c87b03e5Sespie DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically
685*c87b03e5Sespie gets a star inserted as its first character, if it is
686*c87b03e5Sespie written with a brace block instead of a string constant. */
687*c87b03e5Sespie int star_if_braced = (format_ptr[-1] == 'T');
688*c87b03e5Sespie
689*c87b03e5Sespie stringbuf = read_string (&rtl_obstack, infile, star_if_braced);
690*c87b03e5Sespie
691*c87b03e5Sespie /* For insn patterns, we want to provide a default name
692*c87b03e5Sespie based on the file and line, like "*foo.md:12", if the
693*c87b03e5Sespie given name is blank. These are only for define_insn and
694*c87b03e5Sespie define_insn_and_split, to aid debugging. */
695*c87b03e5Sespie if (*stringbuf == '\0'
696*c87b03e5Sespie && i == 0
697*c87b03e5Sespie && (GET_CODE (return_rtx) == DEFINE_INSN
698*c87b03e5Sespie || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
699*c87b03e5Sespie {
700*c87b03e5Sespie char line_name[20];
701*c87b03e5Sespie const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
702*c87b03e5Sespie const char *slash;
703*c87b03e5Sespie for (slash = fn; *slash; slash ++)
704*c87b03e5Sespie if (*slash == '/' || *slash == '\\' || *slash == ':')
705*c87b03e5Sespie fn = slash + 1;
706*c87b03e5Sespie obstack_1grow (&rtl_obstack, '*');
707*c87b03e5Sespie obstack_grow (&rtl_obstack, fn, strlen (fn));
708*c87b03e5Sespie sprintf (line_name, ":%d", read_rtx_lineno);
709*c87b03e5Sespie obstack_grow (&rtl_obstack, line_name, strlen (line_name)+1);
710*c87b03e5Sespie stringbuf = (char *) obstack_finish (&rtl_obstack);
711*c87b03e5Sespie }
712*c87b03e5Sespie
713*c87b03e5Sespie if (star_if_braced)
714*c87b03e5Sespie XTMPL (return_rtx, i) = stringbuf;
715*c87b03e5Sespie else
716*c87b03e5Sespie XSTR (return_rtx, i) = stringbuf;
717*c87b03e5Sespie }
718*c87b03e5Sespie break;
719*c87b03e5Sespie
720*c87b03e5Sespie case 'w':
721*c87b03e5Sespie read_name (tmp_char, infile);
722*c87b03e5Sespie validate_const_int (infile, tmp_char);
723*c87b03e5Sespie #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
724*c87b03e5Sespie tmp_wide = atoi (tmp_char);
725*c87b03e5Sespie #else
726*c87b03e5Sespie #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
727*c87b03e5Sespie tmp_wide = atol (tmp_char);
728*c87b03e5Sespie #else
729*c87b03e5Sespie /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
730*c87b03e5Sespie But prefer not to use our hand-rolled function above either. */
731*c87b03e5Sespie #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
732*c87b03e5Sespie tmp_wide = atoll (tmp_char);
733*c87b03e5Sespie #else
734*c87b03e5Sespie tmp_wide = atoq (tmp_char);
735*c87b03e5Sespie #endif
736*c87b03e5Sespie #endif
737*c87b03e5Sespie #endif
738*c87b03e5Sespie XWINT (return_rtx, i) = tmp_wide;
739*c87b03e5Sespie break;
740*c87b03e5Sespie
741*c87b03e5Sespie case 'i':
742*c87b03e5Sespie case 'n':
743*c87b03e5Sespie read_name (tmp_char, infile);
744*c87b03e5Sespie validate_const_int (infile, tmp_char);
745*c87b03e5Sespie tmp_int = atoi (tmp_char);
746*c87b03e5Sespie XINT (return_rtx, i) = tmp_int;
747*c87b03e5Sespie break;
748*c87b03e5Sespie
749*c87b03e5Sespie default:
750*c87b03e5Sespie fprintf (stderr,
751*c87b03e5Sespie "switch format wrong in rtl.read_rtx(). format was: %c.\n",
752*c87b03e5Sespie format_ptr[-1]);
753*c87b03e5Sespie fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
754*c87b03e5Sespie abort ();
755*c87b03e5Sespie }
756*c87b03e5Sespie
757*c87b03e5Sespie c = read_skip_spaces (infile);
758*c87b03e5Sespie if (c != ')')
759*c87b03e5Sespie fatal_expected_char (infile, ')', c);
760*c87b03e5Sespie
761*c87b03e5Sespie return return_rtx;
762*c87b03e5Sespie }
763