source: trunk/third/gcc/rtl.c @ 8834

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