OSDN Git Service

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