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