|
|
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"
1.1.1.4 ! root 25: #include "real.h"
1.1 root 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:
1.1.1.3 root 39: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
40: extern long atol();
41: #endif
1.1 root 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: /* Commonly used modes. */
126:
127: enum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT */
128: enum 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
1.1.1.2 root 132: each character describes one operand. */
1.1 root 133:
134: char *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'
1.1.1.3 root 142: "w" an integer of width HOST_BITS_PER_WIDE_INT
143: prints the integer
1.1 root 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:
165: char 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:
1.1.1.4 ! root 173: char *note_insn_name[] = { 0 , "NOTE_INSN_DELETED",
1.1 root 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",
1.1.1.3 root 177: "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
178: "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
1.1.1.4 ! root 179: "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG"};
1.1 root 180:
181: char *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:
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: 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:
212: rtx
213: rtx_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:
1.1.1.4 ! root 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:
1.1 root 245: PUT_CODE (rt, code);
246:
247: return rt;
248: }
249:
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:
254: rtx
255: copy_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:
1.1.1.4 ! root 275: case SCRATCH:
! 276: /* SCRATCH must be shared because they represent distinct values. */
1.1 root 277: return orig;
1.1.1.4 ! root 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. */
1.1 root 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:
1.1.1.3 root 313: case '0':
314: case 'u':
315: XEXP (copy, i) = XEXP (orig, i);
316: break;
317:
1.1 root 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:
1.1.1.3 root 329: case 'w':
330: XWINT (copy, i) = XWINT (orig, i);
331: break;
332:
333: case 'i':
1.1 root 334: XINT (copy, i) = XINT (orig, i);
335: break;
1.1.1.3 root 336:
337: case 's':
338: case 'S':
339: XSTR (copy, i) = XSTR (orig, i);
340: break;
341:
342: default:
343: abort ();
1.1 root 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:
352: rtx
353: copy_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:
1.1.1.3 root 399: case '0':
400: case 'u':
401: XEXP (copy, i) = XEXP (orig, i);
402: break;
403:
1.1 root 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:
1.1.1.3 root 416: case 'w':
417: XWINT (copy, i) = XWINT (orig, i);
418: break;
419:
420: case 'n':
421: case 'i':
1.1 root 422: XINT (copy, i) = XINT (orig, i);
423: break;
1.1.1.3 root 424:
425: case 's':
426: case 'S':
427: XSTR (copy, i) = XSTR (orig, i);
428: break;
429:
430: default:
431: abort ();
1.1 root 432: }
433: }
434: return copy;
435: }
436:
437: /* Subroutines of read_rtx. */
438:
439: /* Dump code after printing a message. Used when read_rtx finds
440: invalid data. */
441:
442: static void
443: dump_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:
470: int
471: read_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:
506: static void
507: read_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:
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:
544: rtx
545: read_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;
1.1.1.3 root 558: HOST_WIDE_INT tmp_wide;
1.1 root 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
1.1.1.3 root 671: ? rtvec_alloc (list_counter) : NULL_RTVEC);
1.1 root 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: {
1.1.1.2 root 711: c = getc (infile); /* Read the string */
712: if (c == '\\')
1.1 root 713: {
1.1.1.2 root 714: c = getc (infile); /* Read the string */
1.1 root 715: /* \; makes stuff for a C string constant containing
716: newline and tab. */
1.1.1.2 root 717: if (c == ';')
1.1 root 718: {
1.1.1.2 root 719: obstack_grow (rtl_obstack, "\\n\\t", 4);
720: continue;
1.1 root 721: }
722: }
1.1.1.2 root 723: else if (c == '"')
1.1 root 724: break;
1.1.1.2 root 725:
726: obstack_1grow (rtl_obstack, c);
1.1 root 727: }
728:
1.1.1.2 root 729: obstack_1grow (rtl_obstack, 0);
730: stringbuf = (char *) obstack_finish (rtl_obstack);
1.1 root 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:
1.1.1.3 root 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:
1.1 root 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:
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:
778: void
779: init_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
1.1.1.4 ! root 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++)
1.1.1.3 root 806: *s++ = 'w';
1.1 root 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:
1.1.1.2 root 828: byte_mode = VOIDmode;
829: word_mode = VOIDmode;
830:
1.1 root 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
1.1.1.2 root 840: && GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
841: && byte_mode == VOIDmode)
1.1 root 842: byte_mode = mode;
843:
844: if (GET_MODE_CLASS (mode) == MODE_INT
1.1.1.2 root 845: && GET_MODE_BITSIZE (mode) == BITS_PER_WORD
846: && word_mode == VOIDmode)
1.1 root 847: word_mode = mode;
848: }
849: }
1.1.1.2 root 850:
851: #ifdef memset
852: gcc_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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.