OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / rtl.c
1 /* Allocate and read RTL for GNU C Compiler.
2    Copyright (C) 1987, 1988, 1991, 1994, 1997 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "real.h"
26 #include "bitmap.h"
27
28 #include "obstack.h"
29 #define obstack_chunk_alloc     xmalloc
30 #define obstack_chunk_free      free
31
32 /* Obstack used for allocating RTL objects.
33    Between functions, this is the permanent_obstack.
34    While parsing and expanding a function, this is maybepermanent_obstack
35    so we can save it if it is an inline function.
36    During optimization and output, this is function_obstack.  */
37
38 extern struct obstack *rtl_obstack;
39 \f
40 /* Indexed by rtx code, gives number of operands for an rtx with that code.
41    Does NOT include rtx header data (code and links).
42    This array is initialized in init_rtl.  */
43
44 int rtx_length[NUM_RTX_CODE + 1];
45
46 /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
47
48 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
49
50 char *rtx_name[] = {
51 #include "rtl.def"              /* rtl expressions are documented here */
52 };
53
54 #undef DEF_RTL_EXPR
55
56 /* Indexed by machine mode, gives the name of that machine mode.
57    This name does not include the letters "mode".  */
58
59 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  NAME,
60
61 char *mode_name[(int) MAX_MACHINE_MODE] = {
62 #include "machmode.def"
63
64 #ifdef EXTRA_CC_MODES
65   EXTRA_CC_NAMES
66 #endif
67
68 };
69
70 #undef DEF_MACHMODE
71
72 /* Indexed by machine mode, gives the length of the mode, in bytes.
73    GET_MODE_CLASS uses this.  */
74
75 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  CLASS,
76
77 enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
78 #include "machmode.def"
79 };
80
81 #undef DEF_MACHMODE
82
83 /* Indexed by machine mode, gives the length of the mode, in bytes.
84    GET_MODE_SIZE uses this.  */
85
86 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  SIZE,
87
88 int mode_size[(int) MAX_MACHINE_MODE] = {
89 #include "machmode.def"
90 };
91
92 #undef DEF_MACHMODE
93
94 /* Indexed by machine mode, gives the length of the mode's subunit.
95    GET_MODE_UNIT_SIZE uses this.  */
96
97 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  UNIT,
98
99 int mode_unit_size[(int) MAX_MACHINE_MODE] = {
100 #include "machmode.def"         /* machine modes are documented here */
101 };
102
103 #undef DEF_MACHMODE
104
105 /* Indexed by machine mode, gives next wider natural mode
106    (QI -> HI -> SI -> DI, etc.)  Widening multiply instructions
107    use this.  */
108
109 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
110   (enum machine_mode) WIDER,
111
112 enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
113 #include "machmode.def"         /* machine modes are documented here */
114 };
115
116 #undef DEF_MACHMODE
117
118 /* Indexed by mode class, gives the narrowest mode for each class.  */
119
120 enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
121
122 /* Indexed by rtx code, gives a sequence of operand-types for
123    rtx's of that code.  The sequence is a C string in which
124    each character describes one operand.  */
125
126 char *rtx_format[] = {
127   /* "*" undefined.
128          can cause a warning message
129      "0" field is unused (or used in a phase-dependent manner)
130          prints nothing
131      "i" an integer
132          prints the integer
133      "n" like "i", but prints entries from `note_insn_name'
134      "w" an integer of width HOST_BITS_PER_WIDE_INT
135          prints the integer
136      "s" a pointer to a string
137          prints the string
138      "S" like "s", but optional:
139          the containing rtx may end before this operand
140      "e" a pointer to an rtl expression
141          prints the expression
142      "E" a pointer to a vector that points to a number of rtl expressions
143          prints a list of the rtl expressions
144      "V" like "E", but optional:
145          the containing rtx may end before this operand
146      "u" a pointer to another insn
147          prints the uid of the insn.
148      "b" is a pointer to a bitmap header.
149      "t" is a tree pointer. */
150
151 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
152 #include "rtl.def"              /* rtl expressions are defined here */
153 #undef DEF_RTL_EXPR
154 };
155
156 /* Indexed by rtx code, gives a character representing the "class" of
157    that rtx code.  See rtl.def for documentation on the defined classes.  */
158
159 char rtx_class[] = {
160 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   CLASS, 
161 #include "rtl.def"              /* rtl expressions are defined here */
162 #undef DEF_RTL_EXPR
163 };
164
165 /* Names for kinds of NOTEs and REG_NOTEs.  */
166
167 char *note_insn_name[] = { 0                    , "NOTE_INSN_DELETED",
168                            "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
169                            "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
170                            "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
171                            "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
172                            "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
173                            "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
174                            "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
175                            "NOTE_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_START",
176                            "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE" };
177
178 char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
179                           "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
180                           "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
181                           "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
182                           "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
183                           "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
184                           "REG_BR_PRED", "REG_EH_CONTEXT",
185                           "REG_FRAME_RELATED_EXPR" };
186
187 static void dump_and_abort      PROTO((int, int, FILE *));
188 static void read_name           PROTO((char *, FILE *));
189 \f
190 /* Allocate an rtx vector of N elements.
191    Store the length, and initialize all elements to zero.  */
192
193 rtvec
194 rtvec_alloc (n)
195      int n;
196 {
197   rtvec rt;
198   int i;
199
200   rt = (rtvec) obstack_alloc (rtl_obstack,
201                               sizeof (struct rtvec_def)
202                               + (( n - 1) * sizeof (rtunion)));
203
204   /* clear out the vector */
205   PUT_NUM_ELEM (rt, n);
206
207   for (i = 0; i < n; i++)
208     rt->elem[i].rtwint = 0;
209
210   return rt;
211 }
212
213 /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
214    all the rest is initialized to zero.  */
215
216 rtx
217 rtx_alloc (code)
218   RTX_CODE code;
219 {
220   rtx rt;
221   register struct obstack *ob = rtl_obstack;
222   register int nelts = GET_RTX_LENGTH (code);
223   register int length = sizeof (struct rtx_def)
224     + (nelts - 1) * sizeof (rtunion);
225
226   /* This function is called more than any other in GCC,
227      so we manipulate the obstack directly.
228
229      Even though rtx objects are word aligned, we may be sharing an obstack
230      with tree nodes, which may have to be double-word aligned.  So align
231      our length to the alignment mask in the obstack.  */
232
233   length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
234
235   if (ob->chunk_limit - ob->next_free < length)
236     _obstack_newchunk (ob, length);
237   rt = (rtx)ob->object_base;
238   ob->next_free += length;
239   ob->object_base = ob->next_free;
240
241   /* We want to clear everything up to the FLD array.  Normally, this is
242      one int, but we don't want to assume that and it isn't very portable
243      anyway; this is.  */
244
245   length = (sizeof (struct rtx_def) - sizeof (rtunion) - 1) / sizeof (int);
246   for (; length >= 0; length--)
247     ((int *) rt)[length] = 0;
248
249   PUT_CODE (rt, code);
250
251   return rt;
252 }
253
254 /* Free the rtx X and all RTL allocated since X.  */
255
256 void
257 rtx_free (x)
258      rtx x;
259 {
260   obstack_free (rtl_obstack, x);
261 }
262 \f
263 /* Create a new copy of an rtx.
264    Recursively copies the operands of the rtx,
265    except for those few rtx codes that are sharable.  */
266
267 rtx
268 copy_rtx (orig)
269      register rtx orig;
270 {
271   register rtx copy;
272   register int i, j;
273   register RTX_CODE code;
274   register char *format_ptr;
275
276   code = GET_CODE (orig);
277
278   switch (code)
279     {
280     case REG:
281     case QUEUED:
282     case CONST_INT:
283     case CONST_DOUBLE:
284     case SYMBOL_REF:
285     case CODE_LABEL:
286     case PC:
287     case CC0:
288     case SCRATCH:
289       /* SCRATCH must be shared because they represent distinct values.  */
290     case ADDRESSOF:
291       return orig;
292
293     case CONST:
294       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
295          a LABEL_REF, it isn't sharable.  */
296       if (GET_CODE (XEXP (orig, 0)) == PLUS
297           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
298           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
299         return orig;
300       break;
301
302       /* A MEM with a constant address is not sharable.  The problem is that
303          the constant address may need to be reloaded.  If the mem is shared,
304          then reloading one copy of this mem will cause all copies to appear
305          to have been reloaded.  */
306
307     default:
308       break;
309     }
310
311   copy = rtx_alloc (code);
312   PUT_MODE (copy, GET_MODE (orig));
313   copy->in_struct = orig->in_struct;
314   copy->volatil = orig->volatil;
315   copy->unchanging = orig->unchanging;
316   copy->integrated = orig->integrated;
317   
318   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
319
320   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
321     {
322       switch (*format_ptr++)
323         {
324         case 'e':
325           XEXP (copy, i) = XEXP (orig, i);
326           if (XEXP (orig, i) != NULL)
327             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
328           break;
329
330         case '0':
331         case 'u':
332           XEXP (copy, i) = XEXP (orig, i);
333           break;
334
335         case 'E':
336         case 'V':
337           XVEC (copy, i) = XVEC (orig, i);
338           if (XVEC (orig, i) != NULL)
339             {
340               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
341               for (j = 0; j < XVECLEN (copy, i); j++)
342                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
343             }
344           break;
345
346         case 'b':
347           {
348             bitmap new_bits = BITMAP_OBSTACK_ALLOC (rtl_obstack);
349             bitmap_copy (new_bits, XBITMAP (orig, i));
350             XBITMAP (copy, i) = new_bits;
351             break;
352           }
353
354         case 't':
355           XTREE (copy, i) = XTREE (orig, i);
356           break;
357
358         case 'w':
359           XWINT (copy, i) = XWINT (orig, i);
360           break;
361
362         case 'i':
363           XINT (copy, i) = XINT (orig, i);
364           break;
365
366         case 's':
367         case 'S':
368           XSTR (copy, i) = XSTR (orig, i);
369           break;
370
371         default:
372           abort ();
373         }
374     }
375   return copy;
376 }
377
378 /* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
379    placed in the result directly, rather than being copied.  */
380
381 rtx
382 copy_most_rtx (orig, may_share)
383      register rtx orig;
384      register rtx may_share;
385 {
386   register rtx copy;
387   register int i, j;
388   register RTX_CODE code;
389   register char *format_ptr;
390
391   if (orig == may_share)
392     return orig;
393
394   code = GET_CODE (orig);
395
396   switch (code)
397     {
398     case REG:
399     case QUEUED:
400     case CONST_INT:
401     case CONST_DOUBLE:
402     case SYMBOL_REF:
403     case CODE_LABEL:
404     case PC:
405     case CC0:
406       return orig;
407     default:
408       break;
409     }
410
411   copy = rtx_alloc (code);
412   PUT_MODE (copy, GET_MODE (orig));
413   copy->in_struct = orig->in_struct;
414   copy->volatil = orig->volatil;
415   copy->unchanging = orig->unchanging;
416   copy->integrated = orig->integrated;
417   
418   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
419
420   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
421     {
422       switch (*format_ptr++)
423         {
424         case 'e':
425           XEXP (copy, i) = XEXP (orig, i);
426           if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
427             XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
428           break;
429
430         case '0':
431         case 'u':
432           XEXP (copy, i) = XEXP (orig, i);
433           break;
434
435         case 'E':
436         case 'V':
437           XVEC (copy, i) = XVEC (orig, i);
438           if (XVEC (orig, i) != NULL)
439             {
440               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
441               for (j = 0; j < XVECLEN (copy, i); j++)
442                 XVECEXP (copy, i, j)
443                   = copy_most_rtx (XVECEXP (orig, i, j), may_share);
444             }
445           break;
446
447         case 'w':
448           XWINT (copy, i) = XWINT (orig, i);
449           break;
450
451         case 'n':
452         case 'i':
453           XINT (copy, i) = XINT (orig, i);
454           break;
455
456         case 's':
457         case 'S':
458           XSTR (copy, i) = XSTR (orig, i);
459           break;
460
461         default:
462           abort ();
463         }
464     }
465   return copy;
466 }
467 \f
468 /* Subroutines of read_rtx.  */
469
470 /* Dump code after printing a message.  Used when read_rtx finds
471    invalid data.  */
472
473 static void
474 dump_and_abort (expected_c, actual_c, infile)
475      int expected_c, actual_c;
476      FILE *infile;
477 {
478   int c, i;
479
480   if (expected_c >= 0)
481     fprintf (stderr,
482              "Expected character %c.  Found character %c.",
483              expected_c, actual_c);
484   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
485   fprintf (stderr, "Following characters are:\n\t");
486   for (i = 0; i < 200; i++)
487     {
488       c = getc (infile);
489       if (EOF == c) break;
490       putc (c, stderr);
491     }
492   fprintf (stderr, "Aborting.\n");
493   abort ();
494 }
495
496 /* Read chars from INFILE until a non-whitespace char
497    and return that.  Comments, both Lisp style and C style,
498    are treated as whitespace.
499    Tools such as genflags use this function.  */
500
501 int
502 read_skip_spaces (infile)
503      FILE *infile;
504 {
505   register int c;
506   while ((c = getc (infile)))
507     {
508       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
509         ;
510       else if (c == ';')
511         {
512           while ((c = getc (infile)) && c != '\n' && c != EOF)
513             ;
514         }
515       else if (c == '/')
516         {
517           register int prevc;
518           c = getc (infile);
519           if (c != '*')
520             dump_and_abort ('*', c, infile);
521           
522           prevc = 0;
523           while ((c = getc (infile)) && c != EOF)
524             {
525               if (prevc == '*' && c == '/')
526                 break;
527               prevc = c;
528             }
529         }
530       else break;
531     }
532   return c;
533 }
534
535 /* Read an rtx code name into the buffer STR[].
536    It is terminated by any of the punctuation chars of rtx printed syntax.  */
537
538 static void
539 read_name (str, infile)
540      char *str;
541      FILE *infile;
542 {
543   register char *p;
544   register int c;
545
546   c = read_skip_spaces(infile);
547
548   p = str;
549   while (1)
550     {
551       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
552         break;
553       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
554           || c == '(' || c == '[')
555         {
556           ungetc (c, infile);
557           break;
558         }
559       *p++ = c;
560       c = getc (infile);
561     }
562   if (p == str)
563     {
564       fprintf (stderr, "missing name or number");
565       dump_and_abort (-1, -1, infile);
566     }
567
568   *p = 0;
569 }
570 \f
571 /* Provide a version of a function to read a long long if the system does
572    not provide one.  */
573 #if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !defined(HAVE_ATOLL) && !defined(HAVE_ATOQ)
574 HOST_WIDE_INT
575 atoll(p)
576     const char *p;
577 {
578   int neg = 0;
579   HOST_WIDE_INT tmp_wide;
580
581   while (ISSPACE(*p))
582     p++;
583   if (*p == '-')
584     neg = 1, p++;
585   else if (*p == '+')
586     p++;
587
588   tmp_wide = 0;
589   while (ISDIGIT(*p))
590     {
591       HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
592       if (new_wide < tmp_wide)
593         {
594           /* Return INT_MAX equiv on overflow.  */
595           tmp_wide = (~(unsigned HOST_WIDE_INT)0) >> 1;
596           break;
597         }
598       tmp_wide = new_wide;
599       p++;
600     }
601
602   if (neg)
603     tmp_wide = -tmp_wide;
604   return tmp_wide;
605 }
606 #endif
607
608 /* Read an rtx in printed representation from INFILE
609    and return an actual rtx in core constructed accordingly.
610    read_rtx is not used in the compiler proper, but rather in
611    the utilities gen*.c that construct C code from machine descriptions.  */
612
613 rtx
614 read_rtx (infile)
615      FILE *infile;
616 {
617   register int i, j, list_counter;
618   RTX_CODE tmp_code;
619   register char *format_ptr;
620   /* tmp_char is a buffer used for reading decimal integers
621      and names of rtx types and machine modes.
622      Therefore, 256 must be enough.  */
623   char tmp_char[256];
624   rtx return_rtx;
625   register int c;
626   int tmp_int;
627   HOST_WIDE_INT tmp_wide;
628
629   /* Linked list structure for making RTXs: */
630   struct rtx_list
631     {
632       struct rtx_list *next;
633       rtx value;                /* Value of this node...                */
634     };
635
636   c = read_skip_spaces (infile); /* Should be open paren.  */
637   if (c != '(')
638     dump_and_abort ('(', c, infile);
639
640   read_name (tmp_char, infile);
641
642   tmp_code = UNKNOWN;
643
644   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
645     {
646       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
647         {
648           tmp_code = (RTX_CODE) i;      /* get value for name */
649           break;
650         }
651     }
652   if (tmp_code == UNKNOWN)
653     {
654       fprintf (stderr,
655                "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
656                tmp_char);
657     }
658   /* (NIL) stands for an expression that isn't there.  */
659   if (tmp_code == NIL)
660     {
661       /* Discard the closeparen.  */
662       while ((c = getc (infile)) && c != ')');
663       return 0;
664     }
665
666   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
667                                        then we free this space below.  */
668   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
669
670   /* If what follows is `: mode ', read it and
671      store the mode in the rtx.  */
672
673   i = read_skip_spaces (infile);
674   if (i == ':')
675     {
676       register int k;
677       read_name (tmp_char, infile);
678       for (k = 0; k < NUM_MACHINE_MODES; k++)
679         if (!strcmp (GET_MODE_NAME (k), tmp_char))
680           break;
681
682       PUT_MODE (return_rtx, (enum machine_mode) k );
683     }
684   else
685     ungetc (i, infile);
686
687   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
688     switch (*format_ptr++)
689       {
690         /* 0 means a field for internal use only.
691            Don't expect it to be present in the input.  */
692       case '0':
693         break;
694
695       case 'e':
696       case 'u':
697         XEXP (return_rtx, i) = read_rtx (infile);
698         break;
699
700       case 'V':
701         /* 'V' is an optional vector: if a closeparen follows,
702            just store NULL for this element.  */
703         c = read_skip_spaces (infile);
704         ungetc (c, infile);
705         if (c == ')')
706           {
707             XVEC (return_rtx, i) = 0;
708             break;
709           }
710         /* Now process the vector.  */
711   
712       case 'E':
713         {
714           register struct rtx_list *next_rtx, *rtx_list_link;
715           struct rtx_list *list_rtx = NULL;
716
717           c = read_skip_spaces (infile);
718           if (c != '[')
719             dump_and_abort ('[', c, infile);
720
721           /* add expressions to a list, while keeping a count */
722           next_rtx = NULL;
723           list_counter = 0;
724           while ((c = read_skip_spaces (infile)) && c != ']')
725             {
726               ungetc (c, infile);
727               list_counter++;
728               rtx_list_link = (struct rtx_list *)
729                 alloca (sizeof (struct rtx_list));
730               rtx_list_link->value = read_rtx (infile);
731               if (next_rtx == 0)
732                 list_rtx = rtx_list_link;
733               else
734                 next_rtx->next = rtx_list_link;
735               next_rtx = rtx_list_link;
736               rtx_list_link->next = 0;
737             }
738           /* get vector length and allocate it */
739           XVEC (return_rtx, i) = (list_counter
740                                   ? rtvec_alloc (list_counter) : NULL_RTVEC);
741           if (list_counter > 0)
742             {
743               next_rtx = list_rtx;
744               for (j = 0; j < list_counter; j++,
745                    next_rtx = next_rtx->next)
746                 XVECEXP (return_rtx, i, j) = next_rtx->value;
747             }
748           /* close bracket gotten */
749         }
750         break;
751
752       case 'S':
753         /* 'S' is an optional string: if a closeparen follows,
754            just store NULL for this element.  */
755         c = read_skip_spaces (infile);
756         ungetc (c, infile);
757         if (c == ')')
758           {
759             XSTR (return_rtx, i) = 0;
760             break;
761           }
762
763       case 's':
764         {
765           int saw_paren = 0;
766           register char *stringbuf;
767
768           c = read_skip_spaces (infile);
769           if (c == '(')
770             {
771               saw_paren = 1;
772               c = read_skip_spaces (infile);
773             }
774           if (c != '"')
775             dump_and_abort ('"', c, infile);
776
777           while (1)
778             {
779               c = getc (infile); /* Read the string  */
780               if (c == '\\')
781                 {
782                   c = getc (infile);    /* Read the string  */
783                   /* \; makes stuff for a C string constant containing
784                      newline and tab.  */
785                   if (c == ';')
786                     {
787                       obstack_grow (rtl_obstack, "\\n\\t", 4);
788                       continue;
789                     }
790                 }
791               else if (c == '"')
792                 break;
793
794               obstack_1grow (rtl_obstack, c);
795             }
796
797           obstack_1grow (rtl_obstack, 0);
798           stringbuf = (char *) obstack_finish (rtl_obstack);
799
800           if (saw_paren)
801             {
802               c = read_skip_spaces (infile);
803               if (c != ')')
804                 dump_and_abort (')', c, infile);
805             }
806           XSTR (return_rtx, i) = stringbuf;
807         }
808         break;
809
810       case 'w':
811         read_name (tmp_char, infile);
812 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
813         tmp_wide = atoi (tmp_char);
814 #else
815 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
816         tmp_wide = atol (tmp_char);
817 #else
818         /* Prefer atoll over atoq, since the former is in the ISO C9X draft. 
819            But prefer not to use our hand-rolled function above either.  */
820 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
821         tmp_wide = atoll (tmp_char);
822 #else
823         tmp_wide = atoq (tmp_char);
824 #endif
825 #endif
826 #endif
827         XWINT (return_rtx, i) = tmp_wide;
828         break;
829
830       case 'i':
831       case 'n':
832         read_name (tmp_char, infile);
833         tmp_int = atoi (tmp_char);
834         XINT (return_rtx, i) = tmp_int;
835         break;
836
837       default:
838         fprintf (stderr,
839                  "switch format wrong in rtl.read_rtx(). format was: %c.\n",
840                  format_ptr[-1]);
841         fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
842         abort ();
843       }
844
845   c = read_skip_spaces (infile);
846   if (c != ')')
847     dump_and_abort (')', c, infile);
848
849   return return_rtx;
850 }
851 \f
852 /* This is called once per compilation, before any rtx's are constructed.
853    It initializes the vector `rtx_length', the extra CC modes, if any,
854    and computes certain commonly-used modes.  */
855
856 void
857 init_rtl ()
858 {
859   int min_class_size[(int) MAX_MODE_CLASS];
860   enum machine_mode mode;
861   int i;
862
863   for (i = 0; i < NUM_RTX_CODE; i++)
864     rtx_length[i] = strlen (rtx_format[i]);
865
866   /* Make CONST_DOUBLE bigger, if real values are bigger than
867      it normally expects to have room for.
868      Note that REAL_VALUE_TYPE is not defined by default,
869      since tree.h is not included.  But the default dfn as `double'
870      would do no harm.  */
871 #ifdef REAL_VALUE_TYPE
872   i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
873   if (rtx_length[(int) CONST_DOUBLE] < i)
874     {
875       char *s = (char *) xmalloc (i + 1);
876       rtx_length[(int) CONST_DOUBLE] = i;
877       rtx_format[(int) CONST_DOUBLE] = s;
878       *s++ = 'e';
879       *s++ = '0';
880       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
881          of as many `w's as we now have elements.  Subtract two from
882          the size to account for the 'e' and the '0'.  */
883       for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
884         *s++ = 'w';
885       *s++ = 0;
886     }
887 #endif
888
889 #ifdef EXTRA_CC_MODES
890   for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
891     {
892       mode_class[i] = MODE_CC;
893       mode_size[i] = mode_size[(int) CCmode];
894       mode_unit_size[i] = mode_unit_size[(int) CCmode];
895       mode_wider_mode[i - 1] = (enum machine_mode) i;
896       mode_wider_mode[i] = VOIDmode;
897     }
898 #endif
899
900   /* Find the narrowest mode for each class.  */
901
902   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
903     min_class_size[i] = 1000;
904
905   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
906        mode = (enum machine_mode) ((int) mode + 1))
907     {
908       if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
909         {
910           class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
911           min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
912         }
913     }
914 }