OSDN Git Service

Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
[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 #include "rtl.h"
26 #include "real.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
40 #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
41 extern long atol();
42 #endif
43 \f
44 /* Indexed by rtx code, gives number of operands for an rtx with that code.
45    Does NOT include rtx header data (code and links).
46    This array is initialized in init_rtl.  */
47
48 int rtx_length[NUM_RTX_CODE + 1];
49
50 /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
51
52 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
53
54 char *rtx_name[] = {
55 #include "rtl.def"              /* rtl expressions are documented here */
56 };
57
58 #undef DEF_RTL_EXPR
59
60 /* Indexed by machine mode, gives the name of that machine mode.
61    This name does not include the letters "mode".  */
62
63 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  NAME,
64
65 char *mode_name[(int) MAX_MACHINE_MODE] = {
66 #include "machmode.def"
67
68 #ifdef EXTRA_CC_MODES
69   EXTRA_CC_NAMES
70 #endif
71
72 };
73
74 #undef DEF_MACHMODE
75
76 /* Indexed by machine mode, gives the length of the mode, in bytes.
77    GET_MODE_CLASS uses this.  */
78
79 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  CLASS,
80
81 enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
82 #include "machmode.def"
83 };
84
85 #undef DEF_MACHMODE
86
87 /* Indexed by machine mode, gives the length of the mode, in bytes.
88    GET_MODE_SIZE uses this.  */
89
90 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  SIZE,
91
92 int mode_size[(int) MAX_MACHINE_MODE] = {
93 #include "machmode.def"
94 };
95
96 #undef DEF_MACHMODE
97
98 /* Indexed by machine mode, gives the length of the mode's subunit.
99    GET_MODE_UNIT_SIZE uses this.  */
100
101 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  UNIT,
102
103 int mode_unit_size[(int) MAX_MACHINE_MODE] = {
104 #include "machmode.def"         /* machine modes are documented here */
105 };
106
107 #undef DEF_MACHMODE
108
109 /* Indexed by machine mode, gives next wider natural mode
110    (QI -> HI -> SI -> DI, etc.)  Widening multiply instructions
111    use this.  */
112
113 #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
114   (enum machine_mode) WIDER,
115
116 enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
117 #include "machmode.def"         /* machine modes are documented here */
118 };
119
120 #undef DEF_MACHMODE
121
122 /* Indexed by mode class, gives the narrowest mode for each class.  */
123
124 enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
125
126 /* Indexed by rtx code, gives a sequence of operand-types for
127    rtx's of that code.  The sequence is a C string in which
128    each character describes one operand.  */
129
130 char *rtx_format[] = {
131   /* "*" undefined.
132          can cause a warning message
133      "0" field is unused (or used in a phase-dependent manner)
134          prints nothing
135      "i" an integer
136          prints the integer
137      "n" like "i", but prints entries from `note_insn_name'
138      "w" an integer of width HOST_BITS_PER_WIDE_INT
139          prints the integer
140      "s" a pointer to a string
141          prints the string
142      "S" like "s", but optional:
143          the containing rtx may end before this operand
144      "e" a pointer to an rtl expression
145          prints the expression
146      "E" a pointer to a vector that points to a number of rtl expressions
147          prints a list of the rtl expressions
148      "V" like "E", but optional:
149          the containing rtx may end before this operand
150      "u" a pointer to another insn
151          prints the uid of the insn.  */
152
153 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
154 #include "rtl.def"              /* rtl expressions are defined here */
155 #undef DEF_RTL_EXPR
156 };
157
158 /* Indexed by rtx code, gives a character representing the "class" of
159    that rtx code.  See rtl.def for documentation on the defined classes.  */
160
161 char rtx_class[] = {
162 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   CLASS, 
163 #include "rtl.def"              /* rtl expressions are defined here */
164 #undef DEF_RTL_EXPR
165 };
166
167 /* Names for kinds of NOTEs and REG_NOTEs.  */
168
169 char *note_insn_name[] = { 0                    , "NOTE_INSN_DELETED",
170                            "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
171                            "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
172                            "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
173                            "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
174                            "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
175                            "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
176                            "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
177                            "NOTE_REPEATED_LINE_NUMBER" };
178
179 char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
180                           "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
181                           "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
182                           "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
183                           "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
184                           "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
185                           "REG_BR_PRED", "REG_EH_CONTEXT" };
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 'w':
347           XWINT (copy, i) = XWINT (orig, i);
348           break;
349
350         case 'i':
351           XINT (copy, i) = XINT (orig, i);
352           break;
353
354         case 's':
355         case 'S':
356           XSTR (copy, i) = XSTR (orig, i);
357           break;
358
359         default:
360           abort ();
361         }
362     }
363   return copy;
364 }
365
366 /* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
367    placed in the result directly, rather than being copied.  */
368
369 rtx
370 copy_most_rtx (orig, may_share)
371      register rtx orig;
372      register rtx may_share;
373 {
374   register rtx copy;
375   register int i, j;
376   register RTX_CODE code;
377   register char *format_ptr;
378
379   if (orig == may_share)
380     return orig;
381
382   code = GET_CODE (orig);
383
384   switch (code)
385     {
386     case REG:
387     case QUEUED:
388     case CONST_INT:
389     case CONST_DOUBLE:
390     case SYMBOL_REF:
391     case CODE_LABEL:
392     case PC:
393     case CC0:
394       return orig;
395     default:
396       break;
397     }
398
399   copy = rtx_alloc (code);
400   PUT_MODE (copy, GET_MODE (orig));
401   copy->in_struct = orig->in_struct;
402   copy->volatil = orig->volatil;
403   copy->unchanging = orig->unchanging;
404   copy->integrated = orig->integrated;
405   
406   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
407
408   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
409     {
410       switch (*format_ptr++)
411         {
412         case 'e':
413           XEXP (copy, i) = XEXP (orig, i);
414           if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
415             XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
416           break;
417
418         case '0':
419         case 'u':
420           XEXP (copy, i) = XEXP (orig, i);
421           break;
422
423         case 'E':
424         case 'V':
425           XVEC (copy, i) = XVEC (orig, i);
426           if (XVEC (orig, i) != NULL)
427             {
428               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
429               for (j = 0; j < XVECLEN (copy, i); j++)
430                 XVECEXP (copy, i, j)
431                   = copy_most_rtx (XVECEXP (orig, i, j), may_share);
432             }
433           break;
434
435         case 'w':
436           XWINT (copy, i) = XWINT (orig, i);
437           break;
438
439         case 'n':
440         case 'i':
441           XINT (copy, i) = XINT (orig, i);
442           break;
443
444         case 's':
445         case 'S':
446           XSTR (copy, i) = XSTR (orig, i);
447           break;
448
449         default:
450           abort ();
451         }
452     }
453   return copy;
454 }
455 \f
456 /* Subroutines of read_rtx.  */
457
458 /* Dump code after printing a message.  Used when read_rtx finds
459    invalid data.  */
460
461 static void
462 dump_and_abort (expected_c, actual_c, infile)
463      int expected_c, actual_c;
464      FILE *infile;
465 {
466   int c, i;
467
468   if (expected_c >= 0)
469     fprintf (stderr,
470              "Expected character %c.  Found character %c.",
471              expected_c, actual_c);
472   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
473   fprintf (stderr, "Following characters are:\n\t");
474   for (i = 0; i < 200; i++)
475     {
476       c = getc (infile);
477       if (EOF == c) break;
478       putc (c, stderr);
479     }
480   fprintf (stderr, "Aborting.\n");
481   abort ();
482 }
483
484 /* Read chars from INFILE until a non-whitespace char
485    and return that.  Comments, both Lisp style and C style,
486    are treated as whitespace.
487    Tools such as genflags use this function.  */
488
489 int
490 read_skip_spaces (infile)
491      FILE *infile;
492 {
493   register int c;
494   while (c = getc (infile))
495     {
496       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
497         ;
498       else if (c == ';')
499         {
500           while ((c = getc (infile)) && c != '\n') ;
501         }
502       else if (c == '/')
503         {
504           register int prevc;
505           c = getc (infile);
506           if (c != '*')
507             dump_and_abort ('*', c, infile);
508           
509           prevc = 0;
510           while (c = getc (infile))
511             {
512               if (prevc == '*' && c == '/')
513                 break;
514               prevc = c;
515             }
516         }
517       else break;
518     }
519   return c;
520 }
521
522 /* Read an rtx code name into the buffer STR[].
523    It is terminated by any of the punctuation chars of rtx printed syntax.  */
524
525 static void
526 read_name (str, infile)
527      char *str;
528      FILE *infile;
529 {
530   register char *p;
531   register int c;
532
533   c = read_skip_spaces(infile);
534
535   p = str;
536   while (1)
537     {
538       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
539         break;
540       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
541           || c == '(' || c == '[')
542         {
543           ungetc (c, infile);
544           break;
545         }
546       *p++ = c;
547       c = getc (infile);
548     }
549   if (p == str)
550     {
551       fprintf (stderr, "missing name or number");
552       dump_and_abort (-1, -1, infile);
553     }
554
555   *p = 0;
556 }
557 \f
558 /* Read an rtx in printed representation from INFILE
559    and return an actual rtx in core constructed accordingly.
560    read_rtx is not used in the compiler proper, but rather in
561    the utilities gen*.c that construct C code from machine descriptions.  */
562
563 rtx
564 read_rtx (infile)
565      FILE *infile;
566 {
567   register int i, j, list_counter;
568   RTX_CODE tmp_code;
569   register char *format_ptr;
570   /* tmp_char is a buffer used for reading decimal integers
571      and names of rtx types and machine modes.
572      Therefore, 256 must be enough.  */
573   char tmp_char[256];
574   rtx return_rtx;
575   register int c;
576   int tmp_int;
577   HOST_WIDE_INT tmp_wide;
578
579   /* Linked list structure for making RTXs: */
580   struct rtx_list
581     {
582       struct rtx_list *next;
583       rtx value;                /* Value of this node...                */
584     };
585
586   c = read_skip_spaces (infile); /* Should be open paren.  */
587   if (c != '(')
588     dump_and_abort ('(', c, infile);
589
590   read_name (tmp_char, infile);
591
592   tmp_code = UNKNOWN;
593
594   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
595     {
596       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
597         {
598           tmp_code = (RTX_CODE) i;      /* get value for name */
599           break;
600         }
601     }
602   if (tmp_code == UNKNOWN)
603     {
604       fprintf (stderr,
605                "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
606                tmp_char);
607     }
608   /* (NIL) stands for an expression that isn't there.  */
609   if (tmp_code == NIL)
610     {
611       /* Discard the closeparen.  */
612       while ((c = getc (infile)) && c != ')');
613       return 0;
614     }
615
616   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
617                                        then we free this space below.  */
618   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
619
620   /* If what follows is `: mode ', read it and
621      store the mode in the rtx.  */
622
623   i = read_skip_spaces (infile);
624   if (i == ':')
625     {
626       register int k;
627       read_name (tmp_char, infile);
628       for (k = 0; k < NUM_MACHINE_MODES; k++)
629         if (!strcmp (GET_MODE_NAME (k), tmp_char))
630           break;
631
632       PUT_MODE (return_rtx, (enum machine_mode) k );
633     }
634   else
635     ungetc (i, infile);
636
637   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
638     switch (*format_ptr++)
639       {
640         /* 0 means a field for internal use only.
641            Don't expect it to be present in the input.  */
642       case '0':
643         break;
644
645       case 'e':
646       case 'u':
647         XEXP (return_rtx, i) = read_rtx (infile);
648         break;
649
650       case 'V':
651         /* 'V' is an optional vector: if a closeparen follows,
652            just store NULL for this element.  */
653         c = read_skip_spaces (infile);
654         ungetc (c, infile);
655         if (c == ')')
656           {
657             XVEC (return_rtx, i) = 0;
658             break;
659           }
660         /* Now process the vector.  */
661   
662       case 'E':
663         {
664           register struct rtx_list *next_rtx, *rtx_list_link;
665           struct rtx_list *list_rtx;
666
667           c = read_skip_spaces (infile);
668           if (c != '[')
669             dump_and_abort ('[', c, infile);
670
671           /* add expressions to a list, while keeping a count */
672           next_rtx = NULL;
673           list_counter = 0;
674           while ((c = read_skip_spaces (infile)) && c != ']')
675             {
676               ungetc (c, infile);
677               list_counter++;
678               rtx_list_link = (struct rtx_list *)
679                 alloca (sizeof (struct rtx_list));
680               rtx_list_link->value = read_rtx (infile);
681               if (next_rtx == 0)
682                 list_rtx = rtx_list_link;
683               else
684                 next_rtx->next = rtx_list_link;
685               next_rtx = rtx_list_link;
686               rtx_list_link->next = 0;
687             }
688           /* get vector length and allocate it */
689           XVEC (return_rtx, i) = (list_counter
690                                   ? rtvec_alloc (list_counter) : NULL_RTVEC);
691           if (list_counter > 0)
692             {
693               next_rtx = list_rtx;
694               for (j = 0; j < list_counter; j++,
695                    next_rtx = next_rtx->next)
696                 XVECEXP (return_rtx, i, j) = next_rtx->value;
697             }
698           /* close bracket gotten */
699         }
700         break;
701
702       case 'S':
703         /* 'S' is an optional string: if a closeparen follows,
704            just store NULL for this element.  */
705         c = read_skip_spaces (infile);
706         ungetc (c, infile);
707         if (c == ')')
708           {
709             XSTR (return_rtx, i) = 0;
710             break;
711           }
712
713       case 's':
714         {
715           int saw_paren = 0;
716           register char *stringbuf;
717
718           c = read_skip_spaces (infile);
719           if (c == '(')
720             {
721               saw_paren = 1;
722               c = read_skip_spaces (infile);
723             }
724           if (c != '"')
725             dump_and_abort ('"', c, infile);
726
727           while (1)
728             {
729               c = getc (infile); /* Read the string  */
730               if (c == '\\')
731                 {
732                   c = getc (infile);    /* Read the string  */
733                   /* \; makes stuff for a C string constant containing
734                      newline and tab.  */
735                   if (c == ';')
736                     {
737                       obstack_grow (rtl_obstack, "\\n\\t", 4);
738                       continue;
739                     }
740                 }
741               else if (c == '"')
742                 break;
743
744               obstack_1grow (rtl_obstack, c);
745             }
746
747           obstack_1grow (rtl_obstack, 0);
748           stringbuf = (char *) obstack_finish (rtl_obstack);
749
750           if (saw_paren)
751             {
752               c = read_skip_spaces (infile);
753               if (c != ')')
754                 dump_and_abort (')', c, infile);
755             }
756           XSTR (return_rtx, i) = stringbuf;
757         }
758         break;
759
760       case 'w':
761         read_name (tmp_char, infile);
762 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
763         tmp_wide = atoi (tmp_char);
764 #else
765         tmp_wide = atol (tmp_char);
766 #endif
767         XWINT (return_rtx, i) = tmp_wide;
768         break;
769
770       case 'i':
771       case 'n':
772         read_name (tmp_char, infile);
773         tmp_int = atoi (tmp_char);
774         XINT (return_rtx, i) = tmp_int;
775         break;
776
777       default:
778         fprintf (stderr,
779                  "switch format wrong in rtl.read_rtx(). format was: %c.\n",
780                  format_ptr[-1]);
781         fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
782         abort ();
783       }
784
785   c = read_skip_spaces (infile);
786   if (c != ')')
787     dump_and_abort (')', c, infile);
788
789   return return_rtx;
790 }
791 \f
792 /* This is called once per compilation, before any rtx's are constructed.
793    It initializes the vector `rtx_length', the extra CC modes, if any,
794    and computes certain commonly-used modes.  */
795
796 void
797 init_rtl ()
798 {
799   int min_class_size[(int) MAX_MODE_CLASS];
800   enum machine_mode mode;
801   int i;
802
803   for (i = 0; i < NUM_RTX_CODE; i++)
804     rtx_length[i] = strlen (rtx_format[i]);
805
806   /* Make CONST_DOUBLE bigger, if real values are bigger than
807      it normally expects to have room for.
808      Note that REAL_VALUE_TYPE is not defined by default,
809      since tree.h is not included.  But the default dfn as `double'
810      would do no harm.  */
811 #ifdef REAL_VALUE_TYPE
812   i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
813   if (rtx_length[(int) CONST_DOUBLE] < i)
814     {
815       char *s = (char *) xmalloc (i + 1);
816       rtx_length[(int) CONST_DOUBLE] = i;
817       rtx_format[(int) CONST_DOUBLE] = s;
818       *s++ = 'e';
819       *s++ = '0';
820       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
821          of as many `w's as we now have elements.  Subtract two from
822          the size to account for the 'e' and the '0'.  */
823       for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
824         *s++ = 'w';
825       *s++ = 0;
826     }
827 #endif
828
829 #ifdef EXTRA_CC_MODES
830   for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
831     {
832       mode_class[i] = MODE_CC;
833       mode_size[i] = mode_size[(int) CCmode];
834       mode_unit_size[i] = mode_unit_size[(int) CCmode];
835       mode_wider_mode[i - 1] = (enum machine_mode) i;
836       mode_wider_mode[i] = VOIDmode;
837     }
838 #endif
839
840   /* Find the narrowest mode for each class.  */
841
842   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
843     min_class_size[i] = 1000;
844
845   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
846        mode = (enum machine_mode) ((int) mode + 1))
847     {
848       if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
849         {
850           class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
851           min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
852         }
853     }
854 }