OSDN Git Service

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