OSDN Git Service

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