xref: /openbsd/gnu/usr.bin/gcc/gcc/read-rtl.c (revision c87b03e5)
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