OSDN Git Service

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