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