|
|
1.1 root 1: /* Manage RTL for C-Compiler
2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This file contains the low level primitives for allocating,
23: printing and reading rtl expressions and vectors.
24: It also contains some functions for semantic analysis
25: on rtl expressions. */
26:
27: #include "config.h"
28: #include <ctype.h>
29: #include <stdio.h>
30: #include "rtl.h"
31:
32: #include "obstack.h"
33: #define obstack_chunk_alloc xmalloc
34: #define obstack_chunk_free free
35: extern int xmalloc ();
36: extern void free ();
37:
38: /* Obstack used for allocating RTL objects.
39: Between functions, this is the permanent_obstack.
40: While parsing and expanding a function, this is maybepermanent_obstack
41: so we can save it if it is an inline function.
42: During optimization and output, this is temporary_obstack. */
43:
44: extern struct obstack *rtl_obstack;
45:
46: #define MIN(x,y) ((x < y) ? x : y)
47:
48: extern long ftell();
49:
50: /* Indexed by rtx code, gives number of operands for an rtx with that code.
51: Does NOT include rtx header data (code and links).
52: This array is initialized in init_rtx. */
53:
54: int rtx_length[NUM_RTX_CODE + 1];
55:
56: /* Indexed by rtx code, gives the name of that kind of rtx, as a C string. */
57:
58: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT) NAME ,
59:
60: char *rtx_name[] = {
61: #include "rtl.def" /* rtl expressions are documented here */
62: };
63:
64: #undef DEF_RTL_EXPR
65:
66: /* Indexed by machine mode, gives the name of that machine mode.
67: This name does not include the letters "mode". */
68:
69: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT) NAME,
70:
71: char *mode_name[] = {
72: #include "machmode.def"
73: };
74:
75: #undef DEF_MACHMODE
76:
77: /* Indexed by machine mode, gives the length of the mode, in bytes.
78: GET_MODE_CLASS uses this. */
79:
80: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT) CLASS,
81:
82: enum mode_class mode_class[] = {
83: #include "machmode.def"
84: };
85:
86: #undef DEF_MACHMODE
87:
88: /* Indexed by machine mode, gives the length of the mode, in bytes.
89: GET_MODE_SIZE uses this. */
90:
91: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT) SIZE,
92:
93: int mode_size[] = {
94: #include "machmode.def"
95: };
96:
97: #undef DEF_MACHMODE
98:
99: /* Indexed by machine mode, gives the length of the mode's subunit.
100: GET_MODE_UNIT_SIZE uses this. */
101:
102: #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT) UNIT,
103:
104: int mode_unit_size[] = {
105: #include "machmode.def" /* machine modes are documented here */
106: };
107:
108: #undef DEF_MACHMODE
109:
110: /* Indexed by rtx code, gives a sequence of operand-types for
111: rtx's of that code. The sequence is a C string in which
112: each charcter describes one operand. */
113:
114: char *rtx_format[] = {
115: /* "*" undefined.
116: can cause a warning message
117: "0" field is unused (or used in a phase-dependent manner)
118: prints nothing
119: "i" an integer
120: prints the integer
121: "s" a pointer to a string
122: prints the string
123: "e" a pointer to an rtl expression
124: prints the expression
125: "E" a pointer to a vector that points to a number of rtl expressions
126: prints a list of the rtl expressions
127: "u" a pointer to another insn
128: prints the uid of the insn. */
129:
130: #define DEF_RTL_EXPR(ENUM, NAME, FORMAT) FORMAT ,
131: #include "rtl.def" /* rtl expressions are defined here */
132: #undef DEF_RTL_EXPR
133: };
134:
135: /* Allocate an rtx vector of N elements.
136: Store the length, and initialize all elements to zero. */
137:
138: rtvec
139: rtvec_alloc (n)
140: int n;
141: {
142: rtvec rt;
143: int i;
144:
145: rt = (rtvec) obstack_alloc (rtl_obstack,
146: sizeof (struct rtvec_def)
147: + (( n - 1) * sizeof (rtunion)));
148:
149: /* clear out the vector */
150: PUT_NUM_ELEM(rt, n);
151: for (i=0; i < n; i++)
152: rt->elem[i].rtvec = NULL; /* @@ not portable due to rtunion */
153:
154: return rt;
155: }
156:
157: /* Allocate an rtx of code CODE. The CODE is stored in the rtx;
158: all the rest is initialized to zero. */
159:
160: rtx
161: rtx_alloc (code)
162: RTX_CODE code;
163: {
164: rtx rt;
165: register int nelts = GET_RTX_LENGTH (code);
166: register int length = sizeof (struct rtx_def)
167: + (nelts - 1) * sizeof (rtunion);
168:
169: rt = (rtx) obstack_alloc (rtl_obstack, length);
170:
171: * (int *) rt = 0;
172: PUT_CODE (rt, code);
173:
174: return rt;
175: }
176:
177: /* Create a new copy of an rtx.
178: Recursively copies the operands of the rtx,
179: except for those few rtx codes that are sharable. */
180:
181: rtx
182: copy_rtx (orig)
183: register rtx orig;
184: {
185: register rtx copy;
186: register int i, j;
187: register RTX_CODE code;
188: register char *format_ptr;
189:
190: code = GET_CODE (orig);
191:
192: switch (code)
193: {
194: case REG:
195: case QUEUED:
196: case CONST_INT:
197: case CONST_DOUBLE:
198: case SYMBOL_REF:
199: case CODE_LABEL:
200: case PC:
201: case CC0:
202: return orig;
203: }
204:
205: copy = rtx_alloc (code);
206: PUT_MODE (copy, GET_MODE (orig));
207: copy->in_struct = orig->in_struct;
208: copy->volatil = orig->volatil;
209: copy->unchanging = orig->unchanging;
210: copy->integrated = orig->integrated;
211:
212: format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
213:
214: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
215: {
216: switch (*format_ptr++)
217: {
218: case 'e':
219: XEXP (copy, i) = copy_rtx (XEXP (orig, i));
220: break;
221:
222: case 'E':
223: XVEC (copy, i) = XVEC (orig, i);
224: if (XVEC (orig, i) != NULL)
225: {
226: XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
227: for (j = 0; j < XVECLEN (copy, i); j++)
228: XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
229: }
230: break;
231:
232: default:
233: XINT (copy, i) = XINT (orig, i);
234: break;
235: }
236: }
237: return copy;
238: }
239:
240: /* Return 1 if the value of X is unstable
241: (would be different at a different point in the program).
242: The frame pointer, arg pointer, etc. are considered stable
243: (within one function) and so is anything marked `unchanging'. */
244:
245: int
246: rtx_unstable_p (x)
247: rtx x;
248: {
249: register RTX_CODE code = GET_CODE (x);
250: register int i;
251: register char *fmt;
252:
253: if (code == MEM)
254: return ! x->unchanging;
255:
256: if (code == QUEUED)
257: return 1;
258:
259: if (code == CONST || code == CONST_INT)
260: return 0;
261:
262: if (code == REG)
263: return ! (REGNO (x) == FRAME_POINTER_REGNUM
264: || REGNO (x) == ARG_POINTER_REGNUM
265: || x->unchanging);
266:
267: fmt = GET_RTX_FORMAT (code);
268: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
269: if (fmt[i] == 'e')
270: if (rtx_unstable_p (XEXP (x, i)))
271: return 1;
272: return 0;
273: }
274:
275: /* Return 1 if X has a value that can vary even between two
276: executions of the program. 0 means X can be compared reliably
277: against certain constants or near-constants.
278: The frame pointer and the arg pointer are considered constant. */
279:
280: int
281: rtx_varies_p (x)
282: rtx x;
283: {
284: register RTX_CODE code = GET_CODE (x);
285: register int i;
286: register char *fmt;
287:
288: if (code == MEM)
289: return 1;
290:
291: if (code == QUEUED)
292: return 1;
293:
294: if (code == CONST || code == CONST_INT)
295: return 0;
296:
297: if (code == REG)
298: return ! (REGNO (x) == FRAME_POINTER_REGNUM
299: || REGNO (x) == ARG_POINTER_REGNUM);
300:
301: fmt = GET_RTX_FORMAT (code);
302: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
303: if (fmt[i] == 'e')
304: if (rtx_varies_p (XEXP (x, i)))
305: return 1;
306: return 0;
307: }
308:
309: /* Return 1 if X refers to a memory location whose address
310: cannot be compared reliably with constant addresses,
311: or if X refers to a BLKmode memory object. */
312:
313: int
314: rtx_addr_varies_p (x)
315: rtx x;
316: {
317: register RTX_CODE code = GET_CODE (x);
318: register int i;
319: register char *fmt;
320:
321: if (code == MEM)
322: return GET_MODE (x) == BLKmode || rtx_varies_p (XEXP (x, 0));
323:
324: fmt = GET_RTX_FORMAT (code);
325: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
326: if (fmt[i] == 'e')
327: if (rtx_addr_varies_p (XEXP (x, i)))
328: return 1;
329: return 0;
330: }
331:
332: /* Nonzero if register REG appears somewhere within IN.
333: Also works if REG is not a register; in this case it checks
334: for a subexpression of IN that is Lisp "equal" to REG. */
335:
336: int
337: reg_mentioned_p (reg, in)
338: register rtx reg, in;
339: {
340: register char *fmt;
341: register int i;
342: register enum rtx_code code;
343:
344: if (in == 0)
345: return 0;
346:
347: if (reg == in)
348: return 1;
349:
350: code = GET_CODE (in);
351:
352: switch (code)
353: {
354: /* Compare registers by number. */
355: case REG:
356: return GET_CODE (reg) == REG && REGNO (in) == REGNO (reg);
357:
358: /* These codes have no constituent expressions
359: and are unique. */
360: case CC0:
361: case PC:
362: case CONST_INT:
363: case CONST:
364: case CONST_DOUBLE:
365: case LABEL_REF:
366: case SYMBOL_REF:
367: return 0;
368: }
369:
370: if (GET_CODE (reg) == code && rtx_equal_p (reg, in))
371: return 1;
372:
373: fmt = GET_RTX_FORMAT (code);
374:
375: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
376: {
377: if (fmt[i] == 'E')
378: {
379: register int j;
380: for (j = XVECLEN (in, i) - 1; j >= 0; j--)
381: if (reg_mentioned_p (reg, XVECEXP (in, i, j)))
382: return 1;
383: }
384: else if (fmt[i] == 'e'
385: && reg_mentioned_p (reg, XEXP (in, i)))
386: return 1;
387: }
388: return 0;
389: }
390:
391: /* Nonzero if register REG is used in an insn between
392: FROM_INSN and TO_INSN (exclusive of those two). */
393:
394: int
395: reg_used_between_p (reg, from_insn, to_insn)
396: rtx reg, from_insn, to_insn;
397: {
398: register rtx insn;
399: register RTX_CODE code;
400: for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
401: if (((code = GET_CODE (insn)) == INSN
402: || code == JUMP_INSN || code == CALL_INSN)
403: && reg_mentioned_p (reg, PATTERN (insn)))
404: return 1;
405: return 0;
406: }
407:
408: /* Return 1 if X and Y are identical-looking rtx's.
409: This is the Lisp function EQUAL for rtx arguments. */
410:
411: int
412: rtx_equal_p (x, y)
413: rtx x, y;
414: {
415: register int i;
416: register int hash = 0;
417: register RTX_CODE code = GET_CODE (x);
418: register char *fmt;
419:
420: if (x == y)
421: return 1;
422:
423: /* Rtx's of different codes cannot be equal. */
424: if (code != GET_CODE (y))
425: return 0;
426:
427: /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
428: (REG:SI x) and (REG:HI x) are NOT equivalent. */
429:
430: if (GET_MODE (x) != GET_MODE (y))
431: return 0;
432:
433: /* These three types of rtx's can be compared nonrecursively. */
434: if (code == REG)
435: return (REGNO (x) == REGNO (y));
436: if (code == LABEL_REF)
437: return XEXP (x, 0) == XEXP (y, 0);
438: if (code == SYMBOL_REF)
439: return XSTR (x, 0) == XSTR (y, 0);
440:
441: /* Compare the elements. If any pair of corresponding elements
442: fail to match, return 0 for the whole things. */
443:
444: fmt = GET_RTX_FORMAT (code);
445: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
446: {
447: switch (fmt[i])
448: {
449: case 'i':
450: if (XINT (x, i) != XINT (y, i))
451: return 0;
452: break;
453:
454: case 'e':
455: if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
456: return 0;
457: break;
458:
459: case 's':
460: if (strcmp (XSTR (x, i), XSTR (y, i)))
461: return 0;
462: break;
463:
464: case '0':
465: break;
466:
467: /* It is believed that rtx's at this level will never
468: contain anything but integers and other rtx's,
469: except for within LABEL_REFs and SYMBOL_REFs. */
470: default:
471: abort ();
472: }
473: }
474: return 1;
475: }
476:
477: /* Call FUN on each register or MEM that is stored into or clobbered by X.
478: (X would be the pattern of an insn).
479: FUN receives two arguments:
480: the REG, MEM, CC0 or PC being stored in or clobbered,
481: the SET or CLOBBER rtx that does the store. */
482:
483: void
484: note_stores (x, fun)
485: register rtx x;
486: void (*fun) ();
487: {
488: if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
489: {
490: register rtx dest = SET_DEST (x);
491: while (GET_CODE (dest) == SUBREG
492: || GET_CODE (dest) == ZERO_EXTRACT
493: || GET_CODE (dest) == SIGN_EXTRACT
494: || GET_CODE (dest) == STRICT_LOW_PART)
495: dest = XEXP (dest, 0);
496: (*fun) (dest, GET_CODE (x) == CLOBBER);
497: }
498: else if (GET_CODE (x) == PARALLEL)
499: {
500: register int i;
501: for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
502: {
503: register rtx y = XVECEXP (x, 0, i);
504: if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
505: {
506: register rtx dest = SET_DEST (y);
507: while (GET_CODE (dest) == SUBREG
508: || GET_CODE (dest) == ZERO_EXTRACT
509: || GET_CODE (dest) == SIGN_EXTRACT
510: || GET_CODE (dest) == STRICT_LOW_PART)
511: dest = XEXP (dest, 0);
512: (*fun) (dest, GET_CODE (y) == CLOBBER);
513: }
514: }
515: }
516: }
517:
518: /* Return nonzero if register REG's old contents don't survive after INSN.
519: This can be because REG dies in INSN or because INSN entirely sets REG.
520:
521: "Entirely set" means set directly and not through a SUBREG,
522: ZERO_EXTRACT or SIGN_EXTRACT, so no trace of the old contents remains.
523:
524: REG may be a hard or pseudo reg. Renumbering is not taken into account,
525: but for this use that makes no difference, since regs don't overlap
526: during their lifetimes. Therefore, this function may be used
527: at any time after deaths have been computed (in flow.c). */
528:
529: int
530: dead_or_set_p (insn, reg)
531: rtx insn;
532: rtx reg;
533: {
534: register rtx link;
535: register int regno = REGNO (reg);
536:
537: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
538: if ((REG_NOTE_KIND (link) == REG_DEAD
539: || REG_NOTE_KIND (link) == REG_INC)
540: && REGNO (XEXP (link, 0)) == regno)
541: return 1;
542:
543: if (GET_CODE (PATTERN (insn)) == SET)
544: return SET_DEST (PATTERN (insn)) == reg;
545: else if (GET_CODE (PATTERN (insn)) == PARALLEL)
546: {
547: register int i;
548: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
549: {
550: if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
551: && SET_DEST (XVECEXP (PATTERN (insn), 0, i)) == reg)
552: return 1;
553: }
554: }
555: return 0;
556: }
557:
558: /* Return the reg-note of kind KIND in insn INSN, if there is one.
559: If DATUM is nonzero, look for one whose datum is DATUM. */
560:
561: rtx
562: find_reg_note (insn, kind, datum)
563: rtx insn;
564: enum reg_note kind;
565: rtx datum;
566: {
567: register rtx link;
568:
569: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
570: if (REG_NOTE_KIND (link) == kind
571: && (datum == 0 || datum == XEXP (link, 0)))
572: return link;
573: return 0;
574: }
575:
576: /* Return the reg-note of kind KIND in insn INSN which applies to register
577: number REGNO, if any. Return 0 if there is no such reg-note. */
578:
579: rtx
580: find_regno_note (insn, kind, regno)
581: rtx insn;
582: enum reg_note kind;
583: int regno;
584: {
585: register rtx link;
586:
587: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
588: if (REG_NOTE_KIND (link) == kind
589: && REGNO (XEXP (link, 0)) == regno)
590: return link;
591: return 0;
592: }
593:
594: /* Printing rtl for debugging dumps. */
595:
596: static FILE *outfile;
597:
598: char spaces[] = " ";
599:
600: static int sawclose = 0;
601:
602: /* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */
603:
604: static void
605: print_rtx (in_rtx)
606: register rtx in_rtx;
607: {
608: static int indent;
609: register int i, j;
610: register char *format_ptr;
611:
612: if (sawclose)
613: {
614: fprintf (outfile, "\n%s",
615: (spaces + (sizeof spaces - indent * 2)));
616: sawclose = 0;
617: }
618:
619: if (in_rtx == 0)
620: {
621: fprintf (outfile, "(nil)");
622: sawclose = 1;
623: return;
624: }
625:
626: /* print name of expression code */
627: fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
628:
629: if (in_rtx->in_struct)
630: fprintf (outfile, "/s");
631:
632: if (in_rtx->volatil)
633: fprintf (outfile, "/v");
634:
635: if (in_rtx->unchanging)
636: fprintf (outfile, "/u");
637:
638: if (in_rtx->integrated)
639: fprintf (outfile, "/i");
640:
641: if (GET_MODE (in_rtx) != VOIDmode)
642: fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
643:
644: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
645:
646: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
647: switch (*format_ptr++)
648: {
649: case 's':
650: if (XSTR (in_rtx, i) == 0)
651: fprintf (outfile, " \"\"");
652: else
653: fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));
654: sawclose = 1;
655: break;
656:
657: /* 0 indicates a field for internal use that should not be printed. */
658: case '0':
659: break;
660:
661: case 'e':
662: indent += 2;
663: if (!sawclose)
664: fprintf (outfile, " ");
665: print_rtx (XEXP (in_rtx, i));
666: indent -= 2;
667: break;
668:
669: case 'E':
670: indent += 2;
671: if (sawclose)
672: {
673: fprintf (outfile, "\n%s",
674: (spaces + (sizeof spaces - indent * 2)));
675: sawclose = 0;
676: }
677: fprintf (outfile, "[ ");
678: if (NULL != XVEC (in_rtx, i))
679: {
680: indent += 2;
681: if (XVECLEN (in_rtx, i))
682: sawclose = 1;
683:
684: for (j = 0; j < XVECLEN (in_rtx, i); j++)
685: print_rtx (XVECEXP (in_rtx, i, j));
686:
687: indent -= 2;
688: }
689: if (sawclose)
690: fprintf (outfile, "\n%s",
691: (spaces + (sizeof spaces - indent * 2)));
692:
693: fprintf (outfile, "] ");
694: sawclose = 1;
695: indent -= 2;
696: break;
697:
698: case 'i':
699: fprintf (outfile, " %d", XINT (in_rtx, i));
700: sawclose = 0;
701: break;
702:
703: case 'u':
704: if (XEXP (in_rtx, i) != NULL)
705: fprintf(outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
706: else
707: fprintf(outfile, " 0");
708: sawclose = 0;
709: break;
710:
711: default:
712: fprintf (stderr,
713: "switch format wrong in rtl.print_rtx(). format was: %c.\n",
714: format_ptr[-1]);
715: abort ();
716: }
717:
718: fprintf (outfile, ")");
719: sawclose = 1;
720: }
721:
722: /* Call this function from the debugger to see what X looks like. */
723:
724: void
725: debug_rtx (x)
726: rtx x;
727: {
728: outfile = stderr;
729: print_rtx (x);
730: fprintf (stderr, "\n");
731: }
732:
733: /* External entry point for printing a chain of INSNs
734: starting with RTX_FIRST onto file OUTF. */
735:
736: void
737: print_rtl (outf, rtx_first)
738: FILE *outf;
739: rtx rtx_first;
740: {
741: register rtx tmp_rtx;
742:
743: outfile = outf;
744: sawclose = 0;
745:
746: for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
747: {
748: print_rtx (tmp_rtx);
749: fprintf (outfile, "\n");
750: }
751: }
752:
753: /* Subroutines of read_rtx. */
754:
755: /* Dump code after printing a message. Used when read_rtx finds
756: invalid data. */
757:
758: static void
759: dump_and_abort (expected_c, actual_c, infile)
760: int expected_c, actual_c;
761: FILE *infile;
762: {
763: int c, i;
764:
765: fprintf (stderr,
766: "Expected character %c. Read character %c. At file position: %ld\n",
767: expected_c, actual_c, ftell (infile));
768: fprintf (stderr, "Following characters are:\n\t");
769: for (i = 0; i < 200; i++)
770: {
771: c = getc (infile);
772: if (EOF == c) break;
773: putc (c, stderr);
774: }
775: fprintf (stderr, "Aborting.\n");
776: abort ();
777: }
778:
779: /* Read chars from INFILE until a non-whitespace char
780: and return that. Comments, both Lisp style and C style,
781: are treated as whitespace.
782: Tools such as genflags use this function. */
783:
784: int
785: read_skip_spaces (infile)
786: FILE *infile;
787: {
788: register int c;
789: while (c = getc (infile))
790: {
791: if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
792: ;
793: else if (c == ';')
794: {
795: while ((c = getc (infile)) && c != '\n') ;
796: }
797: else if (c == '/')
798: {
799: register int prevc;
800: c = getc (infile);
801: if (c != '*')
802: dump_and_abort ('*', c, infile);
803:
804: prevc = 0;
805: while (c = getc (infile))
806: {
807: if (prevc == '*' && c == '/')
808: break;
809: prevc = c;
810: }
811: }
812: else break;
813: }
814: return c;
815: }
816:
817: /* Read an rtx code name into the buffer STR[].
818: It is terminated by any of the punctuation chars of rtx printed syntax. */
819:
820: static void
821: read_name (str, infile)
822: char *str;
823: FILE *infile;
824: {
825: register char *p;
826: register int c;
827:
828: c = read_skip_spaces(infile);
829:
830: p = str;
831: while (1)
832: {
833: if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
834: break;
835: if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
836: || c == '(' || c == '[')
837: {
838: ungetc (c, infile);
839: break;
840: }
841: *p++ = c;
842: c = getc (infile);
843: }
844: *p = NULL;
845: }
846:
847: /* Read an rtx in printed representation from INFILE
848: and return an actual rtx in core constructed accordingly.
849: read_rtx is not used in the compiler proper, but rather in
850: the utilities gen*.c that construct C code from machine descriptions. */
851:
852: rtx
853: read_rtx (infile)
854: FILE *infile;
855: {
856: register int i, j, list_counter;
857: RTX_CODE tmp_code;
858: register char *format_ptr;
859: /* tmp_char is a buffer used for reading decimal integers
860: and names of rtx types and machine modes.
861: Therefore, 256 must be enough. */
862: char tmp_char[256];
863: rtx return_rtx;
864: register int c;
865: int tmp_int;
866:
867: /* Linked list structure for making RTXs: */
868: struct rtx_list
869: {
870: struct rtx_list *next;
871: rtx value; /* Value of this node... */
872: };
873:
874: c = read_skip_spaces (infile); /* Should be open paren. */
875: if (c != '(')
876: dump_and_abort ('(', c, infile);
877:
878: read_name (tmp_char, infile);
879:
880: tmp_code = UNKNOWN;
881:
882: for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
883: {
884: if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
885: {
886: tmp_code = (RTX_CODE) i; /* get value for name */
887: break;
888: }
889: }
890: if (tmp_code == UNKNOWN)
891: {
892: fprintf (stderr,
893: "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
894: tmp_char);
895: }
896: /* (NIL) stands for an expression that isn't there. */
897: if (tmp_code == NIL)
898: {
899: /* Discard the closeparen. */
900: while ((c = getc (infile)) && c != ')');
901: return 0;
902: }
903:
904: return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
905: then we free this space below. */
906: format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
907:
908: /* If what follows is `: mode ', read it and
909: store the mode in the rtx. */
910:
911: i = read_skip_spaces (infile);
912: if (i == ':')
913: {
914: register int k;
915: read_name (tmp_char, infile);
916: for (k = 0; k < NUM_MACHINE_MODES; k++)
917: if (!strcmp (GET_MODE_NAME (k), tmp_char))
918: break;
919:
920: PUT_MODE (return_rtx, (enum machine_mode) k );
921: }
922: else
923: ungetc (i, infile);
924:
925: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
926: switch (*format_ptr++)
927: {
928: /* 0 means a field for internal use only.
929: Don't expect it to be present in the input. */
930: case '0':
931: break;
932:
933: case 'e':
934: case 'u':
935: XEXP (return_rtx, i) = read_rtx (infile);
936: break;
937:
938: case 'E':
939: {
940: register struct rtx_list *next_rtx, *rtx_list_link;
941: struct rtx_list *list_rtx;
942:
943: c = read_skip_spaces (infile);
944: if (c != '[')
945: dump_and_abort ('[', c, infile);
946:
947: /* add expressions to a list, while keeping a count */
948: next_rtx = NULL;
949: list_counter = 0;
950: while ((c = read_skip_spaces (infile)) && c != ']')
951: {
952: ungetc (c, infile);
953: list_counter++;
954: rtx_list_link = (struct rtx_list *)
955: alloca (sizeof (struct rtx_list));
956: rtx_list_link->value = read_rtx (infile);
957: if (next_rtx == 0)
958: list_rtx = rtx_list_link;
959: else
960: next_rtx->next = rtx_list_link;
961: next_rtx = rtx_list_link;
962: rtx_list_link->next = 0;
963: }
964: /* get vector length and allocate it */
965: XVEC (return_rtx, i) = (list_counter
966: ? rtvec_alloc (list_counter)
967: : NULL);
968: if (list_counter > 0)
969: {
970: next_rtx = list_rtx;
971: for (j = 0; j < list_counter; j++,
972: next_rtx = next_rtx->next)
973: XVECEXP (return_rtx, i, j) = next_rtx->value;
974: }
975: /* close bracket gotten */
976: }
977: break;
978:
979: case 's':
980: {
981: int saw_paren = 0;
982: register char *stringbuf;
983: int stringbufsize;
984:
985: c = read_skip_spaces (infile);
986: if (c == '(')
987: {
988: saw_paren = 1;
989: c = read_skip_spaces (infile);
990: }
991: if (c != '"')
992: dump_and_abort ('"', c, infile);
993: j = 0;
994: stringbufsize = 10;
995: stringbuf = (char *) xmalloc (stringbufsize + 1);
996:
997: while (1)
998: {
999: if (j >= stringbufsize - 4)
1000: {
1001: stringbufsize *= 2;
1002: stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
1003: }
1004: stringbuf[j] = getc (infile); /* Read the string */
1005: if (stringbuf[j] == '\\')
1006: {
1007: stringbuf[j] = getc (infile); /* Read the string */
1008: /* \; makes stuff for a C string constant containing
1009: newline and tab. */
1010: if (stringbuf[j] == ';')
1011: {
1012: strcpy (&stringbuf[j], "\\n\\t");
1013: j += 3;
1014: }
1015: }
1016: else if (stringbuf[j] == '"')
1017: break;
1018: j++;
1019: }
1020:
1021: stringbuf[j] = 0; /* NUL terminate the string */
1022: stringbuf = (char *) xrealloc (stringbuf, j + 1);
1023:
1024: if (saw_paren)
1025: {
1026: c = read_skip_spaces (infile);
1027: if (c != ')')
1028: dump_and_abort (')', c, infile);
1029: }
1030: XSTR (return_rtx, i) = stringbuf;
1031: }
1032: break;
1033:
1034: case 'i':
1035: read_name (tmp_char, infile);
1036: tmp_int = atoi (tmp_char);
1037: XINT (return_rtx, i) = tmp_int;
1038: break;
1039:
1040: default:
1041: fprintf (stderr,
1042: "switch format wrong in rtl.read_rtx(). format was: %c.\n",
1043: format_ptr[-1]);
1044: fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
1045: abort ();
1046: }
1047:
1048: c = read_skip_spaces (infile);
1049: if (c != ')')
1050: dump_and_abort (')', c, infile);
1051:
1052: return return_rtx;
1053: }
1054:
1055: /* This is called once per compilation, before any rtx's are constructed.
1056: It initializes the vector `rtx_length'. */
1057:
1058: void
1059: init_rtl ()
1060: {
1061: int i;
1062:
1063: for (i = 0; i < NUM_RTX_CODE; i++)
1064: rtx_length[i] = strlen (rtx_format[i]);
1065: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.