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