OSDN Git Service

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