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