OSDN Git Service

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