OSDN Git Service

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