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