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