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