OSDN Git Service

Initial revision
[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" };
186
187 /* Allocate an rtx vector of N elements.
188    Store the length, and initialize all elements to zero.  */
189
190 rtvec
191 rtvec_alloc (n)
192      int n;
193 {
194   rtvec rt;
195   int i;
196
197   rt = (rtvec) obstack_alloc (rtl_obstack,
198                               sizeof (struct rtvec_def)
199                               + (( n - 1) * sizeof (rtunion)));
200
201   /* clear out the vector */
202   PUT_NUM_ELEM (rt, n);
203
204   for (i = 0; i < n; i++)
205     rt->elem[i].rtwint = 0;
206
207   return rt;
208 }
209
210 /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
211    all the rest is initialized to zero.  */
212
213 rtx
214 rtx_alloc (code)
215   RTX_CODE code;
216 {
217   rtx rt;
218   register struct obstack *ob = rtl_obstack;
219   register int nelts = GET_RTX_LENGTH (code);
220   register int length = sizeof (struct rtx_def)
221     + (nelts - 1) * sizeof (rtunion);
222
223   /* This function is called more than any other in GCC,
224      so we manipulate the obstack directly.
225
226      Even though rtx objects are word aligned, we may be sharing an obstack
227      with tree nodes, which may have to be double-word aligned.  So align
228      our length to the alignment mask in the obstack.  */
229
230   length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
231
232   if (ob->chunk_limit - ob->next_free < length)
233     _obstack_newchunk (ob, length);
234   rt = (rtx)ob->object_base;
235   ob->next_free += length;
236   ob->object_base = ob->next_free;
237
238   /* We want to clear everything up to the FLD array.  Normally, this is
239      one int, but we don't want to assume that and it isn't very portable
240      anyway; this is.  */
241
242   length = (sizeof (struct rtx_def) - sizeof (rtunion) - 1) / sizeof (int);
243   for (; length >= 0; length--)
244     ((int *) rt)[length] = 0;
245
246   PUT_CODE (rt, code);
247
248   return rt;
249 }
250
251 /* Free the rtx X and all RTL allocated since X.  */
252
253 void
254 rtx_free (x)
255      rtx x;
256 {
257   obstack_free (rtl_obstack, x);
258 }
259 \f
260 /* Create a new copy of an rtx.
261    Recursively copies the operands of the rtx,
262    except for those few rtx codes that are sharable.  */
263
264 rtx
265 copy_rtx (orig)
266      register rtx orig;
267 {
268   register rtx copy;
269   register int i, j;
270   register RTX_CODE code;
271   register char *format_ptr;
272
273   code = GET_CODE (orig);
274
275   switch (code)
276     {
277     case REG:
278     case QUEUED:
279     case CONST_INT:
280     case CONST_DOUBLE:
281     case SYMBOL_REF:
282     case CODE_LABEL:
283     case PC:
284     case CC0:
285     case SCRATCH:
286       /* SCRATCH must be shared because they represent distinct values.  */
287       return orig;
288
289     case CONST:
290       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
291          a LABEL_REF, it isn't sharable.  */
292       if (GET_CODE (XEXP (orig, 0)) == PLUS
293           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
294           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
295         return orig;
296       break;
297
298       /* A MEM with a constant address is not sharable.  The problem is that
299          the constant address may need to be reloaded.  If the mem is shared,
300          then reloading one copy of this mem will cause all copies to appear
301          to have been reloaded.  */
302     }
303
304   copy = rtx_alloc (code);
305   PUT_MODE (copy, GET_MODE (orig));
306   copy->in_struct = orig->in_struct;
307   copy->volatil = orig->volatil;
308   copy->unchanging = orig->unchanging;
309   copy->integrated = orig->integrated;
310   
311   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
312
313   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
314     {
315       switch (*format_ptr++)
316         {
317         case 'e':
318           XEXP (copy, i) = XEXP (orig, i);
319           if (XEXP (orig, i) != NULL)
320             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
321           break;
322
323         case '0':
324         case 'u':
325           XEXP (copy, i) = XEXP (orig, i);
326           break;
327
328         case 'E':
329         case 'V':
330           XVEC (copy, i) = XVEC (orig, i);
331           if (XVEC (orig, i) != NULL)
332             {
333               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
334               for (j = 0; j < XVECLEN (copy, i); j++)
335                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
336             }
337           break;
338
339         case 'w':
340           XWINT (copy, i) = XWINT (orig, i);
341           break;
342
343         case 'i':
344           XINT (copy, i) = XINT (orig, i);
345           break;
346
347         case 's':
348         case 'S':
349           XSTR (copy, i) = XSTR (orig, i);
350           break;
351
352         default:
353           abort ();
354         }
355     }
356   return copy;
357 }
358
359 /* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
360    placed in the result directly, rather than being copied.  */
361
362 rtx
363 copy_most_rtx (orig, may_share)
364      register rtx orig;
365      register rtx may_share;
366 {
367   register rtx copy;
368   register int i, j;
369   register RTX_CODE code;
370   register char *format_ptr;
371
372   if (orig == may_share)
373     return orig;
374
375   code = GET_CODE (orig);
376
377   switch (code)
378     {
379     case REG:
380     case QUEUED:
381     case CONST_INT:
382     case CONST_DOUBLE:
383     case SYMBOL_REF:
384     case CODE_LABEL:
385     case PC:
386     case CC0:
387       return orig;
388     }
389
390   copy = rtx_alloc (code);
391   PUT_MODE (copy, GET_MODE (orig));
392   copy->in_struct = orig->in_struct;
393   copy->volatil = orig->volatil;
394   copy->unchanging = orig->unchanging;
395   copy->integrated = orig->integrated;
396   
397   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
398
399   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
400     {
401       switch (*format_ptr++)
402         {
403         case 'e':
404           XEXP (copy, i) = XEXP (orig, i);
405           if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
406             XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
407           break;
408
409         case '0':
410         case 'u':
411           XEXP (copy, i) = XEXP (orig, i);
412           break;
413
414         case 'E':
415         case 'V':
416           XVEC (copy, i) = XVEC (orig, i);
417           if (XVEC (orig, i) != NULL)
418             {
419               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
420               for (j = 0; j < XVECLEN (copy, i); j++)
421                 XVECEXP (copy, i, j)
422                   = copy_most_rtx (XVECEXP (orig, i, j), may_share);
423             }
424           break;
425
426         case 'w':
427           XWINT (copy, i) = XWINT (orig, i);
428           break;
429
430         case 'n':
431         case 'i':
432           XINT (copy, i) = XINT (orig, i);
433           break;
434
435         case 's':
436         case 'S':
437           XSTR (copy, i) = XSTR (orig, i);
438           break;
439
440         default:
441           abort ();
442         }
443     }
444   return copy;
445 }
446 \f
447 /* Subroutines of read_rtx.  */
448
449 /* Dump code after printing a message.  Used when read_rtx finds
450    invalid data.  */
451
452 static void
453 dump_and_abort (expected_c, actual_c, infile)
454      int expected_c, actual_c;
455      FILE *infile;
456 {
457   int c, i;
458
459   if (expected_c >= 0)
460     fprintf (stderr,
461              "Expected character %c.  Found character %c.",
462              expected_c, actual_c);
463   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
464   fprintf (stderr, "Following characters are:\n\t");
465   for (i = 0; i < 200; i++)
466     {
467       c = getc (infile);
468       if (EOF == c) break;
469       putc (c, stderr);
470     }
471   fprintf (stderr, "Aborting.\n");
472   abort ();
473 }
474
475 /* Read chars from INFILE until a non-whitespace char
476    and return that.  Comments, both Lisp style and C style,
477    are treated as whitespace.
478    Tools such as genflags use this function.  */
479
480 int
481 read_skip_spaces (infile)
482      FILE *infile;
483 {
484   register int c;
485   while (c = getc (infile))
486     {
487       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
488         ;
489       else if (c == ';')
490         {
491           while ((c = getc (infile)) && c != '\n') ;
492         }
493       else if (c == '/')
494         {
495           register int prevc;
496           c = getc (infile);
497           if (c != '*')
498             dump_and_abort ('*', c, infile);
499           
500           prevc = 0;
501           while (c = getc (infile))
502             {
503               if (prevc == '*' && c == '/')
504                 break;
505               prevc = c;
506             }
507         }
508       else break;
509     }
510   return c;
511 }
512
513 /* Read an rtx code name into the buffer STR[].
514    It is terminated by any of the punctuation chars of rtx printed syntax.  */
515
516 static void
517 read_name (str, infile)
518      char *str;
519      FILE *infile;
520 {
521   register char *p;
522   register int c;
523
524   c = read_skip_spaces(infile);
525
526   p = str;
527   while (1)
528     {
529       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
530         break;
531       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
532           || c == '(' || c == '[')
533         {
534           ungetc (c, infile);
535           break;
536         }
537       *p++ = c;
538       c = getc (infile);
539     }
540   if (p == str)
541     {
542       fprintf (stderr, "missing name or number");
543       dump_and_abort (-1, -1, infile);
544     }
545
546   *p = 0;
547 }
548 \f
549 /* Read an rtx in printed representation from INFILE
550    and return an actual rtx in core constructed accordingly.
551    read_rtx is not used in the compiler proper, but rather in
552    the utilities gen*.c that construct C code from machine descriptions.  */
553
554 rtx
555 read_rtx (infile)
556      FILE *infile;
557 {
558   register int i, j, list_counter;
559   RTX_CODE tmp_code;
560   register char *format_ptr;
561   /* tmp_char is a buffer used for reading decimal integers
562      and names of rtx types and machine modes.
563      Therefore, 256 must be enough.  */
564   char tmp_char[256];
565   rtx return_rtx;
566   register int c;
567   int tmp_int;
568   HOST_WIDE_INT tmp_wide;
569
570   /* Linked list structure for making RTXs: */
571   struct rtx_list
572     {
573       struct rtx_list *next;
574       rtx value;                /* Value of this node...                */
575     };
576
577   c = read_skip_spaces (infile); /* Should be open paren.  */
578   if (c != '(')
579     dump_and_abort ('(', c, infile);
580
581   read_name (tmp_char, infile);
582
583   tmp_code = UNKNOWN;
584
585   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
586     {
587       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
588         {
589           tmp_code = (RTX_CODE) i;      /* get value for name */
590           break;
591         }
592     }
593   if (tmp_code == UNKNOWN)
594     {
595       fprintf (stderr,
596                "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
597                tmp_char);
598     }
599   /* (NIL) stands for an expression that isn't there.  */
600   if (tmp_code == NIL)
601     {
602       /* Discard the closeparen.  */
603       while ((c = getc (infile)) && c != ')');
604       return 0;
605     }
606
607   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
608                                        then we free this space below.  */
609   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
610
611   /* If what follows is `: mode ', read it and
612      store the mode in the rtx.  */
613
614   i = read_skip_spaces (infile);
615   if (i == ':')
616     {
617       register int k;
618       read_name (tmp_char, infile);
619       for (k = 0; k < NUM_MACHINE_MODES; k++)
620         if (!strcmp (GET_MODE_NAME (k), tmp_char))
621           break;
622
623       PUT_MODE (return_rtx, (enum machine_mode) k );
624     }
625   else
626     ungetc (i, infile);
627
628   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
629     switch (*format_ptr++)
630       {
631         /* 0 means a field for internal use only.
632            Don't expect it to be present in the input.  */
633       case '0':
634         break;
635
636       case 'e':
637       case 'u':
638         XEXP (return_rtx, i) = read_rtx (infile);
639         break;
640
641       case 'V':
642         /* 'V' is an optional vector: if a closeparen follows,
643            just store NULL for this element.  */
644         c = read_skip_spaces (infile);
645         ungetc (c, infile);
646         if (c == ')')
647           {
648             XVEC (return_rtx, i) = 0;
649             break;
650           }
651         /* Now process the vector.  */
652   
653       case 'E':
654         {
655           register struct rtx_list *next_rtx, *rtx_list_link;
656           struct rtx_list *list_rtx;
657
658           c = read_skip_spaces (infile);
659           if (c != '[')
660             dump_and_abort ('[', c, infile);
661
662           /* add expressions to a list, while keeping a count */
663           next_rtx = NULL;
664           list_counter = 0;
665           while ((c = read_skip_spaces (infile)) && c != ']')
666             {
667               ungetc (c, infile);
668               list_counter++;
669               rtx_list_link = (struct rtx_list *)
670                 alloca (sizeof (struct rtx_list));
671               rtx_list_link->value = read_rtx (infile);
672               if (next_rtx == 0)
673                 list_rtx = rtx_list_link;
674               else
675                 next_rtx->next = rtx_list_link;
676               next_rtx = rtx_list_link;
677               rtx_list_link->next = 0;
678             }
679           /* get vector length and allocate it */
680           XVEC (return_rtx, i) = (list_counter
681                                   ? rtvec_alloc (list_counter) : NULL_RTVEC);
682           if (list_counter > 0)
683             {
684               next_rtx = list_rtx;
685               for (j = 0; j < list_counter; j++,
686                    next_rtx = next_rtx->next)
687                 XVECEXP (return_rtx, i, j) = next_rtx->value;
688             }
689           /* close bracket gotten */
690         }
691         break;
692
693       case 'S':
694         /* 'S' is an optional string: if a closeparen follows,
695            just store NULL for this element.  */
696         c = read_skip_spaces (infile);
697         ungetc (c, infile);
698         if (c == ')')
699           {
700             XSTR (return_rtx, i) = 0;
701             break;
702           }
703
704       case 's':
705         {
706           int saw_paren = 0;
707           register char *stringbuf;
708
709           c = read_skip_spaces (infile);
710           if (c == '(')
711             {
712               saw_paren = 1;
713               c = read_skip_spaces (infile);
714             }
715           if (c != '"')
716             dump_and_abort ('"', c, infile);
717
718           while (1)
719             {
720               c = getc (infile); /* Read the string  */
721               if (c == '\\')
722                 {
723                   c = getc (infile);    /* Read the string  */
724                   /* \; makes stuff for a C string constant containing
725                      newline and tab.  */
726                   if (c == ';')
727                     {
728                       obstack_grow (rtl_obstack, "\\n\\t", 4);
729                       continue;
730                     }
731                 }
732               else if (c == '"')
733                 break;
734
735               obstack_1grow (rtl_obstack, c);
736             }
737
738           obstack_1grow (rtl_obstack, 0);
739           stringbuf = (char *) obstack_finish (rtl_obstack);
740
741           if (saw_paren)
742             {
743               c = read_skip_spaces (infile);
744               if (c != ')')
745                 dump_and_abort (')', c, infile);
746             }
747           XSTR (return_rtx, i) = stringbuf;
748         }
749         break;
750
751       case 'w':
752         read_name (tmp_char, infile);
753 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
754         tmp_wide = atoi (tmp_char);
755 #else
756         tmp_wide = atol (tmp_char);
757 #endif
758         XWINT (return_rtx, i) = tmp_wide;
759         break;
760
761       case 'i':
762       case 'n':
763         read_name (tmp_char, infile);
764         tmp_int = atoi (tmp_char);
765         XINT (return_rtx, i) = tmp_int;
766         break;
767
768       default:
769         fprintf (stderr,
770                  "switch format wrong in rtl.read_rtx(). format was: %c.\n",
771                  format_ptr[-1]);
772         fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
773         abort ();
774       }
775
776   c = read_skip_spaces (infile);
777   if (c != ')')
778     dump_and_abort (')', c, infile);
779
780   return return_rtx;
781 }
782 \f
783 /* This is called once per compilation, before any rtx's are constructed.
784    It initializes the vector `rtx_length', the extra CC modes, if any,
785    and computes certain commonly-used modes.  */
786
787 void
788 init_rtl ()
789 {
790   int min_class_size[(int) MAX_MODE_CLASS];
791   enum machine_mode mode;
792   int i;
793
794   for (i = 0; i < NUM_RTX_CODE; i++)
795     rtx_length[i] = strlen (rtx_format[i]);
796
797   /* Make CONST_DOUBLE bigger, if real values are bigger than
798      it normally expects to have room for.
799      Note that REAL_VALUE_TYPE is not defined by default,
800      since tree.h is not included.  But the default dfn as `double'
801      would do no harm.  */
802 #ifdef REAL_VALUE_TYPE
803   i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
804   if (rtx_length[(int) CONST_DOUBLE] < i)
805     {
806       char *s = (char *) xmalloc (i + 1);
807       rtx_length[(int) CONST_DOUBLE] = i;
808       rtx_format[(int) CONST_DOUBLE] = s;
809       *s++ = 'e';
810       *s++ = '0';
811       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
812          of as many `w's as we now have elements.  Subtract two from
813          the size to account for the 'e' and the '0'.  */
814       for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
815         *s++ = 'w';
816       *s++ = 0;
817     }
818 #endif
819
820 #ifdef EXTRA_CC_MODES
821   for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
822     {
823       mode_class[i] = MODE_CC;
824       mode_size[i] = mode_size[(int) CCmode];
825       mode_unit_size[i] = mode_unit_size[(int) CCmode];
826       mode_wider_mode[i - 1] = (enum machine_mode) i;
827       mode_wider_mode[i] = VOIDmode;
828     }
829 #endif
830
831   /* Find the narrowest mode for each class.  */
832
833   for (i = 0; i < (int) MAX_MODE_CLASS; i++)
834     min_class_size[i] = 1000;
835
836   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
837        mode = (enum machine_mode) ((int) mode + 1))
838     {
839       if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
840         {
841           class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
842           min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
843         }
844     }
845 }
846 \f
847 #ifdef memset
848 gcc_memset (dest, value, len)
849      char *dest;
850      int value;
851      int len;
852 {
853   while (len-- > 0)
854     *dest++ = value;
855 }
856 #endif /* memset */