rtl.c revision 18334
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 */
852