OSDN Git Service

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