|
|
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.