|
|
1.1 ! root 1: /* Convert tree expression to rtl instructions, for GNU compiler. ! 2: Copyright (C) 1988, 1992 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 "rtl.h" ! 23: #include "tree.h" ! 24: #include "flags.h" ! 25: #include "function.h" ! 26: #include "insn-flags.h" ! 27: #include "insn-codes.h" ! 28: #include "expr.h" ! 29: #include "insn-config.h" ! 30: #include "recog.h" ! 31: #include "output.h" ! 32: #include "gvarargs.h" ! 33: #include "typeclass.h" ! 34: ! 35: #define CEIL(x,y) (((x) + (y) - 1) / (y)) ! 36: ! 37: /* Decide whether a function's arguments should be processed ! 38: from first to last or from last to first. */ ! 39: ! 40: #ifdef STACK_GROWS_DOWNWARD ! 41: #ifdef PUSH_ROUNDING ! 42: #define PUSH_ARGS_REVERSED /* If it's last to first */ ! 43: #endif ! 44: #endif ! 45: ! 46: #ifndef STACK_PUSH_CODE ! 47: #ifdef STACK_GROWS_DOWNWARD ! 48: #define STACK_PUSH_CODE PRE_DEC ! 49: #else ! 50: #define STACK_PUSH_CODE PRE_INC ! 51: #endif ! 52: #endif ! 53: ! 54: /* Like STACK_BOUNDARY but in units of bytes, not bits. */ ! 55: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT) ! 56: ! 57: /* If this is nonzero, we do not bother generating VOLATILE ! 58: around volatile memory references, and we are willing to ! 59: output indirect addresses. If cse is to follow, we reject ! 60: indirect addresses so a useful potential cse is generated; ! 61: if it is used only once, instruction combination will produce ! 62: the same indirect address eventually. */ ! 63: int cse_not_expected; ! 64: ! 65: /* Nonzero to generate code for all the subroutines within an ! 66: expression before generating the upper levels of the expression. ! 67: Nowadays this is never zero. */ ! 68: int do_preexpand_calls = 1; ! 69: ! 70: /* Number of units that we should eventually pop off the stack. ! 71: These are the arguments to function calls that have already returned. */ ! 72: int pending_stack_adjust; ! 73: ! 74: /* Nonzero means stack pops must not be deferred, and deferred stack ! 75: pops must not be output. It is nonzero inside a function call, ! 76: inside a conditional expression, inside a statement expression, ! 77: and in other cases as well. */ ! 78: int inhibit_defer_pop; ! 79: ! 80: /* A list of all cleanups which belong to the arguments of ! 81: function calls being expanded by expand_call. */ ! 82: tree cleanups_this_call; ! 83: ! 84: /* Nonzero means __builtin_saveregs has already been done in this function. ! 85: The value is the pseudoreg containing the value __builtin_saveregs ! 86: returned. */ ! 87: static rtx saveregs_value; ! 88: ! 89: rtx store_expr (); ! 90: static void store_constructor (); ! 91: static rtx store_field (); ! 92: static rtx expand_builtin (); ! 93: static rtx compare (); ! 94: static rtx do_store_flag (); ! 95: static void preexpand_calls (); ! 96: static rtx expand_increment (); ! 97: static void init_queue (); ! 98: ! 99: void do_pending_stack_adjust (); ! 100: static void do_jump_for_compare (); ! 101: static void do_jump_by_parts_equality (); ! 102: static void do_jump_by_parts_equality_rtx (); ! 103: static void do_jump_by_parts_greater (); ! 104: ! 105: /* MOVE_RATIO is the number of move instructions that is better than ! 106: a block move. */ ! 107: ! 108: #ifndef MOVE_RATIO ! 109: #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) ! 110: #define MOVE_RATIO 2 ! 111: #else ! 112: /* A value of around 6 would minimize code size; infinity would minimize ! 113: execution time. */ ! 114: #define MOVE_RATIO 15 ! 115: #endif ! 116: #endif ! 117: ! 118: /* This is run at the start of compiling a function. */ ! 119: ! 120: void ! 121: init_expr () ! 122: { ! 123: init_queue (); ! 124: ! 125: pending_stack_adjust = 0; ! 126: inhibit_defer_pop = 0; ! 127: cleanups_this_call = 0; ! 128: saveregs_value = 0; ! 129: } ! 130: ! 131: /* Save all variables describing the current status into the structure *P. ! 132: This is used before starting a nested function. */ ! 133: ! 134: void ! 135: save_expr_status (p) ! 136: struct function *p; ! 137: { ! 138: /* Instead of saving the postincrement queue, empty it. */ ! 139: emit_queue (); ! 140: ! 141: p->pending_stack_adjust = pending_stack_adjust; ! 142: p->inhibit_defer_pop = inhibit_defer_pop; ! 143: p->cleanups_this_call = cleanups_this_call; ! 144: p->saveregs_value = saveregs_value; ! 145: ! 146: pending_stack_adjust = 0; ! 147: inhibit_defer_pop = 0; ! 148: cleanups_this_call = 0; ! 149: saveregs_value = 0; ! 150: } ! 151: ! 152: /* Restore all variables describing the current status from the structure *P. ! 153: This is used after a nested function. */ ! 154: ! 155: void ! 156: restore_expr_status (p) ! 157: struct function *p; ! 158: { ! 159: pending_stack_adjust = p->pending_stack_adjust; ! 160: inhibit_defer_pop = p->inhibit_defer_pop; ! 161: cleanups_this_call = p->cleanups_this_call; ! 162: saveregs_value = p->saveregs_value; ! 163: } ! 164: ! 165: /* Manage the queue of increment instructions to be output ! 166: for POSTINCREMENT_EXPR expressions, etc. */ ! 167: ! 168: static rtx pending_chain; ! 169: ! 170: /* Queue up to increment (or change) VAR later. BODY says how: ! 171: BODY should be the same thing you would pass to emit_insn ! 172: to increment right away. It will go to emit_insn later on. ! 173: ! 174: The value is a QUEUED expression to be used in place of VAR ! 175: where you want to guarantee the pre-incrementation value of VAR. */ ! 176: ! 177: static rtx ! 178: enqueue_insn (var, body) ! 179: rtx var, body; ! 180: { ! 181: pending_chain = gen_rtx (QUEUED, GET_MODE (var), ! 182: var, 0, 0, body, pending_chain); ! 183: return pending_chain; ! 184: } ! 185: ! 186: /* Use protect_from_queue to convert a QUEUED expression ! 187: into something that you can put immediately into an instruction. ! 188: If the queued incrementation has not happened yet, ! 189: protect_from_queue returns the variable itself. ! 190: If the incrementation has happened, protect_from_queue returns a temp ! 191: that contains a copy of the old value of the variable. ! 192: ! 193: Any time an rtx which might possibly be a QUEUED is to be put ! 194: into an instruction, it must be passed through protect_from_queue first. ! 195: QUEUED expressions are not meaningful in instructions. ! 196: ! 197: Do not pass a value through protect_from_queue and then hold ! 198: on to it for a while before putting it in an instruction! ! 199: If the queue is flushed in between, incorrect code will result. */ ! 200: ! 201: rtx ! 202: protect_from_queue (x, modify) ! 203: register rtx x; ! 204: int modify; ! 205: { ! 206: register RTX_CODE code = GET_CODE (x); ! 207: ! 208: #if 0 /* A QUEUED can hang around after the queue is forced out. */ ! 209: /* Shortcut for most common case. */ ! 210: if (pending_chain == 0) ! 211: return x; ! 212: #endif ! 213: ! 214: if (code != QUEUED) ! 215: { ! 216: /* A special hack for read access to (MEM (QUEUED ...)) ! 217: to facilitate use of autoincrement. ! 218: Make a copy of the contents of the memory location ! 219: rather than a copy of the address, but not ! 220: if the value is of mode BLKmode. */ ! 221: if (code == MEM && GET_MODE (x) != BLKmode ! 222: && GET_CODE (XEXP (x, 0)) == QUEUED && !modify) ! 223: { ! 224: register rtx y = XEXP (x, 0); ! 225: XEXP (x, 0) = QUEUED_VAR (y); ! 226: if (QUEUED_INSN (y)) ! 227: { ! 228: register rtx temp = gen_reg_rtx (GET_MODE (x)); ! 229: emit_insn_before (gen_move_insn (temp, x), ! 230: QUEUED_INSN (y)); ! 231: return temp; ! 232: } ! 233: return x; ! 234: } ! 235: /* Otherwise, recursively protect the subexpressions of all ! 236: the kinds of rtx's that can contain a QUEUED. */ ! 237: if (code == MEM) ! 238: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0); ! 239: else if (code == PLUS || code == MULT) ! 240: { ! 241: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0); ! 242: XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0); ! 243: } ! 244: return x; ! 245: } ! 246: /* If the increment has not happened, use the variable itself. */ ! 247: if (QUEUED_INSN (x) == 0) ! 248: return QUEUED_VAR (x); ! 249: /* If the increment has happened and a pre-increment copy exists, ! 250: use that copy. */ ! 251: if (QUEUED_COPY (x) != 0) ! 252: return QUEUED_COPY (x); ! 253: /* The increment has happened but we haven't set up a pre-increment copy. ! 254: Set one up now, and use it. */ ! 255: QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x))); ! 256: emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)), ! 257: QUEUED_INSN (x)); ! 258: return QUEUED_COPY (x); ! 259: } ! 260: ! 261: /* Return nonzero if X contains a QUEUED expression: ! 262: if it contains anything that will be altered by a queued increment. ! 263: We handle only combinations of MEM, PLUS, MINUS and MULT operators ! 264: since memory addresses generally contain only those. */ ! 265: ! 266: static int ! 267: queued_subexp_p (x) ! 268: rtx x; ! 269: { ! 270: register enum rtx_code code = GET_CODE (x); ! 271: switch (code) ! 272: { ! 273: case QUEUED: ! 274: return 1; ! 275: case MEM: ! 276: return queued_subexp_p (XEXP (x, 0)); ! 277: case MULT: ! 278: case PLUS: ! 279: case MINUS: ! 280: return queued_subexp_p (XEXP (x, 0)) ! 281: || queued_subexp_p (XEXP (x, 1)); ! 282: } ! 283: return 0; ! 284: } ! 285: ! 286: /* Perform all the pending incrementations. */ ! 287: ! 288: void ! 289: emit_queue () ! 290: { ! 291: register rtx p; ! 292: while (p = pending_chain) ! 293: { ! 294: QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p)); ! 295: pending_chain = QUEUED_NEXT (p); ! 296: } ! 297: } ! 298: ! 299: static void ! 300: init_queue () ! 301: { ! 302: if (pending_chain) ! 303: abort (); ! 304: } ! 305: ! 306: /* Copy data from FROM to TO, where the machine modes are not the same. ! 307: Both modes may be integer, or both may be floating. ! 308: UNSIGNEDP should be nonzero if FROM is an unsigned type. ! 309: This causes zero-extension instead of sign-extension. */ ! 310: ! 311: void ! 312: convert_move (to, from, unsignedp) ! 313: register rtx to, from; ! 314: int unsignedp; ! 315: { ! 316: enum machine_mode to_mode = GET_MODE (to); ! 317: enum machine_mode from_mode = GET_MODE (from); ! 318: int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT; ! 319: int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT; ! 320: enum insn_code code; ! 321: rtx libcall; ! 322: ! 323: /* rtx code for making an equivalent value. */ ! 324: enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND); ! 325: ! 326: to = protect_from_queue (to, 1); ! 327: from = protect_from_queue (from, 0); ! 328: ! 329: if (to_real != from_real) ! 330: abort (); ! 331: ! 332: if (to_mode == from_mode ! 333: || (from_mode == VOIDmode && CONSTANT_P (from))) ! 334: { ! 335: emit_move_insn (to, from); ! 336: return; ! 337: } ! 338: ! 339: if (to_real) ! 340: { ! 341: #ifdef HAVE_extendsfdf2 ! 342: if (HAVE_extendsfdf2 && from_mode == SFmode && to_mode == DFmode) ! 343: { ! 344: emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN); ! 345: return; ! 346: } ! 347: #endif ! 348: #ifdef HAVE_extendsftf2 ! 349: if (HAVE_extendsftf2 && from_mode == SFmode && to_mode == TFmode) ! 350: { ! 351: emit_unop_insn (CODE_FOR_extendsftf2, to, from, UNKNOWN); ! 352: return; ! 353: } ! 354: #endif ! 355: #ifdef HAVE_extenddftf2 ! 356: if (HAVE_extenddftf2 && from_mode == DFmode && to_mode == TFmode) ! 357: { ! 358: emit_unop_insn (CODE_FOR_extenddftf2, to, from, UNKNOWN); ! 359: return; ! 360: } ! 361: #endif ! 362: #ifdef HAVE_truncdfsf2 ! 363: if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode) ! 364: { ! 365: emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN); ! 366: return; ! 367: } ! 368: #endif ! 369: #ifdef HAVE_trunctfsf2 ! 370: if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode) ! 371: { ! 372: emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN); ! 373: return; ! 374: } ! 375: #endif ! 376: #ifdef HAVE_trunctfdf2 ! 377: if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode) ! 378: { ! 379: emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN); ! 380: return; ! 381: } ! 382: #endif ! 383: ! 384: if (from_mode == SFmode && to_mode == DFmode) ! 385: libcall = extendsfdf2_libfunc; ! 386: else if (from_mode == DFmode && to_mode == SFmode) ! 387: libcall = truncdfsf2_libfunc; ! 388: else ! 389: /* This conversion is not implemented yet. There aren't any TFmode ! 390: library calls. */ ! 391: abort (); ! 392: ! 393: emit_library_call (libcall, 0, to_mode, 1, from, from_mode); ! 394: emit_move_insn (to, hard_libcall_value (to_mode)); ! 395: return; ! 396: } ! 397: ! 398: /* Now both modes are integers. */ ! 399: ! 400: /* Handle expanding beyond a word. */ ! 401: if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode) ! 402: && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD) ! 403: { ! 404: rtx insns; ! 405: rtx lowpart; ! 406: rtx fill_value; ! 407: rtx lowfrom; ! 408: int i; ! 409: enum machine_mode lowpart_mode; ! 410: int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD); ! 411: ! 412: /* Try converting directly if the insn is supported. */ ! 413: if ((code = can_extend_p (to_mode, from_mode, unsignedp)) ! 414: != CODE_FOR_nothing) ! 415: { ! 416: emit_unop_insn (code, to, from, equiv_code); ! 417: return; ! 418: } ! 419: /* Next, try converting via full word. */ ! 420: else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD ! 421: && ((code = can_extend_p (to_mode, word_mode, unsignedp)) ! 422: != CODE_FOR_nothing)) ! 423: { ! 424: convert_move (gen_lowpart (word_mode, to), from, unsignedp); ! 425: emit_unop_insn (code, to, ! 426: gen_lowpart (word_mode, to), equiv_code); ! 427: return; ! 428: } ! 429: ! 430: /* No special multiword conversion insn; do it by hand. */ ! 431: start_sequence (); ! 432: ! 433: /* Get a copy of FROM widened to a word, if necessary. */ ! 434: if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD) ! 435: lowpart_mode = word_mode; ! 436: else ! 437: lowpart_mode = from_mode; ! 438: ! 439: lowfrom = convert_to_mode (lowpart_mode, from, unsignedp); ! 440: ! 441: lowpart = gen_lowpart (lowpart_mode, to); ! 442: emit_move_insn (lowpart, lowfrom); ! 443: ! 444: /* Compute the value to put in each remaining word. */ ! 445: if (unsignedp) ! 446: fill_value = const0_rtx; ! 447: else ! 448: { ! 449: #ifdef HAVE_slt ! 450: if (HAVE_slt ! 451: && insn_operand_mode[(int) CODE_FOR_slt][0] == word_mode ! 452: && STORE_FLAG_VALUE == -1) ! 453: { ! 454: emit_cmp_insn (lowfrom, const0_rtx, NE, 0, lowpart_mode, 0, 0); ! 455: fill_value = gen_reg_rtx (word_mode); ! 456: emit_insn (gen_slt (fill_value)); ! 457: } ! 458: else ! 459: #endif ! 460: { ! 461: fill_value ! 462: = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom, ! 463: size_int (GET_MODE_BITSIZE (lowpart_mode) - 1), ! 464: 0, 0); ! 465: fill_value = convert_to_mode (word_mode, fill_value, 1); ! 466: } ! 467: } ! 468: ! 469: /* Fill the remaining words. */ ! 470: for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++) ! 471: { ! 472: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); ! 473: rtx subword = operand_subword (to, index, 1, to_mode); ! 474: ! 475: if (subword == 0) ! 476: abort (); ! 477: ! 478: if (fill_value != subword) ! 479: emit_move_insn (subword, fill_value); ! 480: } ! 481: ! 482: insns = get_insns (); ! 483: end_sequence (); ! 484: ! 485: emit_no_conflict_block (insns, to, from, 0, ! 486: gen_rtx (equiv_code, to_mode, from)); ! 487: return; ! 488: } ! 489: ! 490: if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD) ! 491: { ! 492: convert_move (to, gen_lowpart (word_mode, from), 0); ! 493: return; ! 494: } ! 495: ! 496: /* Handle pointer conversion */ /* SPEE 900220 */ ! 497: if (to_mode == PSImode) ! 498: { ! 499: if (from_mode != SImode) ! 500: from = convert_to_mode (SImode, from, unsignedp); ! 501: ! 502: #ifdef HAVE_truncsipsi ! 503: if (HAVE_truncsipsi) ! 504: { ! 505: emit_unop_insn (CODE_FOR_truncsipsi, to, from, UNKNOWN); ! 506: return; ! 507: } ! 508: #endif /* HAVE_truncsipsi */ ! 509: abort (); ! 510: } ! 511: ! 512: if (from_mode == PSImode) ! 513: { ! 514: if (to_mode != SImode) ! 515: { ! 516: from = convert_to_mode (SImode, from, unsignedp); ! 517: from_mode = SImode; ! 518: } ! 519: else ! 520: { ! 521: #ifdef HAVE_extendpsisi ! 522: if (HAVE_extendpsisi) ! 523: { ! 524: emit_unop_insn (CODE_FOR_extendpsisi, to, from, UNKNOWN); ! 525: return; ! 526: } ! 527: #endif /* HAVE_extendpsisi */ ! 528: abort (); ! 529: } ! 530: } ! 531: ! 532: /* Now follow all the conversions between integers ! 533: no more than a word long. */ ! 534: ! 535: /* For truncation, usually we can just refer to FROM in a narrower mode. */ ! 536: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode) ! 537: && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode), ! 538: GET_MODE_BITSIZE (from_mode)) ! 539: && ((GET_CODE (from) == MEM ! 540: && ! MEM_VOLATILE_P (from) ! 541: && ! mode_dependent_address_p (XEXP (from, 0))) ! 542: || GET_CODE (from) == REG ! 543: || GET_CODE (from) == SUBREG)) ! 544: { ! 545: emit_move_insn (to, gen_lowpart (to_mode, from)); ! 546: return; ! 547: } ! 548: ! 549: /* For truncation, usually we can just refer to FROM in a narrower mode. */ ! 550: if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode)) ! 551: { ! 552: /* Convert directly if that works. */ ! 553: if ((code = can_extend_p (to_mode, from_mode, unsignedp)) ! 554: != CODE_FOR_nothing) ! 555: { ! 556: emit_unop_insn (code, to, from, equiv_code); ! 557: return; ! 558: } ! 559: else ! 560: { ! 561: enum machine_mode intermediate; ! 562: ! 563: /* Search for a mode to convert via. */ ! 564: for (intermediate = from_mode; intermediate != VOIDmode; ! 565: intermediate = GET_MODE_WIDER_MODE (intermediate)) ! 566: if ((can_extend_p (to_mode, intermediate, unsignedp) ! 567: != CODE_FOR_nothing) ! 568: && (can_extend_p (intermediate, from_mode, unsignedp) ! 569: != CODE_FOR_nothing)) ! 570: { ! 571: convert_move (to, convert_to_mode (intermediate, from, ! 572: unsignedp), unsignedp); ! 573: return; ! 574: } ! 575: ! 576: /* No suitable intermediate mode. */ ! 577: abort (); ! 578: } ! 579: } ! 580: ! 581: /* Support special truncate insns for certain modes. */ ! 582: ! 583: if (from_mode == DImode && to_mode == SImode) ! 584: { ! 585: #ifdef HAVE_truncdisi2 ! 586: if (HAVE_truncdisi2) ! 587: { ! 588: emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN); ! 589: return; ! 590: } ! 591: #endif ! 592: convert_move (to, force_reg (from_mode, from), unsignedp); ! 593: return; ! 594: } ! 595: ! 596: if (from_mode == DImode && to_mode == HImode) ! 597: { ! 598: #ifdef HAVE_truncdihi2 ! 599: if (HAVE_truncdihi2) ! 600: { ! 601: emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN); ! 602: return; ! 603: } ! 604: #endif ! 605: convert_move (to, force_reg (from_mode, from), unsignedp); ! 606: return; ! 607: } ! 608: ! 609: if (from_mode == DImode && to_mode == QImode) ! 610: { ! 611: #ifdef HAVE_truncdiqi2 ! 612: if (HAVE_truncdiqi2) ! 613: { ! 614: emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN); ! 615: return; ! 616: } ! 617: #endif ! 618: convert_move (to, force_reg (from_mode, from), unsignedp); ! 619: return; ! 620: } ! 621: ! 622: if (from_mode == SImode && to_mode == HImode) ! 623: { ! 624: #ifdef HAVE_truncsihi2 ! 625: if (HAVE_truncsihi2) ! 626: { ! 627: emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN); ! 628: return; ! 629: } ! 630: #endif ! 631: convert_move (to, force_reg (from_mode, from), unsignedp); ! 632: return; ! 633: } ! 634: ! 635: if (from_mode == SImode && to_mode == QImode) ! 636: { ! 637: #ifdef HAVE_truncsiqi2 ! 638: if (HAVE_truncsiqi2) ! 639: { ! 640: emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN); ! 641: return; ! 642: } ! 643: #endif ! 644: convert_move (to, force_reg (from_mode, from), unsignedp); ! 645: return; ! 646: } ! 647: ! 648: if (from_mode == HImode && to_mode == QImode) ! 649: { ! 650: #ifdef HAVE_trunchiqi2 ! 651: if (HAVE_trunchiqi2) ! 652: { ! 653: emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN); ! 654: return; ! 655: } ! 656: #endif ! 657: convert_move (to, force_reg (from_mode, from), unsignedp); ! 658: return; ! 659: } ! 660: ! 661: /* Handle truncation of volatile memrefs, and so on; ! 662: the things that couldn't be truncated directly, ! 663: and for which there was no special instruction. */ ! 664: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)) ! 665: { ! 666: rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from)); ! 667: emit_move_insn (to, temp); ! 668: return; ! 669: } ! 670: ! 671: /* Mode combination is not recognized. */ ! 672: abort (); ! 673: } ! 674: ! 675: /* Return an rtx for a value that would result ! 676: from converting X to mode MODE. ! 677: Both X and MODE may be floating, or both integer. ! 678: UNSIGNEDP is nonzero if X is an unsigned value. ! 679: This can be done by referring to a part of X in place ! 680: or by copying to a new temporary with conversion. */ ! 681: ! 682: rtx ! 683: convert_to_mode (mode, x, unsignedp) ! 684: enum machine_mode mode; ! 685: rtx x; ! 686: int unsignedp; ! 687: { ! 688: register rtx temp; ! 689: ! 690: x = protect_from_queue (x, 0); ! 691: ! 692: if (mode == GET_MODE (x)) ! 693: return x; ! 694: ! 695: /* There is one case that we must handle specially: If we are converting ! 696: a CONST_INT into a mode whose size is twice HOST_BITS_PER_INT and ! 697: we are to interpret the constant as unsigned, gen_lowpart will do ! 698: the wrong if the constant appears negative. What we want to do is ! 699: make the high-order word of the constant zero, not all ones. */ ! 700: ! 701: if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT ! 702: && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_INT ! 703: && GET_CODE (x) == CONST_INT && INTVAL (x) < 0) ! 704: return immed_double_const (INTVAL (x), 0, mode); ! 705: ! 706: /* We can do this with a gen_lowpart if both desired and current modes ! 707: are integer, and this is either a constant integer, a register, or a ! 708: non-volatile MEM. Except for the constant case, we must be narrowing ! 709: the operand. */ ! 710: ! 711: if (GET_CODE (x) == CONST_INT ! 712: || (GET_MODE_CLASS (mode) == MODE_INT ! 713: && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT ! 714: && (GET_CODE (x) == CONST_DOUBLE ! 715: || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)) ! 716: && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)) ! 717: || GET_CODE (x) == REG))))) ! 718: return gen_lowpart (mode, x); ! 719: ! 720: temp = gen_reg_rtx (mode); ! 721: convert_move (temp, x, unsignedp); ! 722: return temp; ! 723: } ! 724: ! 725: /* Generate several move instructions to copy LEN bytes ! 726: from block FROM to block TO. (These are MEM rtx's with BLKmode). ! 727: The caller must pass FROM and TO ! 728: through protect_from_queue before calling. ! 729: ALIGN (in bytes) is maximum alignment we can assume. */ ! 730: ! 731: struct move_by_pieces ! 732: { ! 733: rtx to; ! 734: rtx to_addr; ! 735: int autinc_to; ! 736: int explicit_inc_to; ! 737: rtx from; ! 738: rtx from_addr; ! 739: int autinc_from; ! 740: int explicit_inc_from; ! 741: int len; ! 742: int offset; ! 743: int reverse; ! 744: }; ! 745: ! 746: static void move_by_pieces_1 (); ! 747: static int move_by_pieces_ninsns (); ! 748: ! 749: static void ! 750: move_by_pieces (to, from, len, align) ! 751: rtx to, from; ! 752: int len, align; ! 753: { ! 754: struct move_by_pieces data; ! 755: rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0); ! 756: int max_size = 10000; ! 757: ! 758: data.offset = 0; ! 759: data.to_addr = to_addr; ! 760: data.from_addr = from_addr; ! 761: data.to = to; ! 762: data.from = from; ! 763: data.autinc_to ! 764: = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC ! 765: || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC); ! 766: data.autinc_from ! 767: = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC ! 768: || GET_CODE (from_addr) == POST_INC ! 769: || GET_CODE (from_addr) == POST_DEC); ! 770: ! 771: data.explicit_inc_from = 0; ! 772: data.explicit_inc_to = 0; ! 773: data.reverse ! 774: = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC); ! 775: if (data.reverse) data.offset = len; ! 776: data.len = len; ! 777: ! 778: /* If copying requires more than two move insns, ! 779: copy addresses to registers (to make displacements shorter) ! 780: and use post-increment if available. */ ! 781: if (!(data.autinc_from && data.autinc_to) ! 782: && move_by_pieces_ninsns (len, align) > 2) ! 783: { ! 784: #ifdef HAVE_PRE_DECREMENT ! 785: if (data.reverse && ! data.autinc_from) ! 786: { ! 787: data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len)); ! 788: data.autinc_from = 1; ! 789: data.explicit_inc_from = -1; ! 790: } ! 791: #endif ! 792: #ifdef HAVE_POST_INCREMENT ! 793: if (! data.autinc_from) ! 794: { ! 795: data.from_addr = copy_addr_to_reg (from_addr); ! 796: data.autinc_from = 1; ! 797: data.explicit_inc_from = 1; ! 798: } ! 799: #endif ! 800: if (!data.autinc_from && CONSTANT_P (from_addr)) ! 801: data.from_addr = copy_addr_to_reg (from_addr); ! 802: #ifdef HAVE_PRE_DECREMENT ! 803: if (data.reverse && ! data.autinc_to) ! 804: { ! 805: data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len)); ! 806: data.autinc_to = 1; ! 807: data.explicit_inc_to = -1; ! 808: } ! 809: #endif ! 810: #ifdef HAVE_POST_INCREMENT ! 811: if (! data.reverse && ! data.autinc_to) ! 812: { ! 813: data.to_addr = copy_addr_to_reg (to_addr); ! 814: data.autinc_to = 1; ! 815: data.explicit_inc_to = 1; ! 816: } ! 817: #endif ! 818: if (!data.autinc_to && CONSTANT_P (to_addr)) ! 819: data.to_addr = copy_addr_to_reg (to_addr); ! 820: } ! 821: ! 822: #if defined (STRICT_ALIGNMENT) || defined (SLOW_UNALIGNED_ACCESS) ! 823: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 824: align = MOVE_MAX; ! 825: #else ! 826: align = MOVE_MAX; ! 827: #endif ! 828: ! 829: /* First move what we can in the largest integer mode, then go to ! 830: successively smaller modes. */ ! 831: ! 832: while (max_size > 1) ! 833: { ! 834: enum machine_mode mode = VOIDmode, tmode; ! 835: enum insn_code icode; ! 836: ! 837: for (tmode = VOIDmode; (int) tmode < (int) MAX_MACHINE_MODE; ! 838: tmode = (enum machine_mode) ((int) tmode + 1)) ! 839: if (GET_MODE_CLASS (tmode) == MODE_INT ! 840: && GET_MODE_SIZE (tmode) < max_size) ! 841: mode = tmode; ! 842: ! 843: if (mode == VOIDmode) ! 844: break; ! 845: ! 846: icode = mov_optab->handlers[(int) mode].insn_code; ! 847: if (icode != CODE_FOR_nothing ! 848: && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT, ! 849: GET_MODE_SIZE (mode))) ! 850: move_by_pieces_1 (GEN_FCN (icode), mode, &data); ! 851: ! 852: max_size = GET_MODE_SIZE (mode); ! 853: } ! 854: ! 855: /* The code above should have handled everything. */ ! 856: if (data.len != 0) ! 857: abort (); ! 858: } ! 859: ! 860: /* Return number of insns required to move L bytes by pieces. ! 861: ALIGN (in bytes) is maximum alignment we can assume. */ ! 862: ! 863: static int ! 864: move_by_pieces_ninsns (l, align) ! 865: unsigned int l; ! 866: int align; ! 867: { ! 868: register int n_insns = 0; ! 869: int max_size = 10000; ! 870: ! 871: #if defined (STRICT_ALIGNMENT) || defined (SLOW_UNALIGNED_ACCESS) ! 872: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 873: align = MOVE_MAX; ! 874: #else ! 875: align = MOVE_MAX; ! 876: #endif ! 877: ! 878: while (max_size > 1) ! 879: { ! 880: enum machine_mode mode = VOIDmode, tmode; ! 881: enum insn_code icode; ! 882: ! 883: for (tmode = VOIDmode; (int) tmode < (int) MAX_MACHINE_MODE; ! 884: tmode = (enum machine_mode) ((int) tmode + 1)) ! 885: if (GET_MODE_CLASS (tmode) == MODE_INT ! 886: && GET_MODE_SIZE (tmode) < max_size) ! 887: mode = tmode; ! 888: ! 889: if (mode == VOIDmode) ! 890: break; ! 891: ! 892: icode = mov_optab->handlers[(int) mode].insn_code; ! 893: if (icode != CODE_FOR_nothing ! 894: && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT, ! 895: GET_MODE_SIZE (mode))) ! 896: n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode); ! 897: ! 898: max_size = GET_MODE_SIZE (mode); ! 899: } ! 900: ! 901: return n_insns; ! 902: } ! 903: ! 904: /* Subroutine of move_by_pieces. Move as many bytes as appropriate ! 905: with move instructions for mode MODE. GENFUN is the gen_... function ! 906: to make a move insn for that mode. DATA has all the other info. */ ! 907: ! 908: static void ! 909: move_by_pieces_1 (genfun, mode, data) ! 910: rtx (*genfun) (); ! 911: enum machine_mode mode; ! 912: struct move_by_pieces *data; ! 913: { ! 914: register int size = GET_MODE_SIZE (mode); ! 915: register rtx to1, from1; ! 916: ! 917: while (data->len >= size) ! 918: { ! 919: if (data->reverse) data->offset -= size; ! 920: ! 921: to1 = (data->autinc_to ! 922: ? gen_rtx (MEM, mode, data->to_addr) ! 923: : change_address (data->to, mode, ! 924: plus_constant (data->to_addr, data->offset))); ! 925: from1 = ! 926: (data->autinc_from ! 927: ? gen_rtx (MEM, mode, data->from_addr) ! 928: : change_address (data->from, mode, ! 929: plus_constant (data->from_addr, data->offset))); ! 930: ! 931: #ifdef HAVE_PRE_DECREMENT ! 932: if (data->explicit_inc_to < 0) ! 933: emit_insn (gen_sub2_insn (data->to_addr, ! 934: gen_rtx (CONST_INT, VOIDmode, size))); ! 935: if (data->explicit_inc_from < 0) ! 936: emit_insn (gen_sub2_insn (data->from_addr, ! 937: gen_rtx (CONST_INT, VOIDmode, size))); ! 938: #endif ! 939: ! 940: emit_insn ((*genfun) (to1, from1)); ! 941: #ifdef HAVE_POST_INCREMENT ! 942: if (data->explicit_inc_to > 0) ! 943: emit_insn (gen_add2_insn (data->to_addr, ! 944: gen_rtx (CONST_INT, VOIDmode, size))); ! 945: if (data->explicit_inc_from > 0) ! 946: emit_insn (gen_add2_insn (data->from_addr, ! 947: gen_rtx (CONST_INT, VOIDmode, size))); ! 948: #endif ! 949: ! 950: if (! data->reverse) data->offset += size; ! 951: ! 952: data->len -= size; ! 953: } ! 954: } ! 955: ! 956: /* Emit code to move a block Y to a block X. ! 957: This may be done with string-move instructions, ! 958: with multiple scalar move instructions, or with a library call. ! 959: ! 960: Both X and Y must be MEM rtx's (perhaps inside VOLATILE) ! 961: with mode BLKmode. ! 962: SIZE is an rtx that says how long they are. ! 963: ALIGN is the maximum alignment we can assume they have, ! 964: measured in bytes. */ ! 965: ! 966: void ! 967: emit_block_move (x, y, size, align) ! 968: rtx x, y; ! 969: rtx size; ! 970: int align; ! 971: { ! 972: if (GET_MODE (x) != BLKmode) ! 973: abort (); ! 974: ! 975: if (GET_MODE (y) != BLKmode) ! 976: abort (); ! 977: ! 978: x = protect_from_queue (x, 1); ! 979: y = protect_from_queue (y, 0); ! 980: ! 981: if (GET_CODE (x) != MEM) ! 982: abort (); ! 983: if (GET_CODE (y) != MEM) ! 984: abort (); ! 985: if (size == 0) ! 986: abort (); ! 987: ! 988: if (GET_CODE (size) == CONST_INT ! 989: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) ! 990: < MOVE_RATIO)) ! 991: move_by_pieces (x, y, INTVAL (size), align); ! 992: else ! 993: { ! 994: /* Try the most limited insn first, because there's no point ! 995: including more than one in the machine description unless ! 996: the more limited one has some advantage. */ ! 997: #ifdef HAVE_movstrqi ! 998: if (HAVE_movstrqi ! 999: && GET_CODE (size) == CONST_INT ! 1000: && ((unsigned) INTVAL (size) ! 1001: < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) ! 1002: { ! 1003: rtx insn = gen_movstrqi (x, y, size, ! 1004: gen_rtx (CONST_INT, VOIDmode, align)); ! 1005: if (insn) ! 1006: { ! 1007: emit_insn (insn); ! 1008: return; ! 1009: } ! 1010: } ! 1011: #endif ! 1012: #ifdef HAVE_movstrhi ! 1013: if (HAVE_movstrhi ! 1014: && GET_CODE (size) == CONST_INT ! 1015: && ((unsigned) INTVAL (size) ! 1016: < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) ! 1017: { ! 1018: rtx insn = gen_movstrhi (x, y, size, ! 1019: gen_rtx (CONST_INT, VOIDmode, align)); ! 1020: if (insn) ! 1021: { ! 1022: emit_insn (insn); ! 1023: return; ! 1024: } ! 1025: } ! 1026: #endif ! 1027: #ifdef HAVE_movstrsi ! 1028: if (HAVE_movstrsi) ! 1029: { ! 1030: rtx insn = gen_movstrsi (x, y, size, ! 1031: gen_rtx (CONST_INT, VOIDmode, align)); ! 1032: if (insn) ! 1033: { ! 1034: emit_insn (insn); ! 1035: return; ! 1036: } ! 1037: } ! 1038: #endif ! 1039: #ifdef HAVE_movstrdi ! 1040: if (HAVE_movstrdi) ! 1041: { ! 1042: rtx insn = gen_movstrdi (x, y, size, ! 1043: gen_rtx (CONST_INT, VOIDmode, align)); ! 1044: if (insn) ! 1045: { ! 1046: emit_insn (insn); ! 1047: return; ! 1048: } ! 1049: } ! 1050: #endif ! 1051: ! 1052: #ifdef TARGET_MEM_FUNCTIONS ! 1053: emit_library_call (memcpy_libfunc, 0, ! 1054: VOIDmode, 3, XEXP (x, 0), Pmode, ! 1055: XEXP (y, 0), Pmode, ! 1056: size, Pmode); ! 1057: #else ! 1058: emit_library_call (bcopy_libfunc, 0, ! 1059: VOIDmode, 3, XEXP (y, 0), Pmode, ! 1060: XEXP (x, 0), Pmode, ! 1061: size, Pmode); ! 1062: #endif ! 1063: } ! 1064: } ! 1065: ! 1066: /* Copy all or part of a value X into registers starting at REGNO. ! 1067: The number of registers to be filled is NREGS. */ ! 1068: ! 1069: void ! 1070: move_block_to_reg (regno, x, nregs, mode) ! 1071: int regno; ! 1072: rtx x; ! 1073: int nregs; ! 1074: enum machine_mode mode; ! 1075: { ! 1076: int i; ! 1077: rtx pat, last; ! 1078: ! 1079: if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x)) ! 1080: x = validize_mem (force_const_mem (mode, x)); ! 1081: ! 1082: /* See if the machine can do this with a load multiple insn. */ ! 1083: #ifdef HAVE_load_multiple ! 1084: last = get_last_insn (); ! 1085: pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x, ! 1086: gen_rtx (CONST_INT, VOIDmode, nregs)); ! 1087: if (pat) ! 1088: { ! 1089: emit_insn (pat); ! 1090: return; ! 1091: } ! 1092: else ! 1093: delete_insns_since (last); ! 1094: #endif ! 1095: ! 1096: for (i = 0; i < nregs; i++) ! 1097: emit_move_insn (gen_rtx (REG, word_mode, regno + i), ! 1098: operand_subword_force (x, i, mode)); ! 1099: } ! 1100: ! 1101: /* Copy all or part of a BLKmode value X out of registers starting at REGNO. ! 1102: The number of registers to be filled is NREGS. */ ! 1103: ! 1104: void ! 1105: move_block_from_reg (regno, x, nregs) ! 1106: int regno; ! 1107: rtx x; ! 1108: int nregs; ! 1109: { ! 1110: int i; ! 1111: rtx pat, last; ! 1112: ! 1113: /* See if the machine can do this with a store multiple insn. */ ! 1114: #ifdef HAVE_store_multiple ! 1115: last = get_last_insn (); ! 1116: pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno), ! 1117: gen_rtx (CONST_INT, VOIDmode, nregs)); ! 1118: if (pat) ! 1119: { ! 1120: emit_insn (pat); ! 1121: return; ! 1122: } ! 1123: else ! 1124: delete_insns_since (last); ! 1125: #endif ! 1126: ! 1127: for (i = 0; i < nregs; i++) ! 1128: { ! 1129: rtx tem = operand_subword (x, i, 1, BLKmode); ! 1130: ! 1131: if (tem == 0) ! 1132: abort (); ! 1133: ! 1134: emit_move_insn (tem, gen_rtx (REG, word_mode, regno + i)); ! 1135: } ! 1136: } ! 1137: ! 1138: /* Mark NREGS consecutive regs, starting at REGNO, as being live now. */ ! 1139: ! 1140: void ! 1141: use_regs (regno, nregs) ! 1142: int regno; ! 1143: int nregs; ! 1144: { ! 1145: int i; ! 1146: ! 1147: for (i = 0; i < nregs; i++) ! 1148: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, word_mode, regno + i))); ! 1149: } ! 1150: ! 1151: /* Write zeros through the storage of OBJECT. ! 1152: If OBJECT has BLKmode, SIZE is its length in bytes. */ ! 1153: ! 1154: void ! 1155: clear_storage (object, size) ! 1156: rtx object; ! 1157: int size; ! 1158: { ! 1159: if (GET_MODE (object) == BLKmode) ! 1160: { ! 1161: #ifdef TARGET_MEM_FUNCTIONS ! 1162: emit_library_call (memset_libfunc, 0, ! 1163: VOIDmode, 3, ! 1164: XEXP (object, 0), Pmode, const0_rtx, Pmode, ! 1165: gen_rtx (CONST_INT, VOIDmode, size), Pmode); ! 1166: #else ! 1167: emit_library_call (bzero_libfunc, 0, ! 1168: VOIDmode, 2, ! 1169: XEXP (object, 0), Pmode, ! 1170: gen_rtx (CONST_INT, VOIDmode, size), Pmode); ! 1171: #endif ! 1172: } ! 1173: else ! 1174: emit_move_insn (object, const0_rtx); ! 1175: } ! 1176: ! 1177: /* Generate code to copy Y into X. ! 1178: Both Y and X must have the same mode, except that ! 1179: Y can be a constant with VOIDmode. ! 1180: This mode cannot be BLKmode; use emit_block_move for that. ! 1181: ! 1182: Return the last instruction emitted. */ ! 1183: ! 1184: rtx ! 1185: emit_move_insn (x, y) ! 1186: rtx x, y; ! 1187: { ! 1188: enum machine_mode mode = GET_MODE (x); ! 1189: int i; ! 1190: ! 1191: x = protect_from_queue (x, 1); ! 1192: y = protect_from_queue (y, 0); ! 1193: ! 1194: if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode)) ! 1195: abort (); ! 1196: ! 1197: if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y)) ! 1198: y = force_const_mem (mode, y); ! 1199: ! 1200: /* If X or Y are memory references, verify that their addresses are valid ! 1201: for the machine. */ ! 1202: if (GET_CODE (x) == MEM ! 1203: && ((! memory_address_p (GET_MODE (x), XEXP (x, 0)) ! 1204: && ! push_operand (x, GET_MODE (x))) ! 1205: || (flag_force_addr ! 1206: && CONSTANT_ADDRESS_P (XEXP (x, 0))))) ! 1207: x = change_address (x, VOIDmode, XEXP (x, 0)); ! 1208: ! 1209: if (GET_CODE (y) == MEM ! 1210: && (! memory_address_p (GET_MODE (y), XEXP (y, 0)) ! 1211: || (flag_force_addr ! 1212: && CONSTANT_ADDRESS_P (XEXP (y, 0))))) ! 1213: y = change_address (y, VOIDmode, XEXP (y, 0)); ! 1214: ! 1215: if (mode == BLKmode) ! 1216: abort (); ! 1217: ! 1218: if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 1219: return ! 1220: emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); ! 1221: ! 1222: /* This will handle any multi-word mode that lacks a move_insn pattern. ! 1223: However, you will get better code if you define such patterns, ! 1224: even if they must turn into multiple assembler instructions. */ ! 1225: else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD) ! 1226: { ! 1227: rtx last_insn = 0; ! 1228: ! 1229: for (i = 0; ! 1230: i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; ! 1231: i++) ! 1232: { ! 1233: rtx xpart = operand_subword (x, i, 1, mode); ! 1234: rtx ypart = operand_subword (y, i, 1, mode); ! 1235: ! 1236: /* If we can't get a part of Y, put Y into memory if it is a ! 1237: constant. Otherwise, force it into a register. If we still ! 1238: can't get a part of Y, abort. */ ! 1239: if (ypart == 0 && CONSTANT_P (y)) ! 1240: { ! 1241: y = force_const_mem (mode, y); ! 1242: ypart = operand_subword (y, i, 1, mode); ! 1243: } ! 1244: else if (ypart == 0) ! 1245: ypart = operand_subword_force (y, i, mode); ! 1246: ! 1247: if (xpart == 0 || ypart == 0) ! 1248: abort (); ! 1249: ! 1250: last_insn = emit_move_insn (xpart, ypart); ! 1251: } ! 1252: return last_insn; ! 1253: } ! 1254: else ! 1255: abort (); ! 1256: } ! 1257: ! 1258: /* Pushing data onto the stack. */ ! 1259: ! 1260: /* Push a block of length SIZE (perhaps variable) ! 1261: and return an rtx to address the beginning of the block. ! 1262: Note that it is not possible for the value returned to be a QUEUED. ! 1263: The value may be virtual_outgoing_args_rtx. ! 1264: ! 1265: EXTRA is the number of bytes of padding to push in addition to SIZE. ! 1266: BELOW nonzero means this padding comes at low addresses; ! 1267: otherwise, the padding comes at high addresses. */ ! 1268: ! 1269: rtx ! 1270: push_block (size, extra, below) ! 1271: rtx size; ! 1272: int extra, below; ! 1273: { ! 1274: register rtx temp; ! 1275: if (CONSTANT_P (size)) ! 1276: anti_adjust_stack (plus_constant (size, extra)); ! 1277: else if (GET_CODE (size) == REG && extra == 0) ! 1278: anti_adjust_stack (size); ! 1279: else ! 1280: { ! 1281: rtx temp = copy_to_mode_reg (Pmode, size); ! 1282: if (extra != 0) ! 1283: temp = expand_binop (Pmode, add_optab, ! 1284: temp, ! 1285: gen_rtx (CONST_INT, VOIDmode, extra), ! 1286: temp, 0, OPTAB_LIB_WIDEN); ! 1287: anti_adjust_stack (temp); ! 1288: } ! 1289: ! 1290: #ifdef STACK_GROWS_DOWNWARD ! 1291: temp = virtual_outgoing_args_rtx; ! 1292: if (extra != 0 && below) ! 1293: temp = plus_constant (temp, extra); ! 1294: #else ! 1295: if (GET_CODE (size) == CONST_INT) ! 1296: temp = plus_constant (virtual_outgoing_args_rtx, ! 1297: - INTVAL (size) - (below ? 0 : extra)); ! 1298: else if (extra != 0 && !below) ! 1299: temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx, ! 1300: negate_rtx (Pmode, plus_constant (size, extra))); ! 1301: else ! 1302: temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx, ! 1303: negate_rtx (Pmode, size)); ! 1304: #endif ! 1305: ! 1306: return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp); ! 1307: } ! 1308: ! 1309: static rtx ! 1310: gen_push_operand () ! 1311: { ! 1312: return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx); ! 1313: } ! 1314: ! 1315: /* Generate code to push X onto the stack, assuming it has mode MODE and ! 1316: type TYPE. ! 1317: MODE is redundant except when X is a CONST_INT (since they don't ! 1318: carry mode info). ! 1319: SIZE is an rtx for the size of data to be copied (in bytes), ! 1320: needed only if X is BLKmode. ! 1321: ! 1322: ALIGN (in bytes) is maximum alignment we can assume. ! 1323: ! 1324: If PARTIAL is nonzero, then copy that many of the first words ! 1325: of X into registers starting with REG, and push the rest of X. ! 1326: The amount of space pushed is decreased by PARTIAL words, ! 1327: rounded *down* to a multiple of PARM_BOUNDARY. ! 1328: REG must be a hard register in this case. ! 1329: ! 1330: EXTRA is the amount in bytes of extra space to leave next to this arg. ! 1331: This is ignored if an argument block has already been allocted. ! 1332: ! 1333: On a machine that lacks real push insns, ARGS_ADDR is the address of ! 1334: the bottom of the argument block for this call. We use indexing off there ! 1335: to store the arg. On machines with push insns, ARGS_ADDR is 0 when a ! 1336: argument block has not been preallocated. ! 1337: ! 1338: ARGS_SO_FAR is the size of args previously pushed for this call. */ ! 1339: ! 1340: void ! 1341: emit_push_insn (x, mode, type, size, align, partial, reg, extra, ! 1342: args_addr, args_so_far) ! 1343: register rtx x; ! 1344: enum machine_mode mode; ! 1345: tree type; ! 1346: rtx size; ! 1347: int align; ! 1348: int partial; ! 1349: rtx reg; ! 1350: int extra; ! 1351: rtx args_addr; ! 1352: rtx args_so_far; ! 1353: { ! 1354: rtx xinner; ! 1355: enum direction stack_direction ! 1356: #ifdef STACK_GROWS_DOWNWARD ! 1357: = downward; ! 1358: #else ! 1359: = upward; ! 1360: #endif ! 1361: ! 1362: /* Decide where to pad the argument: `downward' for below, ! 1363: `upward' for above, or `none' for don't pad it. ! 1364: Default is below for small data on big-endian machines; else above. */ ! 1365: enum direction where_pad = FUNCTION_ARG_PADDING (mode, type); ! 1366: ! 1367: /* Invert direction if stack is post-update. */ ! 1368: if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC) ! 1369: if (where_pad != none) ! 1370: where_pad = (where_pad == downward ? upward : downward); ! 1371: ! 1372: xinner = x = protect_from_queue (x, 0); ! 1373: ! 1374: if (mode == BLKmode) ! 1375: { ! 1376: /* Copy a block into the stack, entirely or partially. */ ! 1377: ! 1378: register rtx temp; ! 1379: int used = partial * UNITS_PER_WORD; ! 1380: int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); ! 1381: int skip; ! 1382: ! 1383: if (size == 0) ! 1384: abort (); ! 1385: ! 1386: used -= offset; ! 1387: ! 1388: /* USED is now the # of bytes we need not copy to the stack ! 1389: because registers will take care of them. */ ! 1390: ! 1391: if (partial != 0) ! 1392: xinner = change_address (xinner, BLKmode, ! 1393: plus_constant (XEXP (xinner, 0), used)); ! 1394: ! 1395: /* If the partial register-part of the arg counts in its stack size, ! 1396: skip the part of stack space corresponding to the registers. ! 1397: Otherwise, start copying to the beginning of the stack space, ! 1398: by setting SKIP to 0. */ ! 1399: #ifndef REG_PARM_STACK_SPACE ! 1400: skip = 0; ! 1401: #else ! 1402: skip = used; ! 1403: #endif ! 1404: ! 1405: #ifdef PUSH_ROUNDING ! 1406: /* Do it with several push insns if that doesn't take lots of insns ! 1407: and if there is no difficulty with push insns that skip bytes ! 1408: on the stack for alignment purposes. */ ! 1409: if (args_addr == 0 ! 1410: && GET_CODE (size) == CONST_INT ! 1411: && skip == 0 ! 1412: && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align) ! 1413: < MOVE_RATIO) ! 1414: #if defined (STRICT_ALIGNMENT) || defined (SLOW_UNALIGNED_ACCESS) ! 1415: /* Here we avoid the case of a structure whose weak alignment ! 1416: forces many pushes of a small amount of data, ! 1417: and such small pushes do rounding that causes trouble. */ ! 1418: && (align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT ! 1419: || PUSH_ROUNDING (align) == align) ! 1420: #endif ! 1421: && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size)) ! 1422: { ! 1423: /* Push padding now if padding above and stack grows down, ! 1424: or if padding below and stack grows up. ! 1425: But if space already allocated, this has already been done. */ ! 1426: if (extra && args_addr == 0 ! 1427: && where_pad != none && where_pad != stack_direction) ! 1428: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1429: ! 1430: move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, ! 1431: INTVAL (size) - used, align); ! 1432: } ! 1433: else ! 1434: #endif /* PUSH_ROUNDING */ ! 1435: { ! 1436: /* Otherwise make space on the stack and copy the data ! 1437: to the address of that space. */ ! 1438: ! 1439: /* Deduct words put into registers from the size we must copy. */ ! 1440: if (partial != 0) ! 1441: { ! 1442: if (GET_CODE (size) == CONST_INT) ! 1443: size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used); ! 1444: else ! 1445: size = expand_binop (GET_MODE (size), sub_optab, size, ! 1446: gen_rtx (CONST_INT, VOIDmode, used), ! 1447: 0, 0, OPTAB_LIB_WIDEN); ! 1448: } ! 1449: ! 1450: /* Get the address of the stack space. ! 1451: In this case, we do not deal with EXTRA separately. ! 1452: A single stack adjust will do. */ ! 1453: if (! args_addr) ! 1454: { ! 1455: temp = push_block (size, extra, where_pad == downward); ! 1456: extra = 0; ! 1457: } ! 1458: else if (GET_CODE (args_so_far) == CONST_INT) ! 1459: temp = memory_address (BLKmode, ! 1460: plus_constant (args_addr, ! 1461: skip + INTVAL (args_so_far))); ! 1462: else ! 1463: temp = memory_address (BLKmode, ! 1464: plus_constant (gen_rtx (PLUS, Pmode, ! 1465: args_addr, args_so_far), ! 1466: skip)); ! 1467: ! 1468: /* TEMP is the address of the block. Copy the data there. */ ! 1469: if (GET_CODE (size) == CONST_INT ! 1470: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) ! 1471: < MOVE_RATIO)) ! 1472: { ! 1473: move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner, ! 1474: INTVAL (size), align); ! 1475: goto ret; ! 1476: } ! 1477: /* Try the most limited insn first, because there's no point ! 1478: including more than one in the machine description unless ! 1479: the more limited one has some advantage. */ ! 1480: #ifdef HAVE_movstrqi ! 1481: if (HAVE_movstrqi ! 1482: && GET_CODE (size) == CONST_INT ! 1483: && ((unsigned) INTVAL (size) ! 1484: < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) ! 1485: { ! 1486: emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! 1487: xinner, size, ! 1488: gen_rtx (CONST_INT, VOIDmode, align))); ! 1489: goto ret; ! 1490: } ! 1491: #endif ! 1492: #ifdef HAVE_movstrhi ! 1493: if (HAVE_movstrhi ! 1494: && GET_CODE (size) == CONST_INT ! 1495: && ((unsigned) INTVAL (size) ! 1496: < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) ! 1497: { ! 1498: emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! 1499: xinner, size, ! 1500: gen_rtx (CONST_INT, VOIDmode, align))); ! 1501: goto ret; ! 1502: } ! 1503: #endif ! 1504: #ifdef HAVE_movstrsi ! 1505: if (HAVE_movstrsi) ! 1506: { ! 1507: emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), ! 1508: xinner, size, ! 1509: gen_rtx (CONST_INT, VOIDmode, align))); ! 1510: goto ret; ! 1511: } ! 1512: #endif ! 1513: #ifdef HAVE_movstrdi ! 1514: if (HAVE_movstrdi) ! 1515: { ! 1516: emit_insn (gen_movstrdi (gen_rtx (MEM, BLKmode, temp), ! 1517: xinner, size, ! 1518: gen_rtx (CONST_INT, VOIDmode, align))); ! 1519: goto ret; ! 1520: } ! 1521: #endif ! 1522: ! 1523: #ifndef ACCUMULATE_OUTGOING_ARGS ! 1524: /* If the source is referenced relative to the stack pointer, ! 1525: copy it to another register to stabilize it. We do not need ! 1526: to do this if we know that we won't be changing sp. */ ! 1527: ! 1528: if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp) ! 1529: || reg_mentioned_p (virtual_outgoing_args_rtx, temp)) ! 1530: temp = copy_to_reg (temp); ! 1531: #endif ! 1532: ! 1533: /* Make inhibit_defer_pop nonzero around the library call ! 1534: to force it to pop the bcopy-arguments right away. */ ! 1535: NO_DEFER_POP; ! 1536: #ifdef TARGET_MEM_FUNCTIONS ! 1537: emit_library_call (memcpy_libfunc, 0, ! 1538: VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode, ! 1539: size, Pmode); ! 1540: #else ! 1541: emit_library_call (bcopy_libfunc, 0, ! 1542: VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode, ! 1543: size, Pmode); ! 1544: #endif ! 1545: OK_DEFER_POP; ! 1546: } ! 1547: } ! 1548: else if (partial > 0) ! 1549: { ! 1550: /* Scalar partly in registers. */ ! 1551: ! 1552: int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD; ! 1553: int i; ! 1554: int not_stack; ! 1555: /* # words of start of argument ! 1556: that we must make space for but need not store. */ ! 1557: int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD); ! 1558: int args_offset = INTVAL (args_so_far); ! 1559: int skip; ! 1560: ! 1561: /* Push padding now if padding above and stack grows down, ! 1562: or if padding below and stack grows up. ! 1563: But if space already allocated, this has already been done. */ ! 1564: if (extra && args_addr == 0 ! 1565: && where_pad != none && where_pad != stack_direction) ! 1566: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1567: ! 1568: /* If we make space by pushing it, we might as well push ! 1569: the real data. Otherwise, we can leave OFFSET nonzero ! 1570: and leave the space uninitialized. */ ! 1571: if (args_addr == 0) ! 1572: offset = 0; ! 1573: ! 1574: /* Now NOT_STACK gets the number of words that we don't need to ! 1575: allocate on the stack. */ ! 1576: not_stack = partial - offset; ! 1577: ! 1578: /* If the partial register-part of the arg counts in its stack size, ! 1579: skip the part of stack space corresponding to the registers. ! 1580: Otherwise, start copying to the beginning of the stack space, ! 1581: by setting SKIP to 0. */ ! 1582: #ifndef REG_PARM_STACK_SPACE ! 1583: skip = 0; ! 1584: #else ! 1585: skip = not_stack; ! 1586: #endif ! 1587: ! 1588: if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x)) ! 1589: x = validize_mem (force_const_mem (mode, x)); ! 1590: ! 1591: /* If X is a hard register in a non-integer mode, copy it into a pseudo; ! 1592: SUBREGs of such registers are not allowed. */ ! 1593: if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER ! 1594: && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT)) ! 1595: x = copy_to_reg (x); ! 1596: ! 1597: /* Loop over all the words allocated on the stack for this arg. */ ! 1598: /* We can do it by words, because any scalar bigger than a word ! 1599: has a size a multiple of a word. */ ! 1600: #ifndef PUSH_ARGS_REVERSED ! 1601: for (i = not_stack; i < size; i++) ! 1602: #else ! 1603: for (i = size - 1; i >= not_stack; i--) ! 1604: #endif ! 1605: if (i >= not_stack + offset) ! 1606: emit_push_insn (operand_subword_force (x, i, mode), ! 1607: word_mode, 0, 0, align, 0, 0, 0, args_addr, ! 1608: gen_rtx (CONST_INT, VOIDmode, ! 1609: args_offset + ((i - not_stack + skip) ! 1610: * UNITS_PER_WORD))); ! 1611: } ! 1612: else ! 1613: { ! 1614: rtx addr; ! 1615: ! 1616: /* Push padding now if padding above and stack grows down, ! 1617: or if padding below and stack grows up. ! 1618: But if space already allocated, this has already been done. */ ! 1619: if (extra && args_addr == 0 ! 1620: && where_pad != none && where_pad != stack_direction) ! 1621: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1622: ! 1623: #ifdef PUSH_ROUNDING ! 1624: if (args_addr == 0) ! 1625: addr = gen_push_operand (); ! 1626: else ! 1627: #endif ! 1628: if (GET_CODE (args_so_far) == CONST_INT) ! 1629: addr ! 1630: = memory_address (mode, ! 1631: plus_constant (args_addr, INTVAL (args_so_far))); ! 1632: else ! 1633: addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr, ! 1634: args_so_far)); ! 1635: ! 1636: emit_move_insn (gen_rtx (MEM, mode, addr), x); ! 1637: } ! 1638: ! 1639: ret: ! 1640: /* If part should go in registers, copy that part ! 1641: into the appropriate registers. Do this now, at the end, ! 1642: since mem-to-mem copies above may do function calls. */ ! 1643: if (partial > 0) ! 1644: move_block_to_reg (REGNO (reg), x, partial, mode); ! 1645: ! 1646: if (extra && args_addr == 0 && where_pad == stack_direction) ! 1647: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1648: } ! 1649: ! 1650: /* Output a library call to function FUN (a SYMBOL_REF rtx) ! 1651: (emitting the queue unless NO_QUEUE is nonzero), ! 1652: for a value of mode OUTMODE, ! 1653: with NARGS different arguments, passed as alternating rtx values ! 1654: and machine_modes to convert them to. ! 1655: The rtx values should have been passed through protect_from_queue already. ! 1656: ! 1657: NO_QUEUE will be true if and only if the library call is a `const' call ! 1658: which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent ! 1659: to the variable is_const in expand_call. */ ! 1660: ! 1661: void ! 1662: emit_library_call (va_alist) ! 1663: va_dcl ! 1664: { ! 1665: va_list p; ! 1666: struct args_size args_size; ! 1667: register int argnum; ! 1668: enum machine_mode outmode; ! 1669: int nargs; ! 1670: rtx fun; ! 1671: rtx orgfun; ! 1672: int inc; ! 1673: int count; ! 1674: rtx argblock = 0; ! 1675: CUMULATIVE_ARGS args_so_far; ! 1676: struct arg { rtx value; enum machine_mode mode; rtx reg; int partial; ! 1677: struct args_size offset; struct args_size size; }; ! 1678: struct arg *argvec; ! 1679: int old_inhibit_defer_pop = inhibit_defer_pop; ! 1680: int no_queue = 0; ! 1681: rtx use_insns; ! 1682: ! 1683: va_start (p); ! 1684: orgfun = fun = va_arg (p, rtx); ! 1685: no_queue = va_arg (p, int); ! 1686: outmode = va_arg (p, enum machine_mode); ! 1687: nargs = va_arg (p, int); ! 1688: ! 1689: /* Copy all the libcall-arguments out of the varargs data ! 1690: and into a vector ARGVEC. ! 1691: ! 1692: Compute how to pass each argument. We only support a very small subset ! 1693: of the full argument passing conventions to limit complexity here since ! 1694: library functions shouldn't have many args. */ ! 1695: ! 1696: argvec = (struct arg *) alloca (nargs * sizeof (struct arg)); ! 1697: ! 1698: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0, fun); ! 1699: ! 1700: args_size.constant = 0; ! 1701: args_size.var = 0; ! 1702: ! 1703: for (count = 0; count < nargs; count++) ! 1704: { ! 1705: rtx val = va_arg (p, rtx); ! 1706: enum machine_mode mode = va_arg (p, enum machine_mode); ! 1707: ! 1708: /* We cannot convert the arg value to the mode the library wants here; ! 1709: must do it earlier where we know the signedness of the arg. */ ! 1710: if (mode == BLKmode ! 1711: || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)) ! 1712: abort (); ! 1713: ! 1714: /* On some machines, there's no way to pass a float to a library fcn. ! 1715: Pass it as a double instead. */ ! 1716: #ifdef LIBGCC_NEEDS_DOUBLE ! 1717: if (LIBGCC_NEEDS_DOUBLE && mode == SFmode) ! 1718: val = convert_to_mode (DFmode, val), mode = DFmode; ! 1719: #endif ! 1720: ! 1721: /* Make sure it is a reasonable operand for a move or push insn. */ ! 1722: if (GET_CODE (val) != REG && GET_CODE (val) != MEM ! 1723: && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val))) ! 1724: val = force_operand (val, 0); ! 1725: ! 1726: argvec[count].value = val; ! 1727: argvec[count].mode = mode; ! 1728: ! 1729: #ifdef FUNCTION_ARG_PASS_BY_REFERENCE ! 1730: if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, (tree)0, 1)) ! 1731: abort (); ! 1732: #endif ! 1733: ! 1734: argvec[count].reg = FUNCTION_ARG (args_so_far, mode, (tree)0, 1); ! 1735: if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) ! 1736: abort (); ! 1737: #ifdef FUNCTION_ARG_PARTIAL_NREGS ! 1738: argvec[count].partial ! 1739: = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, (tree)0, 1); ! 1740: #else ! 1741: argvec[count].partial = 0; ! 1742: #endif ! 1743: ! 1744: locate_and_pad_parm (mode, 0, ! 1745: argvec[count].reg && argvec[count].partial == 0, ! 1746: 0, &args_size, &argvec[count].offset, ! 1747: &argvec[count].size); ! 1748: ! 1749: if (argvec[count].size.var) ! 1750: abort (); ! 1751: ! 1752: #ifndef REG_PARM_STACK_SPACE ! 1753: if (argvec[count].partial) ! 1754: argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; ! 1755: #endif ! 1756: ! 1757: if (argvec[count].reg == 0 || argvec[count].partial != 0 ! 1758: #ifdef REG_PARM_STACK_SPACE ! 1759: || 1 ! 1760: #endif ! 1761: ) ! 1762: args_size.constant += argvec[count].size.constant; ! 1763: ! 1764: #ifdef ACCUMULATE_OUTGOING_ARGS ! 1765: /* If this arg is actually passed on the stack, it might be ! 1766: clobbering something we already put there (this library call might ! 1767: be inside the evaluation of an argument to a function whose call ! 1768: requires the stack). This will only occur when the library call ! 1769: has sufficient args to run out of argument registers. Abort in ! 1770: this case; if this ever occurs, code must be added to save and ! 1771: restore the arg slot. */ ! 1772: ! 1773: if (argvec[count].reg == 0 || argvec[count].partial != 0) ! 1774: abort (); ! 1775: #endif ! 1776: ! 1777: FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1); ! 1778: } ! 1779: va_end (p); ! 1780: ! 1781: /* If this machine requires an external definition for library ! 1782: functions, write one out. */ ! 1783: assemble_external_libcall (fun); ! 1784: ! 1785: #ifdef STACK_BOUNDARY ! 1786: args_size.constant = (((args_size.constant + (STACK_BYTES - 1)) ! 1787: / STACK_BYTES) * STACK_BYTES); ! 1788: #endif ! 1789: ! 1790: #ifdef REG_PARM_STACK_SPACE ! 1791: args_size.constant = MAX (args_size.constant, ! 1792: REG_PARM_STACK_SPACE ((tree) 0)); ! 1793: #endif ! 1794: ! 1795: #ifdef ACCUMULATE_OUTGOING_ARGS ! 1796: if (args_size.constant > current_function_outgoing_args_size) ! 1797: current_function_outgoing_args_size = args_size.constant; ! 1798: args_size.constant = 0; ! 1799: #endif ! 1800: ! 1801: #ifndef PUSH_ROUNDING ! 1802: argblock = push_block (gen_rtx (CONST_INT, VOIDmode, args_size.constant), ! 1803: 0, 0); ! 1804: #endif ! 1805: ! 1806: #ifdef PUSH_ARGS_REVERSED ! 1807: inc = -1; ! 1808: argnum = nargs - 1; ! 1809: #else ! 1810: inc = 1; ! 1811: argnum = 0; ! 1812: #endif ! 1813: ! 1814: /* Push the args that need to be pushed. */ ! 1815: ! 1816: for (count = 0; count < nargs; count++, argnum += inc) ! 1817: { ! 1818: register enum machine_mode mode = argvec[argnum].mode; ! 1819: register rtx val = argvec[argnum].value; ! 1820: rtx reg = argvec[argnum].reg; ! 1821: int partial = argvec[argnum].partial; ! 1822: ! 1823: if (! (reg != 0 && partial == 0)) ! 1824: emit_push_insn (val, mode, 0, 0, 0, partial, reg, 0, argblock, ! 1825: gen_rtx (CONST_INT, VOIDmode, ! 1826: argvec[count].offset.constant)); ! 1827: NO_DEFER_POP; ! 1828: } ! 1829: ! 1830: #ifdef PUSH_ARGS_REVERSED ! 1831: argnum = nargs - 1; ! 1832: #else ! 1833: argnum = 0; ! 1834: #endif ! 1835: ! 1836: /* Now load any reg parms into their regs. */ ! 1837: ! 1838: for (count = 0; count < nargs; count++, argnum += inc) ! 1839: { ! 1840: register enum machine_mode mode = argvec[argnum].mode; ! 1841: register rtx val = argvec[argnum].value; ! 1842: rtx reg = argvec[argnum].reg; ! 1843: int partial = argvec[argnum].partial; ! 1844: ! 1845: if (reg != 0 && partial == 0) ! 1846: emit_move_insn (reg, val); ! 1847: NO_DEFER_POP; ! 1848: } ! 1849: ! 1850: /* For version 1.37, try deleting this entirely. */ ! 1851: if (! no_queue) ! 1852: emit_queue (); ! 1853: ! 1854: /* Any regs containing parms remain in use through the call. */ ! 1855: start_sequence (); ! 1856: for (count = 0; count < nargs; count++) ! 1857: if (argvec[count].reg != 0) ! 1858: emit_insn (gen_rtx (USE, VOIDmode, argvec[count].reg)); ! 1859: ! 1860: use_insns = get_insns (); ! 1861: end_sequence (); ! 1862: ! 1863: fun = prepare_call_address (fun, 0, &use_insns); ! 1864: ! 1865: /* Don't allow popping to be deferred, since then ! 1866: cse'ing of library calls could delete a call and leave the pop. */ ! 1867: NO_DEFER_POP; ! 1868: ! 1869: /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which ! 1870: will set inhibit_defer_pop to that value. */ ! 1871: ! 1872: emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, ! 1873: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), ! 1874: outmode != VOIDmode ? hard_libcall_value (outmode) : 0, ! 1875: old_inhibit_defer_pop + 1, use_insns, no_queue); ! 1876: ! 1877: /* Now restore inhibit_defer_pop to its actual original value. */ ! 1878: OK_DEFER_POP; ! 1879: } ! 1880: ! 1881: /* Expand an assignment that stores the value of FROM into TO. ! 1882: If WANT_VALUE is nonzero, return an rtx for the value of TO. ! 1883: (This may contain a QUEUED rtx.) ! 1884: Otherwise, the returned value is not meaningful. ! 1885: ! 1886: SUGGEST_REG is no longer actually used. ! 1887: It used to mean, copy the value through a register ! 1888: and return that register, if that is possible. ! 1889: But now we do this if WANT_VALUE. ! 1890: ! 1891: If the value stored is a constant, we return the constant. */ ! 1892: ! 1893: rtx ! 1894: expand_assignment (to, from, want_value, suggest_reg) ! 1895: tree to, from; ! 1896: int want_value; ! 1897: int suggest_reg; ! 1898: { ! 1899: register rtx to_rtx = 0; ! 1900: rtx result; ! 1901: ! 1902: /* Don't crash if the lhs of the assignment was erroneous. */ ! 1903: ! 1904: if (TREE_CODE (to) == ERROR_MARK) ! 1905: return expand_expr (from, 0, VOIDmode, 0); ! 1906: ! 1907: /* Assignment of a structure component needs special treatment ! 1908: if the structure component's rtx is not simply a MEM. ! 1909: Assignment of an array element at a constant index ! 1910: has the same problem. */ ! 1911: ! 1912: if (TREE_CODE (to) == COMPONENT_REF ! 1913: || TREE_CODE (to) == BIT_FIELD_REF ! 1914: || (TREE_CODE (to) == ARRAY_REF ! 1915: && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST ! 1916: && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST)) ! 1917: { ! 1918: enum machine_mode mode1; ! 1919: int bitsize; ! 1920: int bitpos; ! 1921: int unsignedp; ! 1922: int volatilep = 0; ! 1923: tree tem = get_inner_reference (to, &bitsize, &bitpos, ! 1924: &mode1, &unsignedp, &volatilep); ! 1925: ! 1926: /* If we are going to use store_bit_field and extract_bit_field, ! 1927: make sure to_rtx will be safe for multiple use. */ ! 1928: ! 1929: if (mode1 == VOIDmode && want_value) ! 1930: tem = stabilize_reference (tem); ! 1931: ! 1932: to_rtx = expand_expr (tem, 0, VOIDmode, 0); ! 1933: if (volatilep) ! 1934: { ! 1935: if (GET_CODE (to_rtx) == MEM) ! 1936: MEM_VOLATILE_P (to_rtx) = 1; ! 1937: #if 0 /* This was turned off because, when a field is volatile ! 1938: in an object which is not volatile, the object may be in a register, ! 1939: and then we would abort over here. */ ! 1940: else ! 1941: abort (); ! 1942: #endif ! 1943: } ! 1944: ! 1945: result = store_field (to_rtx, bitsize, bitpos, mode1, from, ! 1946: (want_value ! 1947: /* Spurious cast makes HPUX compiler happy. */ ! 1948: ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to)) ! 1949: : VOIDmode), ! 1950: unsignedp, ! 1951: /* Required alignment of containing datum. */ ! 1952: TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT, ! 1953: int_size_in_bytes (TREE_TYPE (tem))); ! 1954: preserve_temp_slots (result); ! 1955: free_temp_slots (); ! 1956: ! 1957: return result; ! 1958: } ! 1959: ! 1960: /* Ordinary treatment. Expand TO to get a REG or MEM rtx. ! 1961: Don't re-expand if it was expanded already (in COMPONENT_REF case). */ ! 1962: ! 1963: if (to_rtx == 0) ! 1964: to_rtx = expand_expr (to, 0, VOIDmode, 0); ! 1965: ! 1966: /* In case we are returning the contents of an object which overlaps ! 1967: the place the value is being stored, use a safe function when copying ! 1968: a value through a pointer into a structure value return block. */ ! 1969: if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF ! 1970: && current_function_returns_struct ! 1971: && !current_function_returns_pcc_struct) ! 1972: { ! 1973: rtx from_rtx = expand_expr (from, 0, VOIDmode, 0); ! 1974: rtx size = expr_size (from); ! 1975: ! 1976: #ifdef TARGET_MEM_FUNCTIONS ! 1977: emit_library_call (memcpy_libfunc, 0, ! 1978: VOIDmode, 3, XEXP (to_rtx, 0), Pmode, ! 1979: XEXP (from_rtx, 0), Pmode, ! 1980: size, Pmode); ! 1981: #else ! 1982: emit_library_call (bcopy_libfunc, 0, ! 1983: VOIDmode, 3, XEXP (from_rtx, 0), Pmode, ! 1984: XEXP (to_rtx, 0), Pmode, ! 1985: size, Pmode); ! 1986: #endif ! 1987: ! 1988: preserve_temp_slots (to_rtx); ! 1989: free_temp_slots (); ! 1990: return to_rtx; ! 1991: } ! 1992: ! 1993: /* Compute FROM and store the value in the rtx we got. */ ! 1994: ! 1995: result = store_expr (from, to_rtx, want_value); ! 1996: preserve_temp_slots (result); ! 1997: free_temp_slots (); ! 1998: return result; ! 1999: } ! 2000: ! 2001: /* Generate code for computing expression EXP, ! 2002: and storing the value into TARGET. ! 2003: Returns TARGET or an equivalent value. ! 2004: TARGET may contain a QUEUED rtx. ! 2005: ! 2006: If SUGGEST_REG is nonzero, copy the value through a register ! 2007: and return that register, if that is possible. ! 2008: ! 2009: If the value stored is a constant, we return the constant. */ ! 2010: ! 2011: rtx ! 2012: store_expr (exp, target, suggest_reg) ! 2013: register tree exp; ! 2014: register rtx target; ! 2015: int suggest_reg; ! 2016: { ! 2017: register rtx temp; ! 2018: int dont_return_target = 0; ! 2019: ! 2020: if (TREE_CODE (exp) == COMPOUND_EXPR) ! 2021: { ! 2022: /* Perform first part of compound expression, then assign from second ! 2023: part. */ ! 2024: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 2025: emit_queue (); ! 2026: return store_expr (TREE_OPERAND (exp, 1), target, suggest_reg); ! 2027: } ! 2028: else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode) ! 2029: { ! 2030: /* For conditional expression, get safe form of the target. Then ! 2031: test the condition, doing the appropriate assignment on either ! 2032: side. This avoids the creation of unnecessary temporaries. ! 2033: For non-BLKmode, it is more efficient not to do this. */ ! 2034: ! 2035: rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx (); ! 2036: ! 2037: emit_queue (); ! 2038: target = protect_from_queue (target, 1); ! 2039: ! 2040: NO_DEFER_POP; ! 2041: jumpifnot (TREE_OPERAND (exp, 0), lab1); ! 2042: store_expr (TREE_OPERAND (exp, 1), target, suggest_reg); ! 2043: emit_queue (); ! 2044: emit_jump_insn (gen_jump (lab2)); ! 2045: emit_barrier (); ! 2046: emit_label (lab1); ! 2047: store_expr (TREE_OPERAND (exp, 2), target, suggest_reg); ! 2048: emit_queue (); ! 2049: emit_label (lab2); ! 2050: OK_DEFER_POP; ! 2051: return target; ! 2052: } ! 2053: else if (suggest_reg && GET_CODE (target) == MEM ! 2054: && GET_MODE (target) != BLKmode) ! 2055: /* If target is in memory and caller wants value in a register instead, ! 2056: arrange that. Pass TARGET as target for expand_expr so that, ! 2057: if EXP is another assignment, SUGGEST_REG will be nonzero for it. ! 2058: We know expand_expr will not use the target in that case. */ ! 2059: { ! 2060: temp = expand_expr (exp, cse_not_expected ? 0 : target, ! 2061: GET_MODE (target), 0); ! 2062: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) ! 2063: temp = copy_to_reg (temp); ! 2064: dont_return_target = 1; ! 2065: } ! 2066: else if (queued_subexp_p (target)) ! 2067: /* If target contains a postincrement, it is not safe ! 2068: to use as the returned value. It would access the wrong ! 2069: place by the time the queued increment gets output. ! 2070: So copy the value through a temporary and use that temp ! 2071: as the result. */ ! 2072: { ! 2073: if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode) ! 2074: { ! 2075: /* Expand EXP into a new pseudo. */ ! 2076: temp = gen_reg_rtx (GET_MODE (target)); ! 2077: temp = expand_expr (exp, temp, GET_MODE (target), 0); ! 2078: } ! 2079: else ! 2080: temp = expand_expr (exp, 0, GET_MODE (target), 0); ! 2081: dont_return_target = 1; ! 2082: } ! 2083: else ! 2084: { ! 2085: temp = expand_expr (exp, target, GET_MODE (target), 0); ! 2086: /* DO return TARGET if it's a specified hardware register. ! 2087: expand_return relies on this. */ ! 2088: if (!(target && GET_CODE (target) == REG ! 2089: && REGNO (target) < FIRST_PSEUDO_REGISTER) ! 2090: && CONSTANT_P (temp)) ! 2091: dont_return_target = 1; ! 2092: } ! 2093: ! 2094: /* If value was not generated in the target, store it there. ! 2095: Convert the value to TARGET's type first if nec. */ ! 2096: ! 2097: if (temp != target && TREE_CODE (exp) != ERROR_MARK) ! 2098: { ! 2099: target = protect_from_queue (target, 1); ! 2100: if (GET_MODE (temp) != GET_MODE (target) ! 2101: && GET_MODE (temp) != VOIDmode) ! 2102: { ! 2103: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 2104: if (dont_return_target) ! 2105: { ! 2106: /* In this case, we will return TEMP, ! 2107: so make sure it has the proper mode. ! 2108: But don't forget to store the value into TARGET. */ ! 2109: temp = convert_to_mode (GET_MODE (target), temp, unsignedp); ! 2110: emit_move_insn (target, temp); ! 2111: } ! 2112: else ! 2113: convert_move (target, temp, unsignedp); ! 2114: } ! 2115: ! 2116: else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST) ! 2117: { ! 2118: /* Handle copying a string constant into an array. ! 2119: The string constant may be shorter than the array. ! 2120: So copy just the string's actual length, and clear the rest. */ ! 2121: rtx size; ! 2122: ! 2123: emit_block_move (target, temp, ! 2124: gen_rtx (CONST_INT, VOIDmode, ! 2125: TREE_STRING_LENGTH (exp)), ! 2126: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 2127: ! 2128: temp = plus_constant (XEXP (target, 0), TREE_STRING_LENGTH (exp)); ! 2129: size = plus_constant (expr_size (exp), - TREE_STRING_LENGTH (exp)); ! 2130: if (size != const0_rtx) ! 2131: { ! 2132: #ifdef TARGET_MEM_FUNCTIONS ! 2133: emit_library_call (memset_libfunc, 0, VOIDmode, 3, ! 2134: temp, Pmode, const0_rtx, Pmode, size, Pmode); ! 2135: #else ! 2136: emit_library_call (bzero_libfunc, 0, VOIDmode, 2, ! 2137: temp, Pmode, size, Pmode); ! 2138: #endif ! 2139: } ! 2140: } ! 2141: else if (GET_MODE (temp) == BLKmode) ! 2142: emit_block_move (target, temp, expr_size (exp), ! 2143: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 2144: else ! 2145: emit_move_insn (target, temp); ! 2146: } ! 2147: if (dont_return_target) ! 2148: return temp; ! 2149: return target; ! 2150: } ! 2151: ! 2152: /* Store the value of constructor EXP into the rtx TARGET. ! 2153: TARGET is either a REG or a MEM. */ ! 2154: ! 2155: static void ! 2156: store_constructor (exp, target) ! 2157: tree exp; ! 2158: rtx target; ! 2159: { ! 2160: /* We know our target cannot conflict, since safe_from_p has been called. */ ! 2161: #if 0 ! 2162: /* Don't try copying piece by piece into a hard register ! 2163: since that is vulnerable to being clobbered by EXP. ! 2164: Instead, construct in a pseudo register and then copy it all. */ ! 2165: if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER) ! 2166: { ! 2167: rtx temp = gen_reg_rtx (GET_MODE (target)); ! 2168: store_constructor (exp, temp); ! 2169: emit_move_insn (target, temp); ! 2170: return; ! 2171: } ! 2172: #endif ! 2173: ! 2174: if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE ! 2175: || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE) ! 2176: { ! 2177: register tree elt; ! 2178: ! 2179: if (TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE) ! 2180: /* Inform later passes that the whole union value is dead. */ ! 2181: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2182: /* If the constructor has fewer fields than the structure, ! 2183: clear the whole structure first. */ ! 2184: else if (list_length (CONSTRUCTOR_ELTS (exp)) ! 2185: != list_length (TYPE_FIELDS (TREE_TYPE (exp)))) ! 2186: clear_storage (target, int_size_in_bytes (TREE_TYPE (exp))); ! 2187: else ! 2188: /* Inform later passes that the old value is dead. */ ! 2189: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2190: ! 2191: /* Store each element of the constructor into ! 2192: the corresponding field of TARGET. */ ! 2193: ! 2194: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 2195: { ! 2196: register tree field = TREE_PURPOSE (elt); ! 2197: register enum machine_mode mode; ! 2198: int bitsize; ! 2199: int bitpos; ! 2200: int unsignedp; ! 2201: ! 2202: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); ! 2203: unsignedp = TREE_UNSIGNED (field); ! 2204: mode = DECL_MODE (field); ! 2205: if (DECL_BIT_FIELD (field)) ! 2206: mode = VOIDmode; ! 2207: ! 2208: if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST) ! 2209: /* ??? This case remains to be written. */ ! 2210: abort (); ! 2211: ! 2212: bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); ! 2213: ! 2214: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! 2215: /* The alignment of TARGET is ! 2216: at least what its type requires. */ ! 2217: VOIDmode, 0, ! 2218: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT, ! 2219: int_size_in_bytes (TREE_TYPE (exp))); ! 2220: } ! 2221: } ! 2222: else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) ! 2223: { ! 2224: register tree elt; ! 2225: register int i; ! 2226: tree domain = TYPE_DOMAIN (TREE_TYPE (exp)); ! 2227: int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! 2228: int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); ! 2229: tree elttype = TREE_TYPE (TREE_TYPE (exp)); ! 2230: ! 2231: /* If the constructor has fewer fields than the structure, ! 2232: clear the whole structure first. */ ! 2233: ! 2234: if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1) ! 2235: clear_storage (target, maxelt - minelt + 1); ! 2236: else ! 2237: /* Inform later passes that the old value is dead. */ ! 2238: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2239: ! 2240: /* Store each element of the constructor into ! 2241: the corresponding element of TARGET, determined ! 2242: by counting the elements. */ ! 2243: for (elt = CONSTRUCTOR_ELTS (exp), i = 0; ! 2244: elt; ! 2245: elt = TREE_CHAIN (elt), i++) ! 2246: { ! 2247: register enum machine_mode mode; ! 2248: int bitsize; ! 2249: int bitpos; ! 2250: int unsignedp; ! 2251: ! 2252: mode = TYPE_MODE (elttype); ! 2253: bitsize = GET_MODE_BITSIZE (mode); ! 2254: unsignedp = TREE_UNSIGNED (elttype); ! 2255: ! 2256: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))); ! 2257: ! 2258: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! 2259: /* The alignment of TARGET is ! 2260: at least what its type requires. */ ! 2261: VOIDmode, 0, ! 2262: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT, ! 2263: int_size_in_bytes (TREE_TYPE (exp))); ! 2264: } ! 2265: } ! 2266: ! 2267: else ! 2268: abort (); ! 2269: } ! 2270: ! 2271: /* Store the value of EXP (an expression tree) ! 2272: into a subfield of TARGET which has mode MODE and occupies ! 2273: BITSIZE bits, starting BITPOS bits from the start of TARGET. ! 2274: If MODE is VOIDmode, it means that we are storing into a bit-field. ! 2275: ! 2276: If VALUE_MODE is VOIDmode, return nothing in particular. ! 2277: UNSIGNEDP is not used in this case. ! 2278: ! 2279: Otherwise, return an rtx for the value stored. This rtx ! 2280: has mode VALUE_MODE if that is convenient to do. ! 2281: In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. ! 2282: ! 2283: ALIGN is the alignment that TARGET is known to have, measured in bytes. ! 2284: TOTAL_SIZE is the size in bytes of the structure, or -1 if varying. */ ! 2285: ! 2286: static rtx ! 2287: store_field (target, bitsize, bitpos, mode, exp, value_mode, ! 2288: unsignedp, align, total_size) ! 2289: rtx target; ! 2290: int bitsize, bitpos; ! 2291: enum machine_mode mode; ! 2292: tree exp; ! 2293: enum machine_mode value_mode; ! 2294: int unsignedp; ! 2295: int align; ! 2296: int total_size; ! 2297: { ! 2298: int width_mask = 0; ! 2299: ! 2300: if (bitsize < HOST_BITS_PER_INT) ! 2301: width_mask = (1 << bitsize) - 1; ! 2302: ! 2303: /* If we are storing into an unaligned field of an aligned union that is ! 2304: in a register, we may have the mode of TARGET being an integer mode but ! 2305: MODE == BLKmode. In that case, get an aligned object whose size and ! 2306: alignment are the same as TARGET and store TARGET into it (we can avoid ! 2307: the store if the field being stored is the entire width of TARGET). Then ! 2308: call ourselves recursively to store the field into a BLKmode version of ! 2309: that object. Finally, load from the object into TARGET. This is not ! 2310: very efficient in general, but should only be slightly more expensive ! 2311: than the otherwise-required unaligned accesses. Perhaps this can be ! 2312: cleaned up later. */ ! 2313: ! 2314: if (mode == BLKmode ! 2315: && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG)) ! 2316: { ! 2317: rtx object = assign_stack_temp (GET_MODE (target), ! 2318: GET_MODE_SIZE (GET_MODE (target)), 0); ! 2319: rtx blk_object = copy_rtx (object); ! 2320: ! 2321: PUT_MODE (blk_object, BLKmode); ! 2322: ! 2323: if (bitsize != GET_MODE_BITSIZE (GET_MODE (target))) ! 2324: emit_move_insn (object, target); ! 2325: ! 2326: store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, ! 2327: align, total_size); ! 2328: ! 2329: emit_move_insn (target, object); ! 2330: ! 2331: return target; ! 2332: } ! 2333: ! 2334: /* If the structure is in a register or if the component ! 2335: is a bit field, we cannot use addressing to access it. ! 2336: Use bit-field techniques or SUBREG to store in it. */ ! 2337: ! 2338: if (mode == VOIDmode || GET_CODE (target) == REG ! 2339: || GET_CODE (target) == SUBREG) ! 2340: { ! 2341: rtx temp = expand_expr (exp, 0, VOIDmode, 0); ! 2342: /* Store the value in the bitfield. */ ! 2343: store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size); ! 2344: if (value_mode != VOIDmode) ! 2345: { ! 2346: /* The caller wants an rtx for the value. */ ! 2347: /* If possible, avoid refetching from the bitfield itself. */ ! 2348: if (width_mask != 0 ! 2349: && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))) ! 2350: return expand_and (temp, ! 2351: gen_rtx (CONST_INT, VOIDmode, width_mask), 0); ! 2352: return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 2353: 0, value_mode, 0, align, total_size); ! 2354: } ! 2355: return const0_rtx; ! 2356: } ! 2357: else ! 2358: { ! 2359: rtx addr = XEXP (target, 0); ! 2360: rtx to_rtx; ! 2361: ! 2362: /* If a value is wanted, it must be the lhs; ! 2363: so make the address stable for multiple use. */ ! 2364: ! 2365: if (value_mode != VOIDmode && GET_CODE (addr) != REG ! 2366: && ! CONSTANT_ADDRESS_P (addr) ! 2367: /* A frame-pointer reference is already stable. */ ! 2368: && ! (GET_CODE (addr) == PLUS ! 2369: && GET_CODE (XEXP (addr, 1)) == CONST_INT ! 2370: && (XEXP (addr, 0) == virtual_incoming_args_rtx ! 2371: || XEXP (addr, 0) == virtual_stack_vars_rtx))) ! 2372: addr = copy_to_reg (addr); ! 2373: ! 2374: /* Now build a reference to just the desired component. */ ! 2375: ! 2376: to_rtx = change_address (target, mode, ! 2377: plus_constant (addr, (bitpos / BITS_PER_UNIT))); ! 2378: MEM_IN_STRUCT_P (to_rtx) = 1; ! 2379: ! 2380: return store_expr (exp, to_rtx, value_mode != VOIDmode); ! 2381: } ! 2382: } ! 2383: ! 2384: /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF, ! 2385: or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or ! 2386: ARRAY_REFs at constant positions and find the ultimate containing object, ! 2387: which we return. ! 2388: ! 2389: We set *PBITSIZE to the size in bits that we want, *PBITPOS to the ! 2390: bit position, and *PUNSIGNEDP to the signedness of the field. ! 2391: ! 2392: If any of the extraction expressions is volatile, ! 2393: we store 1 in *PVOLATILEP. Otherwise we don't change that. ! 2394: ! 2395: If the field is a bit-field, *PMODE is set to VOIDmode. Otherwise, it ! 2396: is a mode that can be used to access the field. In that case, *PBITSIZE ! 2397: is redundant. */ ! 2398: ! 2399: tree ! 2400: get_inner_reference (exp, pbitsize, pbitpos, pmode, punsignedp, pvolatilep) ! 2401: tree exp; ! 2402: int *pbitsize; ! 2403: int *pbitpos; ! 2404: enum machine_mode *pmode; ! 2405: int *punsignedp; ! 2406: int *pvolatilep; ! 2407: { ! 2408: tree size_tree = 0; ! 2409: enum machine_mode mode = VOIDmode; ! 2410: ! 2411: if (TREE_CODE (exp) == COMPONENT_REF) ! 2412: { ! 2413: size_tree = DECL_SIZE (TREE_OPERAND (exp, 1)); ! 2414: if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1))) ! 2415: mode = DECL_MODE (TREE_OPERAND (exp, 1)); ! 2416: *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1)); ! 2417: } ! 2418: else if (TREE_CODE (exp) == BIT_FIELD_REF) ! 2419: { ! 2420: size_tree = TREE_OPERAND (exp, 1); ! 2421: *punsignedp = TREE_UNSIGNED (exp); ! 2422: } ! 2423: else ! 2424: { ! 2425: mode = TYPE_MODE (TREE_TYPE (exp)); ! 2426: *pbitsize = GET_MODE_BITSIZE (mode); ! 2427: *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 2428: } ! 2429: ! 2430: if (size_tree) ! 2431: { ! 2432: if (TREE_CODE (size_tree) != INTEGER_CST) ! 2433: abort (); ! 2434: ! 2435: *pbitsize = TREE_INT_CST_LOW (size_tree); ! 2436: } ! 2437: ! 2438: /* Compute cumulative bit-offset for nested component-refs and array-refs, ! 2439: and find the ultimate containing object. */ ! 2440: ! 2441: *pbitpos = 0; ! 2442: ! 2443: while (1) ! 2444: { ! 2445: if (TREE_CODE (exp) == COMPONENT_REF) ! 2446: { ! 2447: tree field = TREE_OPERAND (exp, 1); ! 2448: ! 2449: if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST) ! 2450: /* ??? This case remains to be written. */ ! 2451: abort (); ! 2452: ! 2453: *pbitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); ! 2454: if (TREE_THIS_VOLATILE (exp)) ! 2455: *pvolatilep = 1; ! 2456: } ! 2457: else if (TREE_CODE (exp) == BIT_FIELD_REF) ! 2458: { ! 2459: if (TREE_CODE (TREE_OPERAND (exp, 2)) != INTEGER_CST) ! 2460: /* ??? This case remains to be written. */ ! 2461: abort (); ! 2462: ! 2463: *pbitpos += TREE_INT_CST_LOW (TREE_OPERAND (exp, 2)); ! 2464: if (TREE_THIS_VOLATILE (exp)) ! 2465: *pvolatilep = 1; ! 2466: } ! 2467: else if (TREE_CODE (exp) == ARRAY_REF ! 2468: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 2469: && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST) ! 2470: { ! 2471: *pbitpos += (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! 2472: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))); ! 2473: if (TREE_THIS_VOLATILE (exp)) ! 2474: *pvolatilep = 1; ! 2475: } ! 2476: else if (TREE_CODE (exp) != NON_LVALUE_EXPR ! 2477: && ! ((TREE_CODE (exp) == NOP_EXPR ! 2478: || TREE_CODE (exp) == CONVERT_EXPR) ! 2479: && (TYPE_MODE (TREE_TYPE (exp)) ! 2480: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))) ! 2481: break; ! 2482: exp = TREE_OPERAND (exp, 0); ! 2483: } ! 2484: ! 2485: /* If this was a bit-field, see if there is a mode that allows direct ! 2486: access in case EXP is in memory. */ ! 2487: if (mode == VOIDmode && *pbitpos % *pbitsize == 0) ! 2488: { ! 2489: mode = mode_for_size (*pbitsize, MODE_INT, 0); ! 2490: if (mode == BLKmode) ! 2491: mode = VOIDmode; ! 2492: } ! 2493: ! 2494: *pmode = mode; ! 2495: ! 2496: return exp; ! 2497: } ! 2498: ! 2499: /* Given an rtx VALUE that may contain additions and multiplications, ! 2500: return an equivalent value that just refers to a register or memory. ! 2501: This is done by generating instructions to perform the arithmetic ! 2502: and returning a pseudo-register containing the value. */ ! 2503: ! 2504: rtx ! 2505: force_operand (value, target) ! 2506: rtx value, target; ! 2507: { ! 2508: register optab binoptab = 0; ! 2509: /* Use a temporary to force order of execution of calls to ! 2510: `force_operand'. */ ! 2511: rtx tmp; ! 2512: register rtx op2; ! 2513: /* Use subtarget as the target for operand 0 of a binary operation. */ ! 2514: register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); ! 2515: ! 2516: if (GET_CODE (value) == PLUS) ! 2517: binoptab = add_optab; ! 2518: else if (GET_CODE (value) == MINUS) ! 2519: binoptab = sub_optab; ! 2520: else if (GET_CODE (value) == MULT) ! 2521: { ! 2522: op2 = XEXP (value, 1); ! 2523: if (!CONSTANT_P (op2) ! 2524: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 2525: subtarget = 0; ! 2526: tmp = force_operand (XEXP (value, 0), subtarget); ! 2527: return expand_mult (GET_MODE (value), tmp, ! 2528: force_operand (op2, 0), ! 2529: target, 0); ! 2530: } ! 2531: ! 2532: if (binoptab) ! 2533: { ! 2534: op2 = XEXP (value, 1); ! 2535: if (!CONSTANT_P (op2) ! 2536: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 2537: subtarget = 0; ! 2538: if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT) ! 2539: { ! 2540: binoptab = add_optab; ! 2541: op2 = negate_rtx (GET_MODE (value), op2); ! 2542: } ! 2543: ! 2544: /* Check for an addition with OP2 a constant integer and our first ! 2545: operand a PLUS of a virtual register and something else. In that ! 2546: case, we want to emit the sum of the virtual register and the ! 2547: constant first and then add the other value. This allows virtual ! 2548: register instantiation to simply modify the constant rather than ! 2549: creating another one around this addition. */ ! 2550: if (binoptab == add_optab && GET_CODE (op2) == CONST_INT ! 2551: && GET_CODE (XEXP (value, 0)) == PLUS ! 2552: && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG ! 2553: && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER ! 2554: && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER) ! 2555: { ! 2556: rtx temp = expand_binop (GET_MODE (value), binoptab, ! 2557: XEXP (XEXP (value, 0), 0), op2, ! 2558: subtarget, 0, OPTAB_LIB_WIDEN); ! 2559: return expand_binop (GET_MODE (value), binoptab, temp, ! 2560: force_operand (XEXP (XEXP (value, 0), 1), 0), ! 2561: target, 0, OPTAB_LIB_WIDEN); ! 2562: } ! 2563: ! 2564: tmp = force_operand (XEXP (value, 0), subtarget); ! 2565: return expand_binop (GET_MODE (value), binoptab, tmp, ! 2566: force_operand (op2, 0), ! 2567: target, 0, OPTAB_LIB_WIDEN); ! 2568: /* We give UNSIGNEP = 0 to expand_binop ! 2569: because the only operations we are expanding here are signed ones. */ ! 2570: } ! 2571: return value; ! 2572: } ! 2573: ! 2574: /* Subroutine of expand_expr: ! 2575: save the non-copied parts (LIST) of an expr (LHS), and return a list ! 2576: which can restore these values to their previous values, ! 2577: should something modify their storage. */ ! 2578: ! 2579: static tree ! 2580: save_noncopied_parts (lhs, list) ! 2581: tree lhs; ! 2582: tree list; ! 2583: { ! 2584: tree tail; ! 2585: tree parts = 0; ! 2586: ! 2587: for (tail = list; tail; tail = TREE_CHAIN (tail)) ! 2588: if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST) ! 2589: parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail))); ! 2590: else ! 2591: { ! 2592: tree part = TREE_VALUE (tail); ! 2593: tree part_type = TREE_TYPE (part); ! 2594: tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part, 0); ! 2595: rtx target = assign_stack_temp (TYPE_MODE (part_type), ! 2596: int_size_in_bytes (part_type), 0); ! 2597: if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0))) ! 2598: target = change_address (target, TYPE_MODE (part_type), 0); ! 2599: parts = tree_cons (to_be_saved, ! 2600: build (RTL_EXPR, part_type, 0, (tree) target), ! 2601: parts); ! 2602: store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0); ! 2603: } ! 2604: return parts; ! 2605: } ! 2606: ! 2607: /* Subroutine of expand_expr: ! 2608: record the non-copied parts (LIST) of an expr (LHS), and return a list ! 2609: which specifies the initial values of these parts. */ ! 2610: ! 2611: static tree ! 2612: init_noncopied_parts (lhs, list) ! 2613: tree lhs; ! 2614: tree list; ! 2615: { ! 2616: tree tail; ! 2617: tree parts = 0; ! 2618: ! 2619: for (tail = list; tail; tail = TREE_CHAIN (tail)) ! 2620: if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST) ! 2621: parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail))); ! 2622: else ! 2623: { ! 2624: tree part = TREE_VALUE (tail); ! 2625: tree part_type = TREE_TYPE (part); ! 2626: tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part, 0); ! 2627: parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts); ! 2628: } ! 2629: return parts; ! 2630: } ! 2631: ! 2632: /* Subroutine of expand_expr: return nonzero iff there is no way that ! 2633: EXP can reference X, which is being modified. */ ! 2634: ! 2635: static int ! 2636: safe_from_p (x, exp) ! 2637: rtx x; ! 2638: tree exp; ! 2639: { ! 2640: rtx exp_rtl = 0; ! 2641: int i, nops; ! 2642: ! 2643: if (x == 0) ! 2644: return 1; ! 2645: ! 2646: /* If this is a subreg of a hard register, declare it unsafe, otherwise, ! 2647: find the underlying pseudo. */ ! 2648: if (GET_CODE (x) == SUBREG) ! 2649: { ! 2650: x = SUBREG_REG (x); ! 2651: if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) ! 2652: return 0; ! 2653: } ! 2654: ! 2655: /* If X is a location in the outgoing argument area, it is always safe. */ ! 2656: if (GET_CODE (x) == MEM ! 2657: && (XEXP (x, 0) == virtual_outgoing_args_rtx ! 2658: || (GET_CODE (XEXP (x, 0)) == PLUS ! 2659: && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))) ! 2660: return 1; ! 2661: ! 2662: switch (TREE_CODE_CLASS (TREE_CODE (exp))) ! 2663: { ! 2664: case 'd': ! 2665: exp_rtl = DECL_RTL (exp); ! 2666: break; ! 2667: ! 2668: case 'c': ! 2669: return 1; ! 2670: ! 2671: case 'x': ! 2672: if (TREE_CODE (exp) == TREE_LIST) ! 2673: return (safe_from_p (x, TREE_VALUE (exp)) ! 2674: && (TREE_CHAIN (exp) == 0 ! 2675: || safe_from_p (x, TREE_CHAIN (exp)))); ! 2676: else ! 2677: return 0; ! 2678: ! 2679: case '1': ! 2680: return safe_from_p (x, TREE_OPERAND (exp, 0)); ! 2681: ! 2682: case '2': ! 2683: case '<': ! 2684: return (safe_from_p (x, TREE_OPERAND (exp, 0)) ! 2685: && safe_from_p (x, TREE_OPERAND (exp, 1))); ! 2686: ! 2687: case 'e': ! 2688: case 'r': ! 2689: /* Now do code-specific tests. EXP_RTL is set to any rtx we find in ! 2690: the expression. If it is set, we conflict iff we are that rtx or ! 2691: both are in memory. Otherwise, we check all operands of the ! 2692: expression recursively. */ ! 2693: ! 2694: switch (TREE_CODE (exp)) ! 2695: { ! 2696: case ADDR_EXPR: ! 2697: return staticp (TREE_OPERAND (exp, 0)); ! 2698: ! 2699: case INDIRECT_REF: ! 2700: if (GET_CODE (x) == MEM) ! 2701: return 0; ! 2702: break; ! 2703: ! 2704: case CALL_EXPR: ! 2705: exp_rtl = CALL_EXPR_RTL (exp); ! 2706: if (exp_rtl == 0) ! 2707: { ! 2708: /* Assume that the call will clobber all hard registers and ! 2709: all of memory. */ ! 2710: if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) ! 2711: || GET_CODE (x) == MEM) ! 2712: return 0; ! 2713: } ! 2714: ! 2715: break; ! 2716: ! 2717: case RTL_EXPR: ! 2718: exp_rtl = RTL_EXPR_RTL (exp); ! 2719: if (exp_rtl == 0) ! 2720: /* We don't know what this can modify. */ ! 2721: return 0; ! 2722: ! 2723: break; ! 2724: ! 2725: case WITH_CLEANUP_EXPR: ! 2726: exp_rtl = RTL_EXPR_RTL (exp); ! 2727: break; ! 2728: ! 2729: case SAVE_EXPR: ! 2730: exp_rtl = SAVE_EXPR_RTL (exp); ! 2731: break; ! 2732: ! 2733: case METHOD_CALL_EXPR: ! 2734: /* This takes a rtx argument, but shouldn't appear here. */ ! 2735: abort (); ! 2736: } ! 2737: ! 2738: /* If we have an rtx, we do not need to scan our operands. */ ! 2739: if (exp_rtl) ! 2740: break; ! 2741: ! 2742: nops = tree_code_length[(int) TREE_CODE (exp)]; ! 2743: for (i = 0; i < nops; i++) ! 2744: if (TREE_OPERAND (exp, i) != 0 ! 2745: && ! safe_from_p (x, TREE_OPERAND (exp, i))) ! 2746: return 0; ! 2747: } ! 2748: ! 2749: /* If we have an rtl, find any enclosed object. Then see if we conflict ! 2750: with it. */ ! 2751: if (exp_rtl) ! 2752: { ! 2753: if (GET_CODE (exp_rtl) == SUBREG) ! 2754: { ! 2755: exp_rtl = SUBREG_REG (exp_rtl); ! 2756: if (GET_CODE (exp_rtl) == REG ! 2757: && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER) ! 2758: return 0; ! 2759: } ! 2760: ! 2761: /* If the rtl is X, then it is not safe. Otherwise, it is unless both ! 2762: are memory and EXP is not readonly. */ ! 2763: return ! (rtx_equal_p (x, exp_rtl) ! 2764: || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM ! 2765: && ! TREE_READONLY (exp))); ! 2766: } ! 2767: ! 2768: /* If we reach here, it is safe. */ ! 2769: return 1; ! 2770: } ! 2771: ! 2772: /* Subroutine of expand_expr: return nonzero iff EXP is an ! 2773: expression whose type is statically determinable. */ ! 2774: ! 2775: static int ! 2776: fixed_type_p (exp) ! 2777: tree exp; ! 2778: { ! 2779: if (TREE_CODE (exp) == PARM_DECL ! 2780: || TREE_CODE (exp) == VAR_DECL ! 2781: || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR ! 2782: || TREE_CODE (exp) == COMPONENT_REF ! 2783: || TREE_CODE (exp) == ARRAY_REF) ! 2784: return 1; ! 2785: return 0; ! 2786: } ! 2787: ! 2788: /* expand_expr: generate code for computing expression EXP. ! 2789: An rtx for the computed value is returned. The value is never null. ! 2790: In the case of a void EXP, const0_rtx is returned. ! 2791: ! 2792: The value may be stored in TARGET if TARGET is nonzero. ! 2793: TARGET is just a suggestion; callers must assume that ! 2794: the rtx returned may not be the same as TARGET. ! 2795: ! 2796: If TARGET is CONST0_RTX, it means that the value will be ignored. ! 2797: ! 2798: If TMODE is not VOIDmode, it suggests generating the ! 2799: result in mode TMODE. But this is done only when convenient. ! 2800: Otherwise, TMODE is ignored and the value generated in its natural mode. ! 2801: TMODE is just a suggestion; callers must assume that ! 2802: the rtx returned may not have mode TMODE. ! 2803: ! 2804: EXPAND_CONST_ADDRESS says that it is okay to return a MEM ! 2805: with a constant address even if that address is not normally legitimate. ! 2806: EXPAND_INITIALIZER and EXPAND_SUM also have this effect. ! 2807: ! 2808: If MODIFIER is EXPAND_SUM then when EXP is an addition ! 2809: we can return an rtx of the form (MULT (REG ...) (CONST_INT ...)) ! 2810: or a nest of (PLUS ...) and (MINUS ...) where the terms are ! 2811: products as above, or REG or MEM, or constant. ! 2812: Ordinarily in such cases we would output mul or add instructions ! 2813: and then return a pseudo reg containing the sum. ! 2814: ! 2815: EXPAND_INITIALIZER is much like EXPAND_SUM except that ! 2816: it also marks a label as absolutely required (it can't be dead). ! 2817: This is used for outputting expressions used in intializers. */ ! 2818: ! 2819: rtx ! 2820: expand_expr (exp, target, tmode, modifier) ! 2821: register tree exp; ! 2822: rtx target; ! 2823: enum machine_mode tmode; ! 2824: enum expand_modifier modifier; ! 2825: { ! 2826: register rtx op0, op1, temp; ! 2827: tree type = TREE_TYPE (exp); ! 2828: int unsignedp = TREE_UNSIGNED (type); ! 2829: register enum machine_mode mode = TYPE_MODE (type); ! 2830: register enum tree_code code = TREE_CODE (exp); ! 2831: optab this_optab; ! 2832: /* Use subtarget as the target for operand 0 of a binary operation. */ ! 2833: rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); ! 2834: rtx original_target = target; ! 2835: int ignore = target == const0_rtx; ! 2836: tree context; ! 2837: ! 2838: /* Don't use hard regs as subtargets, because the combiner ! 2839: can only handle pseudo regs. */ ! 2840: if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER) ! 2841: subtarget = 0; ! 2842: /* Avoid subtargets inside loops, ! 2843: since they hide some invariant expressions. */ ! 2844: if (preserve_subexpressions_p ()) ! 2845: subtarget = 0; ! 2846: ! 2847: if (ignore) target = 0, original_target = 0; ! 2848: ! 2849: /* If will do cse, generate all results into pseudo registers ! 2850: since 1) that allows cse to find more things ! 2851: and 2) otherwise cse could produce an insn the machine ! 2852: cannot support. */ ! 2853: ! 2854: if (! cse_not_expected && mode != BLKmode && target ! 2855: && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 2856: target = subtarget; ! 2857: ! 2858: /* Ensure we reference a volatile object even if value is ignored. */ ! 2859: if (ignore && TREE_THIS_VOLATILE (exp) ! 2860: && mode != VOIDmode && mode != BLKmode) ! 2861: { ! 2862: target = gen_reg_rtx (mode); ! 2863: temp = expand_expr (exp, target, VOIDmode, modifier); ! 2864: if (temp != target) ! 2865: emit_move_insn (target, temp); ! 2866: return target; ! 2867: } ! 2868: ! 2869: switch (code) ! 2870: { ! 2871: case LABEL_DECL: ! 2872: if (modifier == EXPAND_INITIALIZER) ! 2873: forced_labels = gen_rtx (EXPR_LIST, VOIDmode, ! 2874: label_rtx (exp), forced_labels); ! 2875: return gen_rtx (MEM, FUNCTION_MODE, ! 2876: gen_rtx (LABEL_REF, Pmode, label_rtx (exp))); ! 2877: ! 2878: case PARM_DECL: ! 2879: if (DECL_RTL (exp) == 0) ! 2880: { ! 2881: error_with_decl (exp, "prior parameter's size depends on `%s'"); ! 2882: return const0_rtx; ! 2883: } ! 2884: ! 2885: case FUNCTION_DECL: ! 2886: case VAR_DECL: ! 2887: case RESULT_DECL: ! 2888: if (DECL_RTL (exp) == 0) ! 2889: abort (); ! 2890: /* Ensure variable marked as used ! 2891: even if it doesn't go through a parser. */ ! 2892: TREE_USED (exp) = 1; ! 2893: /* Handle variables inherited from containing functions. */ ! 2894: context = decl_function_context (exp); ! 2895: ! 2896: /* We treat inline_function_decl as an alias for the current function ! 2897: because that is the inline function whose vars, types, etc. ! 2898: are being merged into the current function. ! 2899: See expand_inline_function. */ ! 2900: if (context != 0 && context != current_function_decl ! 2901: && context != inline_function_decl ! 2902: /* If var is static, we don't need a static chain to access it. */ ! 2903: && ! (GET_CODE (DECL_RTL (exp)) == MEM ! 2904: && CONSTANT_P (XEXP (DECL_RTL (exp), 0)))) ! 2905: { ! 2906: rtx addr; ! 2907: ! 2908: /* Mark as non-local and addressable. */ ! 2909: TREE_NONLOCAL (exp) = 1; ! 2910: mark_addressable (exp); ! 2911: if (GET_CODE (DECL_RTL (exp)) != MEM) ! 2912: abort (); ! 2913: addr = XEXP (DECL_RTL (exp), 0); ! 2914: if (GET_CODE (addr) == MEM) ! 2915: addr = gen_rtx (MEM, Pmode, fix_lexical_addr (XEXP (addr, 0), exp)); ! 2916: else ! 2917: addr = fix_lexical_addr (addr, exp); ! 2918: return change_address (DECL_RTL (exp), mode, addr); ! 2919: } ! 2920: /* This is the case of an array whose size is to be determined ! 2921: from its initializer, while the initializer is still being parsed. ! 2922: See expand_decl. */ ! 2923: if (GET_CODE (DECL_RTL (exp)) == MEM ! 2924: && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG) ! 2925: return change_address (DECL_RTL (exp), GET_MODE (DECL_RTL (exp)), ! 2926: XEXP (DECL_RTL (exp), 0)); ! 2927: if (GET_CODE (DECL_RTL (exp)) == MEM ! 2928: && modifier != EXPAND_CONST_ADDRESS ! 2929: && modifier != EXPAND_SUM ! 2930: && modifier != EXPAND_INITIALIZER) ! 2931: { ! 2932: /* DECL_RTL probably contains a constant address. ! 2933: On RISC machines where a constant address isn't valid, ! 2934: make some insns to get that address into a register. */ ! 2935: if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0)) ! 2936: || (flag_force_addr ! 2937: && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (exp), 0)))) ! 2938: return change_address (DECL_RTL (exp), VOIDmode, ! 2939: copy_rtx (XEXP (DECL_RTL (exp), 0))); ! 2940: } ! 2941: return DECL_RTL (exp); ! 2942: ! 2943: case INTEGER_CST: ! 2944: return immed_double_const (TREE_INT_CST_LOW (exp), ! 2945: TREE_INT_CST_HIGH (exp), ! 2946: mode); ! 2947: ! 2948: case CONST_DECL: ! 2949: return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); ! 2950: ! 2951: case REAL_CST: ! 2952: /* If optimized, generate immediate CONST_DOUBLE ! 2953: which will be turned into memory by reload if necessary. ! 2954: ! 2955: We used to force a register so that loop.c could see it. But ! 2956: this does not allow gen_* patterns to perform optimizations with ! 2957: the constants. It also produces two insns in cases like "x = 1.0;". ! 2958: On most machines, floating-point constants are not permitted in ! 2959: many insns, so we'd end up copying it to a register in any case. ! 2960: ! 2961: Now, we do the copying in expand_binop, if appropriate. */ ! 2962: return immed_real_const (exp); ! 2963: ! 2964: case COMPLEX_CST: ! 2965: case STRING_CST: ! 2966: if (! TREE_CST_RTL (exp)) ! 2967: output_constant_def (exp); ! 2968: ! 2969: /* TREE_CST_RTL probably contains a constant address. ! 2970: On RISC machines where a constant address isn't valid, ! 2971: make some insns to get that address into a register. */ ! 2972: if (GET_CODE (TREE_CST_RTL (exp)) == MEM ! 2973: && modifier != EXPAND_CONST_ADDRESS ! 2974: && modifier != EXPAND_INITIALIZER ! 2975: && modifier != EXPAND_SUM ! 2976: && !memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))) ! 2977: return change_address (TREE_CST_RTL (exp), VOIDmode, ! 2978: copy_rtx (XEXP (TREE_CST_RTL (exp), 0))); ! 2979: return TREE_CST_RTL (exp); ! 2980: ! 2981: case SAVE_EXPR: ! 2982: context = decl_function_context (exp); ! 2983: /* We treat inline_function_decl as an alias for the current function ! 2984: because that is the inline function whose vars, types, etc. ! 2985: are being merged into the current function. ! 2986: See expand_inline_function. */ ! 2987: if (context == current_function_decl || context == inline_function_decl) ! 2988: context = 0; ! 2989: ! 2990: /* If this is non-local, handle it. */ ! 2991: if (context) ! 2992: { ! 2993: temp = SAVE_EXPR_RTL (exp); ! 2994: if (temp && GET_CODE (temp) == REG) ! 2995: { ! 2996: put_var_into_stack (exp); ! 2997: temp = SAVE_EXPR_RTL (exp); ! 2998: } ! 2999: if (temp == 0 || GET_CODE (temp) != MEM) ! 3000: abort (); ! 3001: return change_address (temp, mode, ! 3002: fix_lexical_addr (XEXP (temp, 0), exp)); ! 3003: } ! 3004: if (SAVE_EXPR_RTL (exp) == 0) ! 3005: { ! 3006: if (mode == BLKmode) ! 3007: temp ! 3008: = assign_stack_temp (mode, ! 3009: int_size_in_bytes (TREE_TYPE (exp)), 0); ! 3010: else ! 3011: temp = gen_reg_rtx (mode); ! 3012: SAVE_EXPR_RTL (exp) = temp; ! 3013: store_expr (TREE_OPERAND (exp, 0), temp, 0); ! 3014: if (!optimize && GET_CODE (temp) == REG) ! 3015: save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, temp, ! 3016: save_expr_regs); ! 3017: } ! 3018: return SAVE_EXPR_RTL (exp); ! 3019: ! 3020: case EXIT_EXPR: ! 3021: /* Exit the current loop if the body-expression is true. */ ! 3022: { ! 3023: rtx label = gen_label_rtx (); ! 3024: do_jump (TREE_OPERAND (exp, 0), label, 0); ! 3025: expand_exit_loop (0); ! 3026: emit_label (label); ! 3027: } ! 3028: return const0_rtx; ! 3029: ! 3030: case LOOP_EXPR: ! 3031: expand_start_loop (1); ! 3032: expand_expr_stmt (TREE_OPERAND (exp, 0)); ! 3033: expand_end_loop (); ! 3034: ! 3035: return const0_rtx; ! 3036: ! 3037: case BIND_EXPR: ! 3038: { ! 3039: tree vars = TREE_OPERAND (exp, 0); ! 3040: int vars_need_expansion = 0; ! 3041: ! 3042: /* Need to open a binding contour here because ! 3043: if there are any cleanups they most be contained here. */ ! 3044: expand_start_bindings (0); ! 3045: ! 3046: /* Mark the corresponding BLOCK for output. */ ! 3047: if (TREE_OPERAND (exp, 2) != 0) ! 3048: TREE_USED (TREE_OPERAND (exp, 2)) = 1; ! 3049: ! 3050: /* If VARS have not yet been expanded, expand them now. */ ! 3051: while (vars) ! 3052: { ! 3053: if (DECL_RTL (vars) == 0) ! 3054: { ! 3055: vars_need_expansion = 1; ! 3056: expand_decl (vars); ! 3057: } ! 3058: expand_decl_init (vars); ! 3059: vars = TREE_CHAIN (vars); ! 3060: } ! 3061: ! 3062: temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); ! 3063: ! 3064: expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); ! 3065: ! 3066: return temp; ! 3067: } ! 3068: ! 3069: case RTL_EXPR: ! 3070: if (RTL_EXPR_SEQUENCE (exp) == const0_rtx) ! 3071: abort (); ! 3072: emit_insns (RTL_EXPR_SEQUENCE (exp)); ! 3073: RTL_EXPR_SEQUENCE (exp) = const0_rtx; ! 3074: return RTL_EXPR_RTL (exp); ! 3075: ! 3076: case CONSTRUCTOR: ! 3077: /* All elts simple constants => refer to a constant in memory. */ ! 3078: if (TREE_STATIC (exp)) ! 3079: /* For aggregate types with non-BLKmode modes, ! 3080: this should ideally construct a CONST_INT. */ ! 3081: { ! 3082: rtx constructor = output_constant_def (exp); ! 3083: if (! memory_address_p (GET_MODE (constructor), ! 3084: XEXP (constructor, 0))) ! 3085: constructor = change_address (constructor, VOIDmode, ! 3086: XEXP (constructor, 0)); ! 3087: return constructor; ! 3088: } ! 3089: ! 3090: if (ignore) ! 3091: { ! 3092: tree elt; ! 3093: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 3094: expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); ! 3095: return const0_rtx; ! 3096: } ! 3097: else ! 3098: { ! 3099: if (target == 0 || ! safe_from_p (target, exp)) ! 3100: { ! 3101: if (mode != BLKmode && ! TREE_ADDRESSABLE (exp)) ! 3102: target = gen_reg_rtx (mode); ! 3103: else ! 3104: { ! 3105: rtx safe_target = assign_stack_temp (mode, int_size_in_bytes (type), 0); ! 3106: if (target) ! 3107: MEM_IN_STRUCT_P (safe_target) = MEM_IN_STRUCT_P (target); ! 3108: target = safe_target; ! 3109: } ! 3110: } ! 3111: store_constructor (exp, target); ! 3112: return target; ! 3113: } ! 3114: ! 3115: case INDIRECT_REF: ! 3116: { ! 3117: tree exp1 = TREE_OPERAND (exp, 0); ! 3118: tree exp2; ! 3119: ! 3120: /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated ! 3121: for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR. ! 3122: This code has the same general effect as simply doing ! 3123: expand_expr on the save expr, except that the expression PTR ! 3124: is computed for use as a memory address. This means different ! 3125: code, suitable for indexing, may be generated. */ ! 3126: if (TREE_CODE (exp1) == SAVE_EXPR ! 3127: && SAVE_EXPR_RTL (exp1) == 0 ! 3128: && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK ! 3129: && TYPE_MODE (TREE_TYPE (exp1)) == Pmode ! 3130: && TYPE_MODE (TREE_TYPE (exp2)) == Pmode) ! 3131: { ! 3132: temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM); ! 3133: op0 = memory_address (mode, temp); ! 3134: op0 = copy_all_regs (op0); ! 3135: SAVE_EXPR_RTL (exp1) = op0; ! 3136: } ! 3137: else ! 3138: { ! 3139: op0 = expand_expr (exp1, 0, VOIDmode, EXPAND_SUM); ! 3140: op0 = memory_address (mode, op0); ! 3141: } ! 3142: } ! 3143: temp = gen_rtx (MEM, mode, op0); ! 3144: /* If address was computed by addition, ! 3145: mark this as an element of an aggregate. */ ! 3146: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR ! 3147: || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR ! 3148: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR) ! 3149: || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE ! 3150: || TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE ! 3151: || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE) ! 3152: MEM_IN_STRUCT_P (temp) = 1; ! 3153: MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) || flag_volatile; ! 3154: #if 0 /* It is incorrectto set RTX_UNCHANGING_P here, because the fact that ! 3155: a location is accessed through a pointer to const does not mean ! 3156: that the value there can never change. */ ! 3157: RTX_UNCHANGING_P (temp) = TREE_READONLY (exp); ! 3158: #endif ! 3159: return temp; ! 3160: ! 3161: case ARRAY_REF: ! 3162: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST ! 3163: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 3164: { ! 3165: /* Nonconstant array index or nonconstant element size. ! 3166: Generate the tree for *(&array+index) and expand that, ! 3167: except do it in a language-independent way ! 3168: and don't complain about non-lvalue arrays. ! 3169: `mark_addressable' should already have been called ! 3170: for any array for which this case will be reached. */ ! 3171: ! 3172: /* Don't forget the const or volatile flag from the array element. */ ! 3173: tree variant_type = build_type_variant (type, ! 3174: TREE_READONLY (exp), ! 3175: TREE_THIS_VOLATILE (exp)); ! 3176: tree array_adr = build1 (ADDR_EXPR, build_pointer_type (variant_type), ! 3177: TREE_OPERAND (exp, 0)); ! 3178: tree index = TREE_OPERAND (exp, 1); ! 3179: tree elt; ! 3180: ! 3181: /* Convert the integer argument to a type the same size as a pointer ! 3182: so the multiply won't overflow spuriously. */ ! 3183: if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE) ! 3184: index = convert (type_for_size (POINTER_SIZE, 0), index); ! 3185: ! 3186: /* Don't think the address has side effects ! 3187: just because the array does. ! 3188: (In some cases the address might have side effects, ! 3189: and we fail to record that fact here. However, it should not ! 3190: matter, since expand_expr should not care.) */ ! 3191: TREE_SIDE_EFFECTS (array_adr) = 0; ! 3192: ! 3193: elt = build1 (INDIRECT_REF, type, ! 3194: fold (build (PLUS_EXPR, TYPE_POINTER_TO (variant_type), ! 3195: array_adr, ! 3196: fold (build (MULT_EXPR, ! 3197: TYPE_POINTER_TO (variant_type), ! 3198: index, size_in_bytes (type)))))); ! 3199: ! 3200: /* Volatility, etc., of new expression is same as old expression. */ ! 3201: TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp); ! 3202: TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp); ! 3203: TREE_READONLY (elt) = TREE_READONLY (exp); ! 3204: ! 3205: return expand_expr (elt, target, tmode, modifier); ! 3206: } ! 3207: ! 3208: /* Fold an expression like: "foo"[2]. ! 3209: This is not done in fold so it won't happen inside &. */ ! 3210: { ! 3211: int i; ! 3212: tree arg0 = TREE_OPERAND (exp, 0); ! 3213: tree arg1 = TREE_OPERAND (exp, 1); ! 3214: ! 3215: if (TREE_CODE (arg0) == STRING_CST ! 3216: && TREE_CODE (arg1) == INTEGER_CST ! 3217: && !TREE_INT_CST_HIGH (arg1) ! 3218: && (i = TREE_INT_CST_LOW (arg1)) < TREE_STRING_LENGTH (arg0)) ! 3219: { ! 3220: if (TREE_TYPE (TREE_TYPE (arg0)) == integer_type_node) ! 3221: { ! 3222: exp = build_int_2 (((int *)TREE_STRING_POINTER (arg0))[i], 0); ! 3223: TREE_TYPE (exp) = integer_type_node; ! 3224: return expand_expr (exp, target, tmode, modifier); ! 3225: } ! 3226: if (TREE_TYPE (TREE_TYPE (arg0)) == char_type_node) ! 3227: { ! 3228: exp = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0); ! 3229: TREE_TYPE (exp) = integer_type_node; ! 3230: return expand_expr (convert (TREE_TYPE (TREE_TYPE (arg0)), exp), target, tmode, modifier); ! 3231: } ! 3232: } ! 3233: } ! 3234: ! 3235: /* If this is a constant index into a constant array, ! 3236: just get the value from the array. */ ! 3237: if (TREE_READONLY (TREE_OPERAND (exp, 0)) ! 3238: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 3239: && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE ! 3240: && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL ! 3241: && DECL_INITIAL (TREE_OPERAND (exp, 0)) ! 3242: && TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0))) != ERROR_MARK) ! 3243: { ! 3244: tree index = fold (TREE_OPERAND (exp, 1)); ! 3245: if (TREE_CODE (index) == INTEGER_CST) ! 3246: { ! 3247: int i = TREE_INT_CST_LOW (index); ! 3248: tree init = CONSTRUCTOR_ELTS (DECL_INITIAL (TREE_OPERAND (exp, 0))); ! 3249: ! 3250: while (init && i--) ! 3251: init = TREE_CHAIN (init); ! 3252: if (init) ! 3253: return expand_expr (fold (TREE_VALUE (init)), target, tmode, modifier); ! 3254: } ! 3255: } ! 3256: /* Treat array-ref with constant index as a component-ref. */ ! 3257: ! 3258: case COMPONENT_REF: ! 3259: case BIT_FIELD_REF: ! 3260: { ! 3261: enum machine_mode mode1; ! 3262: int bitsize; ! 3263: int bitpos; ! 3264: int volatilep = 0; ! 3265: tree tem = get_inner_reference (exp, &bitsize, &bitpos, ! 3266: &mode1, &unsignedp, &volatilep); ! 3267: ! 3268: /* In some cases, we will be offsetting OP0's address by a constant. ! 3269: So get it as a sum, if possible. If we will be using it ! 3270: directly in an insn, we validate it. */ ! 3271: op0 = expand_expr (tem, 0, VOIDmode, EXPAND_SUM); ! 3272: ! 3273: /* Don't forget about volatility even if this is a bitfield. */ ! 3274: if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0)) ! 3275: { ! 3276: op0 = copy_rtx (op0); ! 3277: MEM_VOLATILE_P (op0) = 1; ! 3278: } ! 3279: ! 3280: if (mode1 == VOIDmode ! 3281: || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) ! 3282: { ! 3283: /* In cases where an aligned union has an unaligned object ! 3284: as a field, we might be extracting a BLKmode value from ! 3285: an integer-mode (e.g., SImode) object. Handle this case ! 3286: by doing the extract into an object as wide as the field ! 3287: (which we know to be the width of a basic mode), then ! 3288: storing into memory, and changing the mode to BLKmode. */ ! 3289: enum machine_mode ext_mode = mode; ! 3290: ! 3291: if (ext_mode == BLKmode) ! 3292: ext_mode = mode_for_size (bitsize, MODE_INT, 1); ! 3293: ! 3294: if (ext_mode == BLKmode) ! 3295: abort (); ! 3296: ! 3297: op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos, ! 3298: unsignedp, target, ext_mode, ext_mode, ! 3299: TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT, ! 3300: int_size_in_bytes (TREE_TYPE (tem))); ! 3301: if (mode == BLKmode) ! 3302: { ! 3303: rtx new = assign_stack_temp (ext_mode, ! 3304: bitsize / BITS_PER_UNIT, 0); ! 3305: ! 3306: emit_move_insn (new, op0); ! 3307: op0 = copy_rtx (new); ! 3308: PUT_MODE (op0, BLKmode); ! 3309: } ! 3310: ! 3311: return op0; ! 3312: } ! 3313: ! 3314: /* Get a reference to just this component. */ ! 3315: if (modifier == EXPAND_CONST_ADDRESS ! 3316: || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 3317: op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0), ! 3318: (bitpos / BITS_PER_UNIT))); ! 3319: else ! 3320: op0 = change_address (op0, mode1, ! 3321: plus_constant (XEXP (op0, 0), ! 3322: (bitpos / BITS_PER_UNIT))); ! 3323: MEM_IN_STRUCT_P (op0) = 1; ! 3324: MEM_VOLATILE_P (op0) |= volatilep; ! 3325: if (mode == mode1 || mode1 == BLKmode || mode1 == tmode) ! 3326: return op0; ! 3327: if (target == 0) ! 3328: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); ! 3329: convert_move (target, op0, unsignedp); ! 3330: return target; ! 3331: } ! 3332: ! 3333: case OFFSET_REF: ! 3334: { ! 3335: tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0); ! 3336: tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1)); ! 3337: op0 = expand_expr (addr, 0, VOIDmode, EXPAND_SUM); ! 3338: temp = gen_rtx (MEM, mode, memory_address (mode, op0)); ! 3339: MEM_IN_STRUCT_P (temp) = 1; ! 3340: MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) || flag_volatile; ! 3341: #if 0 /* It is incorrectto set RTX_UNCHANGING_P here, because the fact that ! 3342: a location is accessed through a pointer to const does not mean ! 3343: that the value there can never change. */ ! 3344: RTX_UNCHANGING_P (temp) = TREE_READONLY (exp); ! 3345: #endif ! 3346: return temp; ! 3347: } ! 3348: ! 3349: /* Intended for a reference to a buffer of a file-object in Pascal. ! 3350: But it's not certain that a special tree code will really be ! 3351: necessary for these. INDIRECT_REF might work for them. */ ! 3352: case BUFFER_REF: ! 3353: abort (); ! 3354: ! 3355: case WITH_CLEANUP_EXPR: ! 3356: if (RTL_EXPR_RTL (exp) == 0) ! 3357: { ! 3358: RTL_EXPR_RTL (exp) ! 3359: = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); ! 3360: cleanups_this_call = tree_cons (0, TREE_OPERAND (exp, 2), cleanups_this_call); ! 3361: /* That's it for this cleanup. */ ! 3362: TREE_OPERAND (exp, 2) = 0; ! 3363: } ! 3364: return RTL_EXPR_RTL (exp); ! 3365: ! 3366: case CALL_EXPR: ! 3367: /* Check for a built-in function. */ ! 3368: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR ! 3369: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL ! 3370: && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 3371: return expand_builtin (exp, target, subtarget, tmode, ignore); ! 3372: /* If this call was expanded already by preexpand_calls, ! 3373: just return the result we got. */ ! 3374: if (CALL_EXPR_RTL (exp) != 0) ! 3375: return CALL_EXPR_RTL (exp); ! 3376: return expand_call (exp, target, ignore, modifier); ! 3377: ! 3378: case NON_LVALUE_EXPR: ! 3379: case NOP_EXPR: ! 3380: case CONVERT_EXPR: ! 3381: case REFERENCE_EXPR: ! 3382: if (TREE_CODE (type) == VOID_TYPE || ignore) ! 3383: { ! 3384: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier); ! 3385: return const0_rtx; ! 3386: } ! 3387: if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 3388: return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier); ! 3389: if (TREE_CODE (type) == UNION_TYPE) ! 3390: { ! 3391: tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 3392: if (target == 0) ! 3393: { ! 3394: if (mode == BLKmode) ! 3395: { ! 3396: if (TYPE_SIZE (type) == 0 ! 3397: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 3398: abort (); ! 3399: target = assign_stack_temp (BLKmode, ! 3400: (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! 3401: + BITS_PER_UNIT - 1) ! 3402: / BITS_PER_UNIT, 0); ! 3403: } ! 3404: else ! 3405: target = gen_reg_rtx (mode); ! 3406: } ! 3407: if (GET_CODE (target) == MEM) ! 3408: /* Store data into beginning of memory target. */ ! 3409: store_expr (TREE_OPERAND (exp, 0), ! 3410: change_address (target, TYPE_MODE (valtype), 0), 0); ! 3411: else if (GET_CODE (target) == REG) ! 3412: /* Store this field into a union of the proper type. */ ! 3413: store_field (target, GET_MODE_BITSIZE (TYPE_MODE (valtype)), 0, ! 3414: TYPE_MODE (valtype), TREE_OPERAND (exp, 0), ! 3415: VOIDmode, 0, 1, ! 3416: int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 3417: else ! 3418: abort (); ! 3419: ! 3420: /* Return the entire union. */ ! 3421: return target; ! 3422: } ! 3423: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0); ! 3424: if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode) ! 3425: return op0; ! 3426: if (flag_force_mem && GET_CODE (op0) == MEM) ! 3427: op0 = copy_to_reg (op0); ! 3428: ! 3429: if (target == 0) ! 3430: return convert_to_mode (mode, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 3431: else ! 3432: convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 3433: return target; ! 3434: ! 3435: case PLUS_EXPR: ! 3436: /* We come here from MINUS_EXPR when the second operand is a constant. */ ! 3437: plus_expr: ! 3438: this_optab = add_optab; ! 3439: ! 3440: /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and ! 3441: something else, make sure we add the register to the constant and ! 3442: then to the other thing. This case can occur during strength ! 3443: reduction and doing it this way will produce better code if the ! 3444: frame pointer or argument pointer is eliminated. ! 3445: ! 3446: fold-const.c will ensure that the constant is always in the inner ! 3447: PLUS_EXPR, so the only case we need to do anything about is if ! 3448: sp, ap, or fp is our second argument, in which case we must swap ! 3449: the innermost first argument and our second argument. */ ! 3450: ! 3451: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR ! 3452: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST ! 3453: && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR ! 3454: && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx ! 3455: || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx ! 3456: || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx)) ! 3457: { ! 3458: tree t = TREE_OPERAND (exp, 1); ! 3459: ! 3460: TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); ! 3461: TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t; ! 3462: } ! 3463: ! 3464: /* If the result is to be Pmode and we are adding an integer to ! 3465: something, we might be forming a constant. So try to use ! 3466: plus_constant. If it produces a sum and we can't accept it, ! 3467: use force_operand. This allows P = &ARR[const] to generate ! 3468: efficient code on machines where a SYMBOL_REF is not a valid ! 3469: address. ! 3470: ! 3471: If this is an EXPAND_SUM call, always return the sum. */ ! 3472: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST ! 3473: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! 3474: && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER ! 3475: || mode == Pmode)) ! 3476: { ! 3477: op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, ! 3478: EXPAND_SUM); ! 3479: op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0))); ! 3480: if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 3481: op1 = force_operand (op1, target); ! 3482: return op1; ! 3483: } ! 3484: ! 3485: else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 3486: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! 3487: && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER ! 3488: || mode == Pmode)) ! 3489: { ! 3490: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, ! 3491: EXPAND_SUM); ! 3492: op0 = plus_constant (op0, TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))); ! 3493: if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 3494: op0 = force_operand (op0, target); ! 3495: return op0; ! 3496: } ! 3497: ! 3498: /* No sense saving up arithmetic to be done ! 3499: if it's all in the wrong mode to form part of an address. ! 3500: And force_operand won't know whether to sign-extend or ! 3501: zero-extend. */ ! 3502: if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 3503: || mode != Pmode) goto binop; ! 3504: ! 3505: preexpand_calls (exp); ! 3506: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 3507: subtarget = 0; ! 3508: ! 3509: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); ! 3510: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, modifier); ! 3511: /* Put a sum last, to simplify what follows. */ ! 3512: #ifdef OLD_INDEXING ! 3513: if (GET_CODE (op1) == MULT) ! 3514: { ! 3515: temp = op0; ! 3516: op0 = op1; ! 3517: op1 = temp; ! 3518: } ! 3519: #endif ! 3520: #ifndef OLD_INDEXING ! 3521: /* Make sure any term that's a sum with a constant comes last. */ ! 3522: if (GET_CODE (op0) == PLUS ! 3523: && CONSTANT_P (XEXP (op0, 1))) ! 3524: { ! 3525: temp = op0; ! 3526: op0 = op1; ! 3527: op1 = temp; ! 3528: } ! 3529: /* If adding to a sum including a constant, ! 3530: associate it to put the constant outside. */ ! 3531: if (GET_CODE (op1) == PLUS ! 3532: && CONSTANT_P (XEXP (op1, 1))) ! 3533: { ! 3534: rtx tem; ! 3535: int constant_term = 0; ! 3536: ! 3537: op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0); ! 3538: /* Let's also eliminate constants from op0 if possible. */ ! 3539: tem = eliminate_constant_term (op0, &constant_term); ! 3540: if (GET_CODE (XEXP (op1, 1)) == CONST_INT) ! 3541: { ! 3542: if (constant_term != 0) ! 3543: return plus_constant (tem, INTVAL (XEXP (op1, 1)) + constant_term); ! 3544: else ! 3545: return plus_constant (op0, INTVAL (XEXP (op1, 1))); ! 3546: } ! 3547: else ! 3548: return gen_rtx (PLUS, mode, op0, XEXP (op1, 1)); ! 3549: } ! 3550: #endif ! 3551: /* Put a constant term last. */ ! 3552: if (CONSTANT_P (op0)) ! 3553: return gen_rtx (PLUS, mode, op1, op0); ! 3554: else ! 3555: return gen_rtx (PLUS, mode, op0, op1); ! 3556: ! 3557: case MINUS_EXPR: ! 3558: /* Handle difference of two symbolic constants, ! 3559: for the sake of an initializer. */ ! 3560: if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 3561: && really_constant_p (TREE_OPERAND (exp, 0)) ! 3562: && really_constant_p (TREE_OPERAND (exp, 1))) ! 3563: { ! 3564: rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, modifier); ! 3565: rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, modifier); ! 3566: return gen_rtx (MINUS, mode, op0, op1); ! 3567: } ! 3568: /* Convert A - const to A + (-const). */ ! 3569: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! 3570: { ! 3571: exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), ! 3572: fold (build1 (NEGATE_EXPR, type, ! 3573: TREE_OPERAND (exp, 1)))); ! 3574: goto plus_expr; ! 3575: } ! 3576: this_optab = sub_optab; ! 3577: goto binop; ! 3578: ! 3579: case MULT_EXPR: ! 3580: preexpand_calls (exp); ! 3581: /* If first operand is constant, swap them. ! 3582: Thus the following special case checks need only ! 3583: check the second operand. */ ! 3584: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST) ! 3585: { ! 3586: register tree t1 = TREE_OPERAND (exp, 0); ! 3587: TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1); ! 3588: TREE_OPERAND (exp, 1) = t1; ! 3589: } ! 3590: ! 3591: /* Attempt to return something suitable for generating an ! 3592: indexed address, for machines that support that. */ ! 3593: ! 3594: if (modifier == EXPAND_SUM && mode == Pmode ! 3595: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 3596: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT) ! 3597: { ! 3598: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); ! 3599: ! 3600: /* Apply distributive law if OP0 is x+c. */ ! 3601: if (GET_CODE (op0) == PLUS ! 3602: && GET_CODE (XEXP (op0, 1)) == CONST_INT) ! 3603: return gen_rtx (PLUS, mode, ! 3604: gen_rtx (MULT, mode, XEXP (op0, 0), ! 3605: gen_rtx (CONST_INT, VOIDmode, ! 3606: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), ! 3607: gen_rtx (CONST_INT, VOIDmode, ! 3608: (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! 3609: * INTVAL (XEXP (op0, 1))))); ! 3610: ! 3611: if (GET_CODE (op0) != REG) ! 3612: op0 = force_operand (op0, 0); ! 3613: if (GET_CODE (op0) != REG) ! 3614: op0 = copy_to_mode_reg (mode, op0); ! 3615: ! 3616: return gen_rtx (MULT, mode, op0, ! 3617: gen_rtx (CONST_INT, VOIDmode, ! 3618: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); ! 3619: } ! 3620: ! 3621: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 3622: subtarget = 0; ! 3623: ! 3624: /* Check for multiplying things that have been extended ! 3625: from a narrower type. If this machine supports multiplying ! 3626: in that narrower type with a result in the desired type, ! 3627: do it that way, and avoid the explicit type-conversion. */ ! 3628: if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR ! 3629: && TREE_CODE (type) == INTEGER_TYPE ! 3630: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 3631: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 3632: && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 3633: && int_fits_type_p (TREE_OPERAND (exp, 1), ! 3634: TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 3635: /* Don't use a widening multiply if a shift will do. */ ! 3636: && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)))) ! 3637: > HOST_BITS_PER_INT) ! 3638: || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)) ! 3639: || ! 3640: (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR ! 3641: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) ! 3642: == ! 3643: TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))) ! 3644: /* If both operands are extended, they must either both ! 3645: be zero-extended or both be sign-extended. */ ! 3646: && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) ! 3647: == ! 3648: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))))) ! 3649: { ! 3650: enum machine_mode innermode ! 3651: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))); ! 3652: this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 3653: ? umul_widen_optab : smul_widen_optab); ! 3654: if (mode == GET_MODE_WIDER_MODE (innermode) ! 3655: && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 3656: { ! 3657: op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 3658: 0, VOIDmode, 0); ! 3659: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! 3660: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 3661: else ! 3662: op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), ! 3663: 0, VOIDmode, 0); ! 3664: goto binop2; ! 3665: } ! 3666: } ! 3667: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3668: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 3669: return expand_mult (mode, op0, op1, target, unsignedp); ! 3670: ! 3671: case TRUNC_DIV_EXPR: ! 3672: case FLOOR_DIV_EXPR: ! 3673: case CEIL_DIV_EXPR: ! 3674: case ROUND_DIV_EXPR: ! 3675: case EXACT_DIV_EXPR: ! 3676: preexpand_calls (exp); ! 3677: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 3678: subtarget = 0; ! 3679: /* Possible optimization: compute the dividend with EXPAND_SUM ! 3680: then if the divisor is constant can optimize the case ! 3681: where some terms of the dividend have coeffs divisible by it. */ ! 3682: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3683: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 3684: return expand_divmod (0, code, mode, op0, op1, target, unsignedp); ! 3685: ! 3686: case RDIV_EXPR: ! 3687: this_optab = flodiv_optab; ! 3688: goto binop; ! 3689: ! 3690: case TRUNC_MOD_EXPR: ! 3691: case FLOOR_MOD_EXPR: ! 3692: case CEIL_MOD_EXPR: ! 3693: case ROUND_MOD_EXPR: ! 3694: preexpand_calls (exp); ! 3695: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 3696: subtarget = 0; ! 3697: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3698: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 3699: return expand_divmod (1, code, mode, op0, op1, target, unsignedp); ! 3700: ! 3701: case FIX_ROUND_EXPR: ! 3702: case FIX_FLOOR_EXPR: ! 3703: case FIX_CEIL_EXPR: ! 3704: abort (); /* Not used for C. */ ! 3705: ! 3706: case FIX_TRUNC_EXPR: ! 3707: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 3708: if (target == 0) ! 3709: target = gen_reg_rtx (mode); ! 3710: expand_fix (target, op0, unsignedp); ! 3711: return target; ! 3712: ! 3713: case FLOAT_EXPR: ! 3714: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 3715: if (target == 0) ! 3716: target = gen_reg_rtx (mode); ! 3717: /* expand_float can't figure out what to do if FROM has VOIDmode. ! 3718: So give it the correct mode. With -O, cse will optimize this. */ ! 3719: if (GET_MODE (op0) == VOIDmode) ! 3720: op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), ! 3721: op0); ! 3722: expand_float (target, op0, ! 3723: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 3724: return target; ! 3725: ! 3726: case NEGATE_EXPR: ! 3727: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 3728: temp = expand_unop (mode, neg_optab, op0, target, 0); ! 3729: if (temp == 0) ! 3730: abort (); ! 3731: return temp; ! 3732: ! 3733: case ABS_EXPR: ! 3734: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3735: ! 3736: /* Unsigned abs is simply the operand. Testing here means we don't ! 3737: risk generating incorrect code below. */ ! 3738: if (TREE_UNSIGNED (type)) ! 3739: return op0; ! 3740: ! 3741: /* First try to do it with a special abs instruction. */ ! 3742: temp = expand_unop (mode, abs_optab, op0, target, 0); ! 3743: if (temp != 0) ! 3744: return temp; ! 3745: ! 3746: /* If this machine has expensive jumps, we can do integer absolute ! 3747: value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)), ! 3748: where W is the width of MODE. */ ! 3749: ! 3750: if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2) ! 3751: { ! 3752: rtx extended = expand_shift (RSHIFT_EXPR, mode, op0, ! 3753: size_int (GET_MODE_BITSIZE (mode) - 1), ! 3754: 0, 0); ! 3755: ! 3756: temp = expand_binop (mode, xor_optab, extended, op0, target, 0, ! 3757: OPTAB_LIB_WIDEN); ! 3758: if (temp != 0) ! 3759: temp = expand_binop (mode, sub_optab, temp, extended, target, 0, ! 3760: OPTAB_LIB_WIDEN); ! 3761: ! 3762: if (temp != 0) ! 3763: return temp; ! 3764: } ! 3765: ! 3766: /* If that does not win, use conditional jump and negate. */ ! 3767: target = original_target; ! 3768: temp = gen_label_rtx (); ! 3769: if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 0)) ! 3770: || (GET_CODE (target) == REG ! 3771: && REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 3772: target = gen_reg_rtx (mode); ! 3773: emit_move_insn (target, op0); ! 3774: emit_cmp_insn (target, ! 3775: expand_expr (convert (type, integer_zero_node), ! 3776: 0, VOIDmode, 0), ! 3777: GE, 0, mode, 0, 0); ! 3778: NO_DEFER_POP; ! 3779: emit_jump_insn (gen_bge (temp)); ! 3780: op0 = expand_unop (mode, neg_optab, target, target, 0); ! 3781: if (op0 != target) ! 3782: emit_move_insn (target, op0); ! 3783: emit_label (temp); ! 3784: OK_DEFER_POP; ! 3785: return target; ! 3786: ! 3787: case MAX_EXPR: ! 3788: case MIN_EXPR: ! 3789: target = original_target; ! 3790: if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1)) ! 3791: || (GET_CODE (target) == REG ! 3792: && REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 3793: target = gen_reg_rtx (mode); ! 3794: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 3795: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 3796: ! 3797: /* First try to do it with a special MIN or MAX instruction. ! 3798: If that does not win, use a conditional jump to select the proper ! 3799: value. */ ! 3800: this_optab = (TREE_UNSIGNED (type) ! 3801: ? (code == MIN_EXPR ? umin_optab : umax_optab) ! 3802: : (code == MIN_EXPR ? smin_optab : smax_optab)); ! 3803: ! 3804: temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp, ! 3805: OPTAB_WIDEN); ! 3806: if (temp != 0) ! 3807: return temp; ! 3808: ! 3809: if (target != op0) ! 3810: emit_move_insn (target, op0); ! 3811: op0 = gen_label_rtx (); ! 3812: if (code == MAX_EXPR) ! 3813: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 3814: ? compare_from_rtx (target, op1, GEU, 1, mode, 0, 0) ! 3815: : compare_from_rtx (target, op1, GE, 0, mode, 0, 0)); ! 3816: else ! 3817: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 3818: ? compare_from_rtx (target, op1, LEU, 1, mode, 0, 0) ! 3819: : compare_from_rtx (target, op1, LE, 0, mode, 0, 0)); ! 3820: if (temp == const0_rtx) ! 3821: emit_move_insn (target, op1); ! 3822: else if (temp != const_true_rtx) ! 3823: { ! 3824: if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0) ! 3825: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op0)); ! 3826: else ! 3827: abort (); ! 3828: emit_move_insn (target, op1); ! 3829: } ! 3830: emit_label (op0); ! 3831: return target; ! 3832: ! 3833: /* ??? Can optimize when the operand of this is a bitwise operation, ! 3834: by using a different bitwise operation. */ ! 3835: case BIT_NOT_EXPR: ! 3836: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3837: temp = expand_unop (mode, one_cmpl_optab, op0, target, 1); ! 3838: if (temp == 0) ! 3839: abort (); ! 3840: return temp; ! 3841: ! 3842: case FFS_EXPR: ! 3843: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3844: temp = expand_unop (mode, ffs_optab, op0, target, 1); ! 3845: if (temp == 0) ! 3846: abort (); ! 3847: return temp; ! 3848: ! 3849: /* ??? Can optimize bitwise operations with one arg constant. ! 3850: Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b) ! 3851: and (a bitwise1 b) bitwise2 b (etc) ! 3852: but that is probably not worth while. */ ! 3853: ! 3854: /* BIT_AND_EXPR is for bitwise anding. ! 3855: TRUTH_AND_EXPR is for anding two boolean values ! 3856: when we want in all cases to compute both of them. ! 3857: In general it is fastest to do TRUTH_AND_EXPR by ! 3858: computing both operands as actual zero-or-1 values ! 3859: and then bitwise anding. In cases where there cannot ! 3860: be any side effects, better code would be made by ! 3861: treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR; ! 3862: but the question is how to recognize those cases. */ ! 3863: ! 3864: case TRUTH_AND_EXPR: ! 3865: case BIT_AND_EXPR: ! 3866: this_optab = and_optab; ! 3867: goto binop; ! 3868: ! 3869: /* See comment above about TRUTH_AND_EXPR; it applies here too. */ ! 3870: case TRUTH_OR_EXPR: ! 3871: case BIT_IOR_EXPR: ! 3872: this_optab = ior_optab; ! 3873: goto binop; ! 3874: ! 3875: case BIT_XOR_EXPR: ! 3876: this_optab = xor_optab; ! 3877: goto binop; ! 3878: ! 3879: case LSHIFT_EXPR: ! 3880: case RSHIFT_EXPR: ! 3881: case LROTATE_EXPR: ! 3882: case RROTATE_EXPR: ! 3883: preexpand_calls (exp); ! 3884: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 3885: subtarget = 0; ! 3886: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 3887: return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, ! 3888: unsignedp); ! 3889: ! 3890: /* Could determine the answer when only additive constants differ. ! 3891: Also, the addition of one can be handled by changing the condition. */ ! 3892: case LT_EXPR: ! 3893: case LE_EXPR: ! 3894: case GT_EXPR: ! 3895: case GE_EXPR: ! 3896: case EQ_EXPR: ! 3897: case NE_EXPR: ! 3898: preexpand_calls (exp); ! 3899: temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0); ! 3900: if (temp != 0) ! 3901: return temp; ! 3902: /* For foo != 0, load foo, and if it is nonzero load 1 instead. */ ! 3903: if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1)) ! 3904: && original_target ! 3905: && GET_CODE (original_target) == REG ! 3906: && (GET_MODE (original_target) ! 3907: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 3908: { ! 3909: temp = expand_expr (TREE_OPERAND (exp, 0), original_target, VOIDmode, 0); ! 3910: if (temp != original_target) ! 3911: temp = copy_to_reg (temp); ! 3912: op1 = gen_label_rtx (); ! 3913: emit_cmp_insn (temp, const0_rtx, EQ, 0, ! 3914: GET_MODE (temp), unsignedp, 0); ! 3915: emit_jump_insn (gen_beq (op1)); ! 3916: emit_move_insn (temp, const1_rtx); ! 3917: emit_label (op1); ! 3918: return temp; ! 3919: } ! 3920: /* If no set-flag instruction, must generate a conditional ! 3921: store into a temporary variable. Drop through ! 3922: and handle this like && and ||. */ ! 3923: ! 3924: case TRUTH_ANDIF_EXPR: ! 3925: case TRUTH_ORIF_EXPR: ! 3926: if (target == 0 || ! safe_from_p (target, exp) ! 3927: /* Make sure we don't have a hard reg (such as function's return ! 3928: value) live across basic blocks, if not optimizing. */ ! 3929: || (!optimize && GET_CODE (target) == REG ! 3930: && REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 3931: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); ! 3932: emit_clr_insn (target); ! 3933: op1 = gen_label_rtx (); ! 3934: jumpifnot (exp, op1); ! 3935: emit_0_to_1_insn (target); ! 3936: emit_label (op1); ! 3937: return target; ! 3938: ! 3939: case TRUTH_NOT_EXPR: ! 3940: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 3941: /* The parser is careful to generate TRUTH_NOT_EXPR ! 3942: only with operands that are always zero or one. */ ! 3943: temp = expand_binop (mode, xor_optab, op0, ! 3944: gen_rtx (CONST_INT, mode, 1), ! 3945: target, 1, OPTAB_LIB_WIDEN); ! 3946: if (temp == 0) ! 3947: abort (); ! 3948: return temp; ! 3949: ! 3950: case COMPOUND_EXPR: ! 3951: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 3952: emit_queue (); ! 3953: return expand_expr (TREE_OPERAND (exp, 1), ! 3954: (ignore ? const0_rtx : target), ! 3955: VOIDmode, 0); ! 3956: ! 3957: case COND_EXPR: ! 3958: { ! 3959: /* Note that COND_EXPRs whose type is a structure or union ! 3960: are required to be constructed to contain assignments of ! 3961: a temporary variable, so that we can evaluate them here ! 3962: for side effect only. If type is void, we must do likewise. */ ! 3963: ! 3964: /* If an arm of the branch requires a cleanup, ! 3965: only that cleanup is performed. */ ! 3966: ! 3967: tree singleton = 0; ! 3968: tree binary_op = 0, unary_op = 0; ! 3969: tree old_cleanups = cleanups_this_call; ! 3970: cleanups_this_call = 0; ! 3971: ! 3972: /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and ! 3973: convert it to our mode, if necessary. */ ! 3974: if (integer_onep (TREE_OPERAND (exp, 1)) ! 3975: && integer_zerop (TREE_OPERAND (exp, 2)) ! 3976: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') ! 3977: { ! 3978: op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier); ! 3979: if (GET_MODE (op0) == mode) ! 3980: return op0; ! 3981: if (target == 0) ! 3982: target = gen_reg_rtx (mode); ! 3983: convert_move (target, op0, unsignedp); ! 3984: return target; ! 3985: } ! 3986: ! 3987: /* If we are not to produce a result, we have no target. Otherwise, ! 3988: if a target was specified use it; it will not be used as an ! 3989: intermediate target unless it is safe. If no target, use a ! 3990: temporary. */ ! 3991: ! 3992: if (mode == VOIDmode || ignore) ! 3993: temp = 0; ! 3994: else if (original_target ! 3995: && safe_from_p (original_target, TREE_OPERAND (exp, 0))) ! 3996: temp = original_target; ! 3997: else if (mode == BLKmode) ! 3998: { ! 3999: if (TYPE_SIZE (type) == 0 ! 4000: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 4001: abort (); ! 4002: temp = assign_stack_temp (BLKmode, ! 4003: (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! 4004: + BITS_PER_UNIT - 1) ! 4005: / BITS_PER_UNIT, 0); ! 4006: } ! 4007: else ! 4008: temp = gen_reg_rtx (mode); ! 4009: ! 4010: /* Check for X ? A + B : A. If we have this, we can copy ! 4011: A to the output and conditionally add B. Similarly for unary ! 4012: operations. Don't do this if X has side-effects because ! 4013: those side effects might affect A or B and the "?" operation is ! 4014: a sequence point in ANSI. (We test for side effects later.) */ ! 4015: ! 4016: if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2' ! 4017: && operand_equal_p (TREE_OPERAND (exp, 2), ! 4018: TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0)) ! 4019: singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1); ! 4020: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2' ! 4021: && operand_equal_p (TREE_OPERAND (exp, 1), ! 4022: TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0)) ! 4023: singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2); ! 4024: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1' ! 4025: && operand_equal_p (TREE_OPERAND (exp, 2), ! 4026: TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0)) ! 4027: singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1); ! 4028: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1' ! 4029: && operand_equal_p (TREE_OPERAND (exp, 1), ! 4030: TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0)) ! 4031: singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2); ! 4032: ! 4033: /* If we had X ? A + 1 : A and we can do the test of X as a store-flag ! 4034: operation, do this as A + (X != 0). Similarly for other simple ! 4035: binary operators. */ ! 4036: if (singleton && binary_op ! 4037: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 4038: && (TREE_CODE (binary_op) == PLUS_EXPR ! 4039: || TREE_CODE (binary_op) == MINUS_EXPR ! 4040: || TREE_CODE (binary_op) == BIT_IOR_EXPR ! 4041: || TREE_CODE (binary_op) == BIT_XOR_EXPR ! 4042: || TREE_CODE (binary_op) == BIT_AND_EXPR) ! 4043: && integer_onep (TREE_OPERAND (binary_op, 1)) ! 4044: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') ! 4045: { ! 4046: rtx result; ! 4047: optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab ! 4048: : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab ! 4049: : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab ! 4050: : TREE_CODE (binary_op) == BIT_XOR_EXPR ? xor_optab ! 4051: : and_optab); ! 4052: ! 4053: /* If we had X ? A : A + 1, do this as A + (X == 0). ! 4054: ! 4055: We have to invert the truth value here and then put it ! 4056: back later if do_store_flag fails. We cannot simply copy ! 4057: TREE_OPERAND (exp, 0) to another variable and modify that ! 4058: because invert_truthvalue can modify the tree pointed to ! 4059: by its argument. */ ! 4060: if (singleton == TREE_OPERAND (exp, 1)) ! 4061: TREE_OPERAND (exp, 0) ! 4062: = invert_truthvalue (TREE_OPERAND (exp, 0)); ! 4063: ! 4064: result = do_store_flag (TREE_OPERAND (exp, 0), ! 4065: safe_from_p (temp, singleton) ? temp : 0, ! 4066: mode, BRANCH_COST <= 1); ! 4067: ! 4068: if (result) ! 4069: { ! 4070: op1 = expand_expr (singleton, 0, VOIDmode, 0); ! 4071: return expand_binop (mode, boptab, op1, result, temp, ! 4072: unsignedp, OPTAB_LIB_WIDEN); ! 4073: } ! 4074: else if (singleton == TREE_OPERAND (exp, 1)) ! 4075: TREE_OPERAND (exp, 0) ! 4076: = invert_truthvalue (TREE_OPERAND (exp, 0)); ! 4077: } ! 4078: ! 4079: NO_DEFER_POP; ! 4080: op0 = gen_label_rtx (); ! 4081: ! 4082: if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))) ! 4083: { ! 4084: if (temp != 0) ! 4085: { ! 4086: /* If the target conflicts with the other operand of the ! 4087: binary op, we can't use it. Also, we can't use the target ! 4088: if it is a hard register, because evaluating the condition ! 4089: might clobber it. */ ! 4090: if ((binary_op ! 4091: && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1))) ! 4092: || (GET_CODE (temp) == REG ! 4093: && REGNO (temp) < FIRST_PSEUDO_REGISTER)) ! 4094: temp = gen_reg_rtx (mode); ! 4095: store_expr (singleton, temp, 0); ! 4096: } ! 4097: else ! 4098: expand_expr (singleton, ignore ? const1_rtx : 0, VOIDmode, 0); ! 4099: if (cleanups_this_call) ! 4100: { ! 4101: sorry ("aggregate value in COND_EXPR"); ! 4102: cleanups_this_call = 0; ! 4103: } ! 4104: if (singleton == TREE_OPERAND (exp, 1)) ! 4105: jumpif (TREE_OPERAND (exp, 0), op0); ! 4106: else ! 4107: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 4108: ! 4109: if (binary_op && temp == 0) ! 4110: /* Just touch the other operand. */ ! 4111: expand_expr (TREE_OPERAND (binary_op, 1), ! 4112: ignore ? const0_rtx : 0, VOIDmode, 0); ! 4113: else if (binary_op) ! 4114: store_expr (build (TREE_CODE (binary_op), type, ! 4115: make_tree (type, temp), ! 4116: TREE_OPERAND (binary_op, 1)), ! 4117: temp, 0); ! 4118: else ! 4119: store_expr (build1 (TREE_CODE (unary_op), type, ! 4120: make_tree (type, temp)), ! 4121: temp, 0); ! 4122: op1 = op0; ! 4123: } ! 4124: #if 0 ! 4125: /* This is now done in jump.c and is better done there because it ! 4126: produces shorter register lifetimes. */ ! 4127: ! 4128: /* Check for both possibilities either constants or variables ! 4129: in registers (but not the same as the target!). If so, can ! 4130: save branches by assigning one, branching, and assigning the ! 4131: other. */ ! 4132: else if (temp && GET_MODE (temp) != BLKmode ! 4133: && (TREE_CONSTANT (TREE_OPERAND (exp, 1)) ! 4134: || ((TREE_CODE (TREE_OPERAND (exp, 1)) == PARM_DECL ! 4135: || TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL) ! 4136: && DECL_RTL (TREE_OPERAND (exp, 1)) ! 4137: && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 1))) == REG ! 4138: && DECL_RTL (TREE_OPERAND (exp, 1)) != temp)) ! 4139: && (TREE_CONSTANT (TREE_OPERAND (exp, 2)) ! 4140: || ((TREE_CODE (TREE_OPERAND (exp, 2)) == PARM_DECL ! 4141: || TREE_CODE (TREE_OPERAND (exp, 2)) == VAR_DECL) ! 4142: && DECL_RTL (TREE_OPERAND (exp, 2)) ! 4143: && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 2))) == REG ! 4144: && DECL_RTL (TREE_OPERAND (exp, 2)) != temp))) ! 4145: { ! 4146: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 4147: temp = gen_reg_rtx (mode); ! 4148: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 4149: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 4150: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 4151: op1 = op0; ! 4152: } ! 4153: #endif ! 4154: /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any ! 4155: comparison operator. If we have one of these cases, set the ! 4156: output to A, branch on A (cse will merge these two references), ! 4157: then set the output to FOO. */ ! 4158: else if (temp ! 4159: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<' ! 4160: && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) ! 4161: && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 4162: TREE_OPERAND (exp, 1), 0) ! 4163: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 4164: && safe_from_p (temp, TREE_OPERAND (exp, 2))) ! 4165: { ! 4166: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 4167: temp = gen_reg_rtx (mode); ! 4168: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 4169: jumpif (TREE_OPERAND (exp, 0), op0); ! 4170: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 4171: op1 = op0; ! 4172: } ! 4173: else if (temp ! 4174: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<' ! 4175: && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) ! 4176: && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 4177: TREE_OPERAND (exp, 2), 0) ! 4178: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 4179: && safe_from_p (temp, TREE_OPERAND (exp, 1))) ! 4180: { ! 4181: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 4182: temp = gen_reg_rtx (mode); ! 4183: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 4184: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 4185: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 4186: op1 = op0; ! 4187: } ! 4188: else ! 4189: { ! 4190: op1 = gen_label_rtx (); ! 4191: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 4192: if (temp != 0) ! 4193: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 4194: else ! 4195: expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0, ! 4196: VOIDmode, 0); ! 4197: if (cleanups_this_call) ! 4198: { ! 4199: sorry ("aggregate value in COND_EXPR"); ! 4200: cleanups_this_call = 0; ! 4201: } ! 4202: ! 4203: emit_queue (); ! 4204: emit_jump_insn (gen_jump (op1)); ! 4205: emit_barrier (); ! 4206: emit_label (op0); ! 4207: if (temp != 0) ! 4208: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 4209: else ! 4210: expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0, ! 4211: VOIDmode, 0); ! 4212: } ! 4213: ! 4214: if (cleanups_this_call) ! 4215: { ! 4216: sorry ("aggregate value in COND_EXPR"); ! 4217: cleanups_this_call = 0; ! 4218: } ! 4219: ! 4220: emit_queue (); ! 4221: emit_label (op1); ! 4222: OK_DEFER_POP; ! 4223: cleanups_this_call = old_cleanups; ! 4224: return temp; ! 4225: } ! 4226: ! 4227: case TARGET_EXPR: ! 4228: { ! 4229: /* Something needs to be initialized, but we didn't know ! 4230: where that thing was when building the tree. For example, ! 4231: it could be the return value of a function, or a parameter ! 4232: to a function which lays down in the stack, or a temporary ! 4233: variable which must be passed by reference. ! 4234: ! 4235: We guarantee that the expression will either be constructed ! 4236: or copied into our original target. */ ! 4237: ! 4238: tree slot = TREE_OPERAND (exp, 0); ! 4239: ! 4240: if (TREE_CODE (slot) != VAR_DECL) ! 4241: abort (); ! 4242: ! 4243: if (target == 0) ! 4244: { ! 4245: if (DECL_RTL (slot) != 0) ! 4246: target = DECL_RTL (slot); ! 4247: else ! 4248: { ! 4249: target = assign_stack_temp (mode, int_size_in_bytes (type), 0); ! 4250: /* All temp slots at this level must not conflict. */ ! 4251: preserve_temp_slots (target); ! 4252: DECL_RTL (slot) = target; ! 4253: } ! 4254: ! 4255: #if 0 ! 4256: /* Since SLOT is not known to the called function ! 4257: to belong to its stack frame, we must build an explicit ! 4258: cleanup. This case occurs when we must build up a reference ! 4259: to pass the reference as an argument. In this case, ! 4260: it is very likely that such a reference need not be ! 4261: built here. */ ! 4262: ! 4263: if (TREE_OPERAND (exp, 2) == 0) ! 4264: TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot); ! 4265: if (TREE_OPERAND (exp, 2)) ! 4266: cleanups_this_call = tree_cons (0, TREE_OPERAND (exp, 2), ! 4267: cleanups_this_call); ! 4268: #endif ! 4269: } ! 4270: else ! 4271: { ! 4272: /* This case does occur, when expanding a parameter which ! 4273: needs to be constructed on the stack. The target ! 4274: is the actual stack address that we want to initialize. ! 4275: The function we call will perform the cleanup in this case. */ ! 4276: ! 4277: DECL_RTL (slot) = target; ! 4278: } ! 4279: ! 4280: return expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); ! 4281: } ! 4282: ! 4283: case INIT_EXPR: ! 4284: { ! 4285: tree lhs = TREE_OPERAND (exp, 0); ! 4286: tree rhs = TREE_OPERAND (exp, 1); ! 4287: tree noncopied_parts = 0; ! 4288: tree lhs_type = TREE_TYPE (lhs); ! 4289: ! 4290: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); ! 4291: if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs)) ! 4292: noncopied_parts = init_noncopied_parts (stabilize_reference (lhs), ! 4293: TYPE_NONCOPIED_PARTS (lhs_type)); ! 4294: while (noncopied_parts != 0) ! 4295: { ! 4296: expand_assignment (TREE_VALUE (noncopied_parts), ! 4297: TREE_PURPOSE (noncopied_parts), 0, 0); ! 4298: noncopied_parts = TREE_CHAIN (noncopied_parts); ! 4299: } ! 4300: return temp; ! 4301: } ! 4302: ! 4303: case MODIFY_EXPR: ! 4304: { ! 4305: /* If lhs is complex, expand calls in rhs before computing it. ! 4306: That's so we don't compute a pointer and save it over a call. ! 4307: If lhs is simple, compute it first so we can give it as a ! 4308: target if the rhs is just a call. This avoids an extra temp and copy ! 4309: and that prevents a partial-subsumption which makes bad code. ! 4310: Actually we could treat component_ref's of vars like vars. */ ! 4311: ! 4312: tree lhs = TREE_OPERAND (exp, 0); ! 4313: tree rhs = TREE_OPERAND (exp, 1); ! 4314: tree noncopied_parts = 0; ! 4315: tree lhs_type = TREE_TYPE (lhs); ! 4316: ! 4317: temp = 0; ! 4318: ! 4319: if (TREE_CODE (lhs) != VAR_DECL ! 4320: && TREE_CODE (lhs) != RESULT_DECL ! 4321: && TREE_CODE (lhs) != PARM_DECL) ! 4322: preexpand_calls (exp); ! 4323: ! 4324: /* Check for |= or &= of a bitfield of size one into another bitfield ! 4325: of size 1. In this case, (unless we need the result of the ! 4326: assignment) we can do this more efficiently with a ! 4327: test followed by an assignment, if necessary. ! 4328: ! 4329: ??? At this point, we can't get a BIT_FIELD_REF here. But if ! 4330: things change so we do, this code should be enhanced to ! 4331: support it. */ ! 4332: if (ignore ! 4333: && TREE_CODE (lhs) == COMPONENT_REF ! 4334: && (TREE_CODE (rhs) == BIT_IOR_EXPR ! 4335: || TREE_CODE (rhs) == BIT_AND_EXPR) ! 4336: && TREE_OPERAND (rhs, 0) == lhs ! 4337: && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF ! 4338: && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (lhs, 1))) == 1 ! 4339: && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))) == 1) ! 4340: { ! 4341: rtx label = gen_label_rtx (); ! 4342: ! 4343: do_jump (TREE_OPERAND (rhs, 1), ! 4344: TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0, ! 4345: TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0); ! 4346: expand_assignment (lhs, convert (TREE_TYPE (rhs), ! 4347: (TREE_CODE (rhs) == BIT_IOR_EXPR ! 4348: ? integer_one_node ! 4349: : integer_zero_node)), ! 4350: 0, 0); ! 4351: emit_label (label); ! 4352: return const0_rtx; ! 4353: } ! 4354: ! 4355: if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 ! 4356: && ! (fixed_type_p (lhs) && fixed_type_p (rhs))) ! 4357: noncopied_parts = save_noncopied_parts (stabilize_reference (lhs), ! 4358: TYPE_NONCOPIED_PARTS (lhs_type)); ! 4359: ! 4360: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); ! 4361: while (noncopied_parts != 0) ! 4362: { ! 4363: expand_assignment (TREE_PURPOSE (noncopied_parts), ! 4364: TREE_VALUE (noncopied_parts), 0, 0); ! 4365: noncopied_parts = TREE_CHAIN (noncopied_parts); ! 4366: } ! 4367: return temp; ! 4368: } ! 4369: ! 4370: case PREINCREMENT_EXPR: ! 4371: case PREDECREMENT_EXPR: ! 4372: return expand_increment (exp, 0); ! 4373: ! 4374: case POSTINCREMENT_EXPR: ! 4375: case POSTDECREMENT_EXPR: ! 4376: /* Faster to treat as pre-increment if result is not used. */ ! 4377: return expand_increment (exp, ! ignore); ! 4378: ! 4379: case ADDR_EXPR: ! 4380: /* Are we taking the address of a nested function? */ ! 4381: if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL ! 4382: && decl_function_context (TREE_OPERAND (exp, 0)) != 0) ! 4383: { ! 4384: op0 = trampoline_address (TREE_OPERAND (exp, 0)); ! 4385: op0 = force_operand (op0, target); ! 4386: } ! 4387: else ! 4388: { ! 4389: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, ! 4390: (modifier == EXPAND_INITIALIZER ! 4391: ? modifier : EXPAND_CONST_ADDRESS)); ! 4392: if (GET_CODE (op0) != MEM) ! 4393: abort (); ! 4394: ! 4395: if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 4396: return XEXP (op0, 0); ! 4397: op0 = force_operand (XEXP (op0, 0), target); ! 4398: } ! 4399: if (flag_force_addr && GET_CODE (op0) != REG) ! 4400: return force_reg (Pmode, op0); ! 4401: return op0; ! 4402: ! 4403: case ENTRY_VALUE_EXPR: ! 4404: abort (); ! 4405: ! 4406: case ERROR_MARK: ! 4407: return const0_rtx; ! 4408: ! 4409: default: ! 4410: return (*lang_expand_expr) (exp, target, tmode, modifier); ! 4411: } ! 4412: ! 4413: /* Here to do an ordinary binary operator, generating an instruction ! 4414: from the optab already placed in `this_optab'. */ ! 4415: binop: ! 4416: preexpand_calls (exp); ! 4417: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 4418: subtarget = 0; ! 4419: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 4420: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 4421: binop2: ! 4422: temp = expand_binop (mode, this_optab, op0, op1, target, ! 4423: unsignedp, OPTAB_LIB_WIDEN); ! 4424: if (temp == 0) ! 4425: abort (); ! 4426: return temp; ! 4427: } ! 4428: ! 4429: /* Return the alignment of EXP, a pointer valued expression for the mem* ! 4430: builtin functions. Alignments greater than MAX_ALIGN are not significant. ! 4431: The alignment returned is, by default, the alignment of the thing that ! 4432: EXP points to (if it is not a POINTER_TYPE, 0 is returned). ! 4433: ! 4434: Otherwise, look at the expression to see if we can do better, i.e., if the ! 4435: expression is actually pointing at an object whose alignment is tighter. */ ! 4436: ! 4437: static int ! 4438: get_pointer_alignment (exp, max_align) ! 4439: tree exp; ! 4440: unsigned max_align; ! 4441: { ! 4442: unsigned align, inner; ! 4443: ! 4444: if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) ! 4445: return 0; ! 4446: ! 4447: align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); ! 4448: align = MIN (align, max_align); ! 4449: ! 4450: while (1) ! 4451: { ! 4452: switch (TREE_CODE (exp)) ! 4453: { ! 4454: case NOP_EXPR: ! 4455: case CONVERT_EXPR: ! 4456: case NON_LVALUE_EXPR: ! 4457: exp = TREE_OPERAND (exp, 0); ! 4458: if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) ! 4459: return align; ! 4460: inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); ! 4461: inner = MIN (inner, max_align); ! 4462: align = MAX (align, inner); ! 4463: break; ! 4464: ! 4465: case PLUS_EXPR: ! 4466: /* If sum of pointer + int, restrict our maximum alignment to that ! 4467: imposed by the integer. If not, we can't do any better than ! 4468: ALIGN. */ ! 4469: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST) ! 4470: return align; ! 4471: ! 4472: while ((TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! 4473: & (max_align - 1)) != 0) ! 4474: max_align >>= 1; ! 4475: ! 4476: exp = TREE_OPERAND (exp, 0); ! 4477: break; ! 4478: ! 4479: case ADDR_EXPR: ! 4480: /* See what we are pointing at and look at its alignment. */ ! 4481: exp = TREE_OPERAND (exp, 0); ! 4482: if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd') ! 4483: align = MAX (align, DECL_ALIGN (exp)); ! 4484: #ifdef CONSTANT_ALIGNMENT ! 4485: else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c') ! 4486: align = CONSTANT_ALIGNMENT (exp, align); ! 4487: #endif ! 4488: return MIN (align, max_align); ! 4489: ! 4490: default: ! 4491: return align; ! 4492: } ! 4493: } ! 4494: } ! 4495: ! 4496: /* Return the tree node and offset if a given argument corresponds to ! 4497: a string constant. */ ! 4498: ! 4499: static tree ! 4500: string_constant (arg, ptr_offset) ! 4501: tree arg; ! 4502: tree *ptr_offset; ! 4503: { ! 4504: STRIP_NOPS (arg); ! 4505: ! 4506: if (TREE_CODE (arg) == ADDR_EXPR ! 4507: && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST) ! 4508: { ! 4509: *ptr_offset = integer_zero_node; ! 4510: return TREE_OPERAND (arg, 0); ! 4511: } ! 4512: else if (TREE_CODE (arg) == PLUS_EXPR) ! 4513: { ! 4514: tree arg0 = TREE_OPERAND (arg, 0); ! 4515: tree arg1 = TREE_OPERAND (arg, 1); ! 4516: ! 4517: STRIP_NOPS (arg0); ! 4518: STRIP_NOPS (arg1); ! 4519: ! 4520: if (TREE_CODE (arg0) == ADDR_EXPR ! 4521: && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST) ! 4522: { ! 4523: *ptr_offset = arg1; ! 4524: return TREE_OPERAND (arg0, 0); ! 4525: } ! 4526: else if (TREE_CODE (arg1) == ADDR_EXPR ! 4527: && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST) ! 4528: { ! 4529: *ptr_offset = arg0; ! 4530: return TREE_OPERAND (arg1, 0); ! 4531: } ! 4532: } ! 4533: ! 4534: return 0; ! 4535: } ! 4536: ! 4537: /* Compute the length of a C string. TREE_STRING_LENGTH is not the right ! 4538: way, because it could contain a zero byte in the middle. ! 4539: TREE_STRING_LENGTH is the size of the character array, not the string. ! 4540: ! 4541: Unfortunately, string_constant can't access the values of const char ! 4542: arrays with initializers, so neither can we do so here. */ ! 4543: ! 4544: static tree ! 4545: c_strlen (src) ! 4546: tree src; ! 4547: { ! 4548: tree offset_node; ! 4549: int offset, max; ! 4550: char *ptr; ! 4551: ! 4552: src = string_constant (src, &offset_node); ! 4553: if (src == 0) ! 4554: return 0; ! 4555: max = TREE_STRING_LENGTH (src); ! 4556: ptr = TREE_STRING_POINTER (src); ! 4557: if (offset_node && TREE_CODE (offset_node) != INTEGER_CST) ! 4558: { ! 4559: /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't ! 4560: compute the offset to the following null if we don't know where to ! 4561: start searching for it. */ ! 4562: int i; ! 4563: for (i = 0; i < max; i++) ! 4564: if (ptr[i] == 0) ! 4565: return 0; ! 4566: /* We don't know the starting offset, but we do know that the string ! 4567: has no internal zero bytes. We can assume that the offset falls ! 4568: within the bounds of the string; otherwise, the programmer deserves ! 4569: what he gets. Subtract the offset from the length of the string, ! 4570: and return that. */ ! 4571: /* This would perhaps not be valid if we were dealing with named ! 4572: arrays in addition to literal string constants. */ ! 4573: return size_binop (MINUS_EXPR, size_int (max), offset_node); ! 4574: } ! 4575: ! 4576: /* We have a known offset into the string. Start searching there for ! 4577: a null character. */ ! 4578: if (offset_node == 0) ! 4579: offset = 0; ! 4580: else ! 4581: { ! 4582: /* Did we get a long long offset? If so, punt. */ ! 4583: if (TREE_INT_CST_HIGH (offset_node) != 0) ! 4584: return 0; ! 4585: offset = TREE_INT_CST_LOW (offset_node); ! 4586: } ! 4587: /* If the offset is known to be out of bounds, warn, and call strlen at ! 4588: runtime. */ ! 4589: if (offset < 0 || offset > max) ! 4590: { ! 4591: warning ("offset outside bounds of constant string"); ! 4592: return 0; ! 4593: } ! 4594: /* Use strlen to search for the first zero byte. Since any strings ! 4595: constructed with build_string will have nulls appended, we win even ! 4596: if we get handed something like (char[4])"abcd". ! 4597: ! 4598: Since OFFSET is our starting index into the string, no further ! 4599: calculation is needed. */ ! 4600: return size_int (strlen (ptr + offset)); ! 4601: } ! 4602: ! 4603: /* Expand an expression EXP that calls a built-in function, ! 4604: with result going to TARGET if that's convenient ! 4605: (and in mode MODE if that's convenient). ! 4606: SUBTARGET may be used as the target for computing one of EXP's operands. ! 4607: IGNORE is nonzero if the value is to be ignored. */ ! 4608: ! 4609: static rtx ! 4610: expand_builtin (exp, target, subtarget, mode, ignore) ! 4611: tree exp; ! 4612: rtx target; ! 4613: rtx subtarget; ! 4614: enum machine_mode mode; ! 4615: int ignore; ! 4616: { ! 4617: tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); ! 4618: tree arglist = TREE_OPERAND (exp, 1); ! 4619: rtx op0; ! 4620: enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); ! 4621: ! 4622: switch (DECL_FUNCTION_CODE (fndecl)) ! 4623: { ! 4624: case BUILT_IN_ABS: ! 4625: case BUILT_IN_LABS: ! 4626: case BUILT_IN_FABS: ! 4627: /* build_function_call changes these into ABS_EXPR. */ ! 4628: abort (); ! 4629: ! 4630: case BUILT_IN_SAVEREGS: ! 4631: /* Don't do __builtin_saveregs more than once in a function. ! 4632: Save the result of the first call and reuse it. */ ! 4633: if (saveregs_value != 0) ! 4634: return saveregs_value; ! 4635: { ! 4636: /* When this function is called, it means that registers must be ! 4637: saved on entry to this function. So we migrate the ! 4638: call to the first insn of this function. */ ! 4639: rtx temp; ! 4640: rtx seq; ! 4641: rtx valreg, saved_valreg; ! 4642: ! 4643: /* Now really call the function. `expand_call' does not call ! 4644: expand_builtin, so there is no danger of infinite recursion here. */ ! 4645: start_sequence (); ! 4646: ! 4647: #ifdef EXPAND_BUILTIN_SAVEREGS ! 4648: /* Do whatever the machine needs done in this case. */ ! 4649: temp = EXPAND_BUILTIN_SAVEREGS (arglist); ! 4650: #else ! 4651: /* The register where the function returns its value ! 4652: is likely to have something else in it, such as an argument. ! 4653: So preserve that register around the call. */ ! 4654: if (value_mode != VOIDmode) ! 4655: { ! 4656: valreg = hard_libcall_value (value_mode); ! 4657: saved_valreg = gen_reg_rtx (value_mode); ! 4658: emit_move_insn (saved_valreg, valreg); ! 4659: } ! 4660: ! 4661: /* Generate the call, putting the value in a pseudo. */ ! 4662: temp = expand_call (exp, target, ignore); ! 4663: ! 4664: if (value_mode != VOIDmode) ! 4665: emit_move_insn (valreg, saved_valreg); ! 4666: #endif ! 4667: ! 4668: seq = get_insns (); ! 4669: end_sequence (); ! 4670: ! 4671: saveregs_value = temp; ! 4672: ! 4673: /* This won't work inside a SEQUENCE--it really has to be ! 4674: at the start of the function. */ ! 4675: if (in_sequence_p ()) ! 4676: { ! 4677: /* Better to do this than to crash. */ ! 4678: error ("`va_start' used within `({...})'"); ! 4679: return temp; ! 4680: } ! 4681: ! 4682: /* Put the sequence after the NOTE that starts the function. */ ! 4683: emit_insns_before (seq, NEXT_INSN (get_insns ())); ! 4684: return temp; ! 4685: } ! 4686: ! 4687: /* __builtin_args_info (N) returns word N of the arg space info ! 4688: for the current function. The number and meanings of words ! 4689: is controlled by the definition of CUMULATIVE_ARGS. */ ! 4690: case BUILT_IN_ARGS_INFO: ! 4691: { ! 4692: int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int); ! 4693: int i; ! 4694: int *word_ptr = (int *) ¤t_function_args_info; ! 4695: tree type, elts, result; ! 4696: ! 4697: if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0) ! 4698: fatal ("CUMULATIVE_ARGS type defined badly; see %s, line %d", ! 4699: __FILE__, __LINE__); ! 4700: ! 4701: if (arglist != 0) ! 4702: { ! 4703: tree arg = TREE_VALUE (arglist); ! 4704: if (TREE_CODE (arg) != INTEGER_CST) ! 4705: error ("argument of __builtin_args_info must be constant"); ! 4706: else ! 4707: { ! 4708: int wordnum = TREE_INT_CST_LOW (arg); ! 4709: ! 4710: if (wordnum < 0 || wordnum >= nwords) ! 4711: error ("argument of __builtin_args_info out of range"); ! 4712: else ! 4713: return gen_rtx (CONST_INT, VOIDmode, word_ptr[wordnum]); ! 4714: } ! 4715: } ! 4716: else ! 4717: error ("missing argument in __builtin_args_info"); ! 4718: ! 4719: return const0_rtx; ! 4720: ! 4721: #if 0 ! 4722: for (i = 0; i < nwords; i++) ! 4723: elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0)); ! 4724: ! 4725: type = build_array_type (integer_type_node, ! 4726: build_index_type (build_int_2 (nwords, 0))); ! 4727: result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts)); ! 4728: TREE_CONSTANT (result) = 1; ! 4729: TREE_STATIC (result) = 1; ! 4730: result = build (INDIRECT_REF, build_pointer_type (type), result); ! 4731: TREE_CONSTANT (result) = 1; ! 4732: return expand_expr (result, 0, VOIDmode, 0); ! 4733: #endif ! 4734: } ! 4735: ! 4736: /* Return the address of the first anonymous stack arg. */ ! 4737: case BUILT_IN_NEXT_ARG: ! 4738: { ! 4739: tree fntype = TREE_TYPE (current_function_decl); ! 4740: if (!(TYPE_ARG_TYPES (fntype) != 0 ! 4741: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) ! 4742: != void_type_node))) ! 4743: { ! 4744: error ("`va_start' used in function with fixed args"); ! 4745: return const0_rtx; ! 4746: } ! 4747: } ! 4748: ! 4749: return expand_binop (Pmode, add_optab, ! 4750: current_function_internal_arg_pointer, ! 4751: current_function_arg_offset_rtx, ! 4752: 0, 0, OPTAB_LIB_WIDEN); ! 4753: ! 4754: case BUILT_IN_CLASSIFY_TYPE: ! 4755: if (arglist != 0) ! 4756: { ! 4757: tree type = TREE_TYPE (TREE_VALUE (arglist)); ! 4758: enum tree_code code = TREE_CODE (type); ! 4759: if (code == VOID_TYPE) ! 4760: return gen_rtx (CONST_INT, VOIDmode, void_type_class); ! 4761: if (code == INTEGER_TYPE) ! 4762: return gen_rtx (CONST_INT, VOIDmode, integer_type_class); ! 4763: if (code == CHAR_TYPE) ! 4764: return gen_rtx (CONST_INT, VOIDmode, char_type_class); ! 4765: if (code == ENUMERAL_TYPE) ! 4766: return gen_rtx (CONST_INT, VOIDmode, enumeral_type_class); ! 4767: if (code == BOOLEAN_TYPE) ! 4768: return gen_rtx (CONST_INT, VOIDmode, boolean_type_class); ! 4769: if (code == POINTER_TYPE) ! 4770: return gen_rtx (CONST_INT, VOIDmode, pointer_type_class); ! 4771: if (code == REFERENCE_TYPE) ! 4772: return gen_rtx (CONST_INT, VOIDmode, reference_type_class); ! 4773: if (code == OFFSET_TYPE) ! 4774: return gen_rtx (CONST_INT, VOIDmode, offset_type_class); ! 4775: if (code == REAL_TYPE) ! 4776: return gen_rtx (CONST_INT, VOIDmode, real_type_class); ! 4777: if (code == COMPLEX_TYPE) ! 4778: return gen_rtx (CONST_INT, VOIDmode, complex_type_class); ! 4779: if (code == FUNCTION_TYPE) ! 4780: return gen_rtx (CONST_INT, VOIDmode, function_type_class); ! 4781: if (code == METHOD_TYPE) ! 4782: return gen_rtx (CONST_INT, VOIDmode, method_type_class); ! 4783: if (code == RECORD_TYPE) ! 4784: return gen_rtx (CONST_INT, VOIDmode, record_type_class); ! 4785: if (code == UNION_TYPE) ! 4786: return gen_rtx (CONST_INT, VOIDmode, union_type_class); ! 4787: if (code == ARRAY_TYPE) ! 4788: return gen_rtx (CONST_INT, VOIDmode, array_type_class); ! 4789: if (code == STRING_TYPE) ! 4790: return gen_rtx (CONST_INT, VOIDmode, string_type_class); ! 4791: if (code == SET_TYPE) ! 4792: return gen_rtx (CONST_INT, VOIDmode, set_type_class); ! 4793: if (code == FILE_TYPE) ! 4794: return gen_rtx (CONST_INT, VOIDmode, file_type_class); ! 4795: if (code == LANG_TYPE) ! 4796: return gen_rtx (CONST_INT, VOIDmode, lang_type_class); ! 4797: } ! 4798: return gen_rtx (CONST_INT, VOIDmode, no_type_class); ! 4799: ! 4800: case BUILT_IN_CONSTANT_P: ! 4801: if (arglist == 0) ! 4802: return const0_rtx; ! 4803: else ! 4804: return (TREE_CODE_CLASS (TREE_VALUE (arglist)) == 'c' ! 4805: ? const1_rtx : const0_rtx); ! 4806: ! 4807: case BUILT_IN_FRAME_ADDRESS: ! 4808: /* The argument must be a nonnegative integer constant. ! 4809: It counts the number of frames to scan up the stack. ! 4810: The value is the address of that frame. */ ! 4811: case BUILT_IN_RETURN_ADDRESS: ! 4812: /* The argument must be a nonnegative integer constant. ! 4813: It counts the number of frames to scan up the stack. ! 4814: The value is the return address saved in that frame. */ ! 4815: if (arglist == 0) ! 4816: /* Warning about missing arg was already issued. */ ! 4817: return const0_rtx; ! 4818: else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST) ! 4819: { ! 4820: error ("invalid arg to __builtin_return_address"); ! 4821: return const0_rtx; ! 4822: } ! 4823: else if (tree_int_cst_lt (TREE_VALUE (arglist), integer_zero_node)) ! 4824: { ! 4825: error ("invalid arg to __builtin_return_address"); ! 4826: return const0_rtx; ! 4827: } ! 4828: else ! 4829: { ! 4830: int count = TREE_INT_CST_LOW (TREE_VALUE (arglist)); ! 4831: rtx tem = frame_pointer_rtx; ! 4832: int i; ! 4833: ! 4834: /* Scan back COUNT frames to the specified frame. */ ! 4835: for (i = 0; i < count; i++) ! 4836: { ! 4837: /* Assume the dynamic chain pointer is in the word that ! 4838: the frame address points to, unless otherwise specified. */ ! 4839: #ifdef DYNAMIC_CHAIN_ADDRESS ! 4840: tem = DYNAMIC_CHAIN_ADDRESS (tem); ! 4841: #endif ! 4842: tem = memory_address (Pmode, tem); ! 4843: tem = copy_to_reg (gen_rtx (MEM, Pmode, tem)); ! 4844: } ! 4845: ! 4846: /* For __builtin_frame_address, return what we've got. */ ! 4847: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) ! 4848: return tem; ! 4849: ! 4850: /* For __builtin_return_address, ! 4851: Get the return address from that frame. */ ! 4852: #ifdef RETURN_ADDR_RTX ! 4853: return RETURN_ADDR_RTX (count, tem); ! 4854: #else ! 4855: tem = memory_address (Pmode, ! 4856: plus_constant (tem, GET_MODE_SIZE (Pmode))); ! 4857: return copy_to_reg (gen_rtx (MEM, Pmode, tem)); ! 4858: #endif ! 4859: } ! 4860: ! 4861: case BUILT_IN_ALLOCA: ! 4862: if (arglist == 0 ! 4863: /* Arg could be non-integer if user redeclared this fcn wrong. */ ! 4864: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE) ! 4865: return const0_rtx; ! 4866: current_function_calls_alloca = 1; ! 4867: /* Compute the argument. */ ! 4868: op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0); ! 4869: ! 4870: /* Allocate the desired space. */ ! 4871: target = allocate_dynamic_stack_space (op0, target); ! 4872: ! 4873: /* Record the new stack level for nonlocal gotos. */ ! 4874: if (nonlocal_goto_stack_level != 0) ! 4875: emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx); ! 4876: return target; ! 4877: ! 4878: case BUILT_IN_FFS: ! 4879: /* If not optimizing, call the library function. */ ! 4880: if (!optimize) ! 4881: break; ! 4882: ! 4883: if (arglist == 0 ! 4884: /* Arg could be non-integer if user redeclared this fcn wrong. */ ! 4885: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE) ! 4886: return const0_rtx; ! 4887: ! 4888: /* Compute the argument. */ ! 4889: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); ! 4890: /* Compute ffs, into TARGET if possible. ! 4891: Set TARGET to wherever the result comes back. */ ! 4892: target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), ! 4893: ffs_optab, op0, target, 1); ! 4894: if (target == 0) ! 4895: abort (); ! 4896: return target; ! 4897: ! 4898: case BUILT_IN_STRLEN: ! 4899: /* If not optimizing, call the library function. */ ! 4900: if (!optimize) ! 4901: break; ! 4902: ! 4903: if (arglist == 0 ! 4904: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 4905: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) ! 4906: return const0_rtx; ! 4907: else ! 4908: { ! 4909: tree len = c_strlen (TREE_VALUE (arglist)); ! 4910: ! 4911: if (len == 0) ! 4912: break; ! 4913: return expand_expr (len, target, mode, 0); ! 4914: } ! 4915: ! 4916: case BUILT_IN_STRCPY: ! 4917: /* If not optimizing, call the library function. */ ! 4918: if (!optimize) ! 4919: break; ! 4920: ! 4921: if (arglist == 0 ! 4922: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 4923: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 4924: || TREE_CHAIN (arglist) == 0 ! 4925: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE) ! 4926: return const0_rtx; ! 4927: else ! 4928: { ! 4929: tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist))); ! 4930: ! 4931: if (len == 0) ! 4932: break; ! 4933: ! 4934: len = size_binop (PLUS_EXPR, len, integer_one_node); ! 4935: ! 4936: chainon (arglist, build_tree_list (0, len)); ! 4937: } ! 4938: ! 4939: /* Drops in. */ ! 4940: case BUILT_IN_MEMCPY: ! 4941: /* If not optimizing, call the library function. */ ! 4942: if (!optimize) ! 4943: break; ! 4944: ! 4945: if (arglist == 0 ! 4946: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 4947: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 4948: || TREE_CHAIN (arglist) == 0 ! 4949: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE ! 4950: || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 ! 4951: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE) ! 4952: return const0_rtx; ! 4953: else ! 4954: { ! 4955: tree dest = TREE_VALUE (arglist); ! 4956: tree src = TREE_VALUE (TREE_CHAIN (arglist)); ! 4957: tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); ! 4958: ! 4959: int src_align ! 4960: = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 4961: int dest_align ! 4962: = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 4963: rtx dest_rtx; ! 4964: ! 4965: /* If either SRC or DEST is not a pointer type, don't do ! 4966: this operation in-line. */ ! 4967: if (src_align == 0 || dest_align == 0) ! 4968: { ! 4969: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCPY) ! 4970: TREE_CHAIN (TREE_CHAIN (arglist)) = 0; ! 4971: break; ! 4972: } ! 4973: ! 4974: dest_rtx = expand_expr (dest, 0, Pmode, EXPAND_NORMAL); ! 4975: ! 4976: /* Copy word part most expediently. */ ! 4977: emit_block_move (gen_rtx (MEM, BLKmode, ! 4978: memory_address (BLKmode, dest_rtx)), ! 4979: gen_rtx (MEM, BLKmode, ! 4980: memory_address (BLKmode, ! 4981: expand_expr (src, 0, Pmode, ! 4982: EXPAND_NORMAL))), ! 4983: expand_expr (len, 0, VOIDmode, 0), ! 4984: MIN (src_align, dest_align)); ! 4985: return dest_rtx; ! 4986: } ! 4987: ! 4988: /* These comparison functions need an instruction that returns an actual ! 4989: index. An ordinary compare that just sets the condition codes ! 4990: is not enough. */ ! 4991: #ifdef HAVE_cmpstrsi ! 4992: case BUILT_IN_STRCMP: ! 4993: /* If not optimizing, call the library function. */ ! 4994: if (!optimize) ! 4995: break; ! 4996: ! 4997: if (arglist == 0 ! 4998: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 4999: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 5000: || TREE_CHAIN (arglist) == 0 ! 5001: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE) ! 5002: return const0_rtx; ! 5003: else if (!HAVE_cmpstrsi) ! 5004: break; ! 5005: { ! 5006: tree arg1 = TREE_VALUE (arglist); ! 5007: tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); ! 5008: tree offset; ! 5009: tree len, len2; ! 5010: ! 5011: len = c_strlen (arg1); ! 5012: if (len) ! 5013: len = size_binop (PLUS_EXPR, integer_one_node, len); ! 5014: len2 = c_strlen (arg2); ! 5015: if (len2) ! 5016: len2 = size_binop (PLUS_EXPR, integer_one_node, len2); ! 5017: ! 5018: /* If we don't have a constant length for the first, use the length ! 5019: of the second, if we know it. We don't require a constant for ! 5020: this case; some cost analysis could be done if both are available ! 5021: but neither is constant. For now, assume they're equally cheap. ! 5022: ! 5023: If both strings have constant lengths, use the smaller. This ! 5024: could arise if optimization results in strcpy being called with ! 5025: two fixed strings, or if the code was machine-generated. We should ! 5026: add some code to the `memcmp' handler below to deal with such ! 5027: situations, someday. */ ! 5028: if (!len || TREE_CODE (len) != INTEGER_CST) ! 5029: { ! 5030: if (len2) ! 5031: len = len2; ! 5032: else if (len == 0) ! 5033: break; ! 5034: } ! 5035: else if (len2 && TREE_CODE (len2) == INTEGER_CST) ! 5036: { ! 5037: if (tree_int_cst_lt (len2, len)) ! 5038: len = len2; ! 5039: } ! 5040: ! 5041: chainon (arglist, build_tree_list (0, len)); ! 5042: } ! 5043: ! 5044: /* Drops in. */ ! 5045: case BUILT_IN_MEMCMP: ! 5046: /* If not optimizing, call the library function. */ ! 5047: if (!optimize) ! 5048: break; ! 5049: ! 5050: if (arglist == 0 ! 5051: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 5052: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 5053: || TREE_CHAIN (arglist) == 0 ! 5054: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE ! 5055: || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 ! 5056: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE) ! 5057: return const0_rtx; ! 5058: else if (!HAVE_cmpstrsi) ! 5059: break; ! 5060: { ! 5061: tree arg1 = TREE_VALUE (arglist); ! 5062: tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); ! 5063: tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); ! 5064: rtx result; ! 5065: ! 5066: int arg1_align ! 5067: = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 5068: int arg2_align ! 5069: = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 5070: enum machine_mode insn_mode ! 5071: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; ! 5072: ! 5073: /* If we don't have POINTER_TYPE, call the function. */ ! 5074: if (arg1_align == 0 || arg2_align == 0) ! 5075: { ! 5076: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCMP) ! 5077: TREE_CHAIN (TREE_CHAIN (arglist)) = 0; ! 5078: break; ! 5079: } ! 5080: ! 5081: /* Make a place to write the result of the instruction. */ ! 5082: result = target; ! 5083: if (! (result != 0 ! 5084: && GET_CODE (result) == REG && GET_MODE (result) == insn_mode ! 5085: && REGNO (result) >= FIRST_PSEUDO_REGISTER)) ! 5086: result = gen_reg_rtx (insn_mode); ! 5087: ! 5088: emit_insn (gen_cmpstrsi (result, ! 5089: gen_rtx (MEM, BLKmode, ! 5090: expand_expr (arg1, 0, Pmode, EXPAND_NORMAL)), ! 5091: gen_rtx (MEM, BLKmode, ! 5092: expand_expr (arg2, 0, Pmode, EXPAND_NORMAL)), ! 5093: expand_expr (len, 0, VOIDmode, 0), ! 5094: gen_rtx (CONST_INT, VOIDmode, ! 5095: MIN (arg1_align, arg2_align)))); ! 5096: ! 5097: /* Return the value in the proper mode for this function. */ ! 5098: mode = TYPE_MODE (TREE_TYPE (exp)); ! 5099: if (GET_MODE (result) == mode) ! 5100: return result; ! 5101: else if (target != 0) ! 5102: { ! 5103: convert_move (target, result, 0); ! 5104: return target; ! 5105: } ! 5106: else ! 5107: return convert_to_mode (mode, result, 0); ! 5108: } ! 5109: #else ! 5110: case BUILT_IN_STRCMP: ! 5111: case BUILT_IN_MEMCMP: ! 5112: break; ! 5113: #endif ! 5114: ! 5115: default: /* just do library call, if unknown builtin */ ! 5116: error ("built-in function %s not currently supported", ! 5117: IDENTIFIER_POINTER (DECL_NAME (fndecl))); ! 5118: } ! 5119: ! 5120: /* The switch statement above can drop through to cause the function ! 5121: to be called normally. */ ! 5122: ! 5123: return expand_call (exp, target, ignore); ! 5124: } ! 5125: ! 5126: /* Expand code for a post- or pre- increment or decrement ! 5127: and return the RTX for the result. ! 5128: POST is 1 for postinc/decrements and 0 for preinc/decrements. */ ! 5129: ! 5130: static rtx ! 5131: expand_increment (exp, post) ! 5132: register tree exp; ! 5133: int post; ! 5134: { ! 5135: register rtx op0, op1; ! 5136: register rtx temp, value; ! 5137: register tree incremented = TREE_OPERAND (exp, 0); ! 5138: optab this_optab = add_optab; ! 5139: int icode; ! 5140: enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); ! 5141: int op0_is_copy = 0; ! 5142: ! 5143: /* Stabilize any component ref that might need to be ! 5144: evaluated more than once below. */ ! 5145: if (TREE_CODE (incremented) == BIT_FIELD_REF ! 5146: || (TREE_CODE (incremented) == COMPONENT_REF ! 5147: && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF ! 5148: || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1))))) ! 5149: incremented = stabilize_reference (incremented); ! 5150: ! 5151: /* Compute the operands as RTX. ! 5152: Note whether OP0 is the actual lvalue or a copy of it: ! 5153: I believe it is a copy iff it is a register and insns were ! 5154: generated in computing it. */ ! 5155: temp = get_last_insn (); ! 5156: op0 = expand_expr (incremented, 0, VOIDmode, 0); ! 5157: if (temp != get_last_insn ()) ! 5158: op0_is_copy = (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG); ! 5159: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 5160: ! 5161: /* Decide whether incrementing or decrementing. */ ! 5162: if (TREE_CODE (exp) == POSTDECREMENT_EXPR ! 5163: || TREE_CODE (exp) == PREDECREMENT_EXPR) ! 5164: this_optab = sub_optab; ! 5165: ! 5166: /* If OP0 is not the actual lvalue, but rather a copy in a register, ! 5167: then we cannot just increment OP0. We must ! 5168: therefore contrive to increment the original value. ! 5169: Then we can return OP0 since it is a copy of the old value. */ ! 5170: if (op0_is_copy) ! 5171: { ! 5172: /* This is the easiest way to increment the value wherever it is. ! 5173: Problems with multiple evaluation of INCREMENTED ! 5174: are prevented because either (1) it is a component_ref, ! 5175: in which case it was stabilized above, or (2) it is an array_ref ! 5176: with constant index in an array in a register, which is ! 5177: safe to reevaluate. */ ! 5178: tree newexp = build ((this_optab == add_optab ! 5179: ? PLUS_EXPR : MINUS_EXPR), ! 5180: TREE_TYPE (exp), ! 5181: incremented, ! 5182: TREE_OPERAND (exp, 1)); ! 5183: temp = expand_assignment (incremented, newexp, ! post, 0); ! 5184: return post ? op0 : temp; ! 5185: } ! 5186: ! 5187: /* Convert decrement by a constant into a negative increment. */ ! 5188: if (this_optab == sub_optab ! 5189: && GET_CODE (op1) == CONST_INT) ! 5190: { ! 5191: op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1)); ! 5192: this_optab = add_optab; ! 5193: } ! 5194: ! 5195: if (post) ! 5196: { ! 5197: /* We have a true reference to the value in OP0. ! 5198: If there is an insn to add or subtract in this mode, queue it. */ ! 5199: ! 5200: #if 0 /* Turned off to avoid making extra insn for indexed memref. */ ! 5201: op0 = stabilize (op0); ! 5202: #endif ! 5203: ! 5204: icode = (int) this_optab->handlers[(int) mode].insn_code; ! 5205: if (icode != (int) CODE_FOR_nothing ! 5206: /* Make sure that OP0 is valid for operands 0 and 1 ! 5207: of the insn we want to queue. */ ! 5208: && (*insn_operand_predicate[icode][0]) (op0, mode) ! 5209: && (*insn_operand_predicate[icode][1]) (op0, mode)) ! 5210: { ! 5211: if (! (*insn_operand_predicate[icode][2]) (op1, mode)) ! 5212: op1 = force_reg (mode, op1); ! 5213: ! 5214: return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1)); ! 5215: } ! 5216: } ! 5217: ! 5218: /* Preincrement, or we can't increment with one simple insn. */ ! 5219: if (post) ! 5220: /* Save a copy of the value before inc or dec, to return it later. */ ! 5221: temp = value = copy_to_reg (op0); ! 5222: else ! 5223: /* Arrange to return the incremented value. */ ! 5224: /* Copy the rtx because expand_binop will protect from the queue, ! 5225: and the results of that would be invalid for us to return ! 5226: if our caller does emit_queue before using our result. */ ! 5227: temp = copy_rtx (value = op0); ! 5228: ! 5229: /* Increment however we can. */ ! 5230: op1 = expand_binop (mode, this_optab, value, op1, op0, ! 5231: TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); ! 5232: /* Make sure the value is stored into OP0. */ ! 5233: if (op1 != op0) ! 5234: emit_move_insn (op0, op1); ! 5235: ! 5236: return temp; ! 5237: } ! 5238: ! 5239: /* Expand all function calls contained within EXP, innermost ones first. ! 5240: But don't look within expressions that have sequence points. ! 5241: For each CALL_EXPR, record the rtx for its value ! 5242: in the CALL_EXPR_RTL field. */ ! 5243: ! 5244: static void ! 5245: preexpand_calls (exp) ! 5246: tree exp; ! 5247: { ! 5248: register int nops, i; ! 5249: int type = TREE_CODE_CLASS (TREE_CODE (exp)); ! 5250: ! 5251: if (! do_preexpand_calls) ! 5252: return; ! 5253: ! 5254: /* Only expressions and references can contain calls. */ ! 5255: ! 5256: if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r') ! 5257: return; ! 5258: ! 5259: switch (TREE_CODE (exp)) ! 5260: { ! 5261: case CALL_EXPR: ! 5262: /* Do nothing if already expanded. */ ! 5263: if (CALL_EXPR_RTL (exp) != 0) ! 5264: return; ! 5265: ! 5266: /* Do nothing to built-in functions. */ ! 5267: if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR ! 5268: || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL ! 5269: || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 5270: CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0, 0); ! 5271: return; ! 5272: ! 5273: case COMPOUND_EXPR: ! 5274: case COND_EXPR: ! 5275: case TRUTH_ANDIF_EXPR: ! 5276: case TRUTH_ORIF_EXPR: ! 5277: /* If we find one of these, then we can be sure ! 5278: the adjust will be done for it (since it makes jumps). ! 5279: Do it now, so that if this is inside an argument ! 5280: of a function, we don't get the stack adjustment ! 5281: after some other args have already been pushed. */ ! 5282: do_pending_stack_adjust (); ! 5283: return; ! 5284: ! 5285: case BLOCK: ! 5286: case RTL_EXPR: ! 5287: case WITH_CLEANUP_EXPR: ! 5288: return; ! 5289: ! 5290: case SAVE_EXPR: ! 5291: if (SAVE_EXPR_RTL (exp) != 0) ! 5292: return; ! 5293: } ! 5294: ! 5295: nops = tree_code_length[(int) TREE_CODE (exp)]; ! 5296: for (i = 0; i < nops; i++) ! 5297: if (TREE_OPERAND (exp, i) != 0) ! 5298: { ! 5299: type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i))); ! 5300: if (type == 'e' || type == '<' || type == '1' || type == '2' ! 5301: || type == 'r') ! 5302: preexpand_calls (TREE_OPERAND (exp, i)); ! 5303: } ! 5304: } ! 5305: ! 5306: /* At the start of a function, record that we have no previously-pushed ! 5307: arguments waiting to be popped. */ ! 5308: ! 5309: void ! 5310: init_pending_stack_adjust () ! 5311: { ! 5312: pending_stack_adjust = 0; ! 5313: } ! 5314: ! 5315: /* When exiting from function, if safe, clear out any pending stack adjust ! 5316: so the adjustment won't get done. */ ! 5317: ! 5318: void ! 5319: clear_pending_stack_adjust () ! 5320: { ! 5321: #ifdef EXIT_IGNORE_STACK ! 5322: if (!flag_omit_frame_pointer && EXIT_IGNORE_STACK ! 5323: && ! (TREE_INLINE (current_function_decl) && optimize) ! 5324: && ! flag_inline_functions) ! 5325: pending_stack_adjust = 0; ! 5326: #endif ! 5327: } ! 5328: ! 5329: /* Pop any previously-pushed arguments that have not been popped yet. */ ! 5330: ! 5331: void ! 5332: do_pending_stack_adjust () ! 5333: { ! 5334: if (inhibit_defer_pop == 0) ! 5335: { ! 5336: if (pending_stack_adjust != 0) ! 5337: adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust)); ! 5338: pending_stack_adjust = 0; ! 5339: } ! 5340: } ! 5341: ! 5342: /* Expand all cleanups up to OLD_CLEANUPS. ! 5343: Needed here, and also for language-dependent calls. */ ! 5344: ! 5345: void ! 5346: expand_cleanups_to (old_cleanups) ! 5347: tree old_cleanups; ! 5348: { ! 5349: while (cleanups_this_call != old_cleanups) ! 5350: { ! 5351: expand_expr (TREE_VALUE (cleanups_this_call), 0, VOIDmode, 0); ! 5352: cleanups_this_call = TREE_CHAIN (cleanups_this_call); ! 5353: } ! 5354: } ! 5355: ! 5356: /* Expand conditional expressions. */ ! 5357: ! 5358: /* Generate code to evaluate EXP and jump to LABEL if the value is zero. ! 5359: LABEL is an rtx of code CODE_LABEL, in this function and all the ! 5360: functions here. */ ! 5361: ! 5362: void ! 5363: jumpifnot (exp, label) ! 5364: tree exp; ! 5365: rtx label; ! 5366: { ! 5367: do_jump (exp, label, 0); ! 5368: } ! 5369: ! 5370: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */ ! 5371: ! 5372: void ! 5373: jumpif (exp, label) ! 5374: tree exp; ! 5375: rtx label; ! 5376: { ! 5377: do_jump (exp, 0, label); ! 5378: } ! 5379: ! 5380: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if ! 5381: the result is zero, or IF_TRUE_LABEL if the result is one. ! 5382: Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero, ! 5383: meaning fall through in that case. ! 5384: ! 5385: This function is responsible for optimizing cases such as ! 5386: &&, || and comparison operators in EXP. */ ! 5387: ! 5388: void ! 5389: do_jump (exp, if_false_label, if_true_label) ! 5390: tree exp; ! 5391: rtx if_false_label, if_true_label; ! 5392: { ! 5393: register enum tree_code code = TREE_CODE (exp); ! 5394: /* Some cases need to create a label to jump to ! 5395: in order to properly fall through. ! 5396: These cases set DROP_THROUGH_LABEL nonzero. */ ! 5397: rtx drop_through_label = 0; ! 5398: rtx temp; ! 5399: rtx comparison = 0; ! 5400: int i; ! 5401: tree type; ! 5402: ! 5403: emit_queue (); ! 5404: ! 5405: switch (code) ! 5406: { ! 5407: case ERROR_MARK: ! 5408: break; ! 5409: ! 5410: case INTEGER_CST: ! 5411: temp = integer_zerop (exp) ? if_false_label : if_true_label; ! 5412: if (temp) ! 5413: emit_jump (temp); ! 5414: break; ! 5415: ! 5416: #if 0 ! 5417: /* This is not true with #pragma weak */ ! 5418: case ADDR_EXPR: ! 5419: /* The address of something can never be zero. */ ! 5420: if (if_true_label) ! 5421: emit_jump (if_true_label); ! 5422: break; ! 5423: #endif ! 5424: ! 5425: case NOP_EXPR: ! 5426: if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF ! 5427: || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF ! 5428: || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF) ! 5429: goto normal; ! 5430: case CONVERT_EXPR: ! 5431: /* If we are narrowing the operand, we have to do the compare in the ! 5432: narrower mode. */ ! 5433: if ((TYPE_PRECISION (TREE_TYPE (exp)) ! 5434: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5435: goto normal; ! 5436: case NON_LVALUE_EXPR: ! 5437: case REFERENCE_EXPR: ! 5438: case ABS_EXPR: ! 5439: case NEGATE_EXPR: ! 5440: case LROTATE_EXPR: ! 5441: case RROTATE_EXPR: ! 5442: /* These cannot change zero->non-zero or vice versa. */ ! 5443: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 5444: break; ! 5445: ! 5446: #if 0 ! 5447: /* This is never less insns than evaluating the PLUS_EXPR followed by ! 5448: a test and can be longer if the test is eliminated. */ ! 5449: case PLUS_EXPR: ! 5450: /* Reduce to minus. */ ! 5451: exp = build (MINUS_EXPR, TREE_TYPE (exp), ! 5452: TREE_OPERAND (exp, 0), ! 5453: fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)), ! 5454: TREE_OPERAND (exp, 1)))); ! 5455: /* Process as MINUS. */ ! 5456: #endif ! 5457: ! 5458: case MINUS_EXPR: ! 5459: /* Non-zero iff operands of minus differ. */ ! 5460: comparison = compare (build (NE_EXPR, TREE_TYPE (exp), ! 5461: TREE_OPERAND (exp, 0), ! 5462: TREE_OPERAND (exp, 1)), ! 5463: NE, NE); ! 5464: break; ! 5465: ! 5466: case BIT_AND_EXPR: ! 5467: /* If we are AND'ing with a small constant, do this comparison in the ! 5468: smallest type that fits. If the machine doesn't have comparisons ! 5469: that small, it will be converted back to the wider comparison. ! 5470: This helps if we are testing the sign bit of a narrower object. ! 5471: combine can't do this for us because it can't know whether a ! 5472: ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */ ! 5473: ! 5474: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 5475: && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_INT ! 5476: && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0 ! 5477: && (type = type_for_size (i + 1, 1)) != 0 ! 5478: && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))) ! 5479: { ! 5480: do_jump (convert (type, exp), if_false_label, if_true_label); ! 5481: break; ! 5482: } ! 5483: goto normal; ! 5484: ! 5485: case TRUTH_NOT_EXPR: ! 5486: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 5487: break; ! 5488: ! 5489: case TRUTH_ANDIF_EXPR: ! 5490: if (if_false_label == 0) ! 5491: if_false_label = drop_through_label = gen_label_rtx (); ! 5492: do_jump (TREE_OPERAND (exp, 0), if_false_label, 0); ! 5493: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 5494: break; ! 5495: ! 5496: case TRUTH_ORIF_EXPR: ! 5497: if (if_true_label == 0) ! 5498: if_true_label = drop_through_label = gen_label_rtx (); ! 5499: do_jump (TREE_OPERAND (exp, 0), 0, if_true_label); ! 5500: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 5501: break; ! 5502: ! 5503: case COMPOUND_EXPR: ! 5504: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 5505: free_temp_slots (); ! 5506: emit_queue (); ! 5507: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 5508: break; ! 5509: ! 5510: case COMPONENT_REF: ! 5511: case BIT_FIELD_REF: ! 5512: case ARRAY_REF: ! 5513: { ! 5514: int bitsize, bitpos, unsignedp; ! 5515: enum machine_mode mode; ! 5516: tree type; ! 5517: int volatilep = 0; ! 5518: ! 5519: /* Get description of this reference. We don't actually care ! 5520: about the underlying object here. */ ! 5521: get_inner_reference (exp, &bitsize, &bitpos, &mode, &unsignedp, ! 5522: &volatilep); ! 5523: ! 5524: type = type_for_size (bitsize, unsignedp); ! 5525: if (type != 0 ! 5526: && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))) ! 5527: { ! 5528: do_jump (convert (type, exp), if_false_label, if_true_label); ! 5529: break; ! 5530: } ! 5531: goto normal; ! 5532: } ! 5533: ! 5534: case COND_EXPR: ! 5535: /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases. */ ! 5536: if (integer_onep (TREE_OPERAND (exp, 1)) ! 5537: && integer_zerop (TREE_OPERAND (exp, 2))) ! 5538: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 5539: ! 5540: else if (integer_zerop (TREE_OPERAND (exp, 1)) ! 5541: && integer_onep (TREE_OPERAND (exp, 2))) ! 5542: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 5543: ! 5544: else ! 5545: { ! 5546: register rtx label1 = gen_label_rtx (); ! 5547: drop_through_label = gen_label_rtx (); ! 5548: do_jump (TREE_OPERAND (exp, 0), label1, 0); ! 5549: /* Now the THEN-expression. */ ! 5550: do_jump (TREE_OPERAND (exp, 1), ! 5551: if_false_label ? if_false_label : drop_through_label, ! 5552: if_true_label ? if_true_label : drop_through_label); ! 5553: emit_label (label1); ! 5554: /* Now the ELSE-expression. */ ! 5555: do_jump (TREE_OPERAND (exp, 2), ! 5556: if_false_label ? if_false_label : drop_through_label, ! 5557: if_true_label ? if_true_label : drop_through_label); ! 5558: } ! 5559: break; ! 5560: ! 5561: case EQ_EXPR: ! 5562: if (integer_zerop (TREE_OPERAND (exp, 1))) ! 5563: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 5564: else if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5565: == MODE_INT) ! 5566: && ! 5567: !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5568: do_jump_by_parts_equality (exp, if_false_label, if_true_label); ! 5569: else ! 5570: comparison = compare (exp, EQ, EQ); ! 5571: break; ! 5572: ! 5573: case NE_EXPR: ! 5574: if (integer_zerop (TREE_OPERAND (exp, 1))) ! 5575: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 5576: else if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5577: == MODE_INT) ! 5578: && ! 5579: !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5580: do_jump_by_parts_equality (exp, if_true_label, if_false_label); ! 5581: else ! 5582: comparison = compare (exp, NE, NE); ! 5583: break; ! 5584: ! 5585: case LT_EXPR: ! 5586: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5587: == MODE_INT) ! 5588: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5589: do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label); ! 5590: else ! 5591: comparison = compare (exp, LT, LTU); ! 5592: break; ! 5593: ! 5594: case LE_EXPR: ! 5595: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5596: == MODE_INT) ! 5597: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5598: do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label); ! 5599: else ! 5600: comparison = compare (exp, LE, LEU); ! 5601: break; ! 5602: ! 5603: case GT_EXPR: ! 5604: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5605: == MODE_INT) ! 5606: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5607: do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label); ! 5608: else ! 5609: comparison = compare (exp, GT, GTU); ! 5610: break; ! 5611: ! 5612: case GE_EXPR: ! 5613: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5614: == MODE_INT) ! 5615: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5616: do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label); ! 5617: else ! 5618: comparison = compare (exp, GE, GEU); ! 5619: break; ! 5620: ! 5621: default: ! 5622: normal: ! 5623: temp = expand_expr (exp, 0, VOIDmode, 0); ! 5624: #if 0 ! 5625: /* This is not needed any more and causes poor code since it causes ! 5626: comparisons and tests from non-SI objects to have different code ! 5627: sequences. */ ! 5628: /* Copy to register to avoid generating bad insns by cse ! 5629: from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */ ! 5630: if (!cse_not_expected && GET_CODE (temp) == MEM) ! 5631: temp = copy_to_reg (temp); ! 5632: #endif ! 5633: do_pending_stack_adjust (); ! 5634: if (GET_CODE (temp) == CONST_INT) ! 5635: comparison = (temp == const0_rtx ? const0_rtx : const_true_rtx); ! 5636: else if (GET_CODE (temp) == LABEL_REF) ! 5637: comparison = const_true_rtx; ! 5638: else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT ! 5639: && !can_compare_p (GET_MODE (temp))) ! 5640: /* Note swapping the labels gives us not-equal. */ ! 5641: do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label); ! 5642: else if (GET_MODE (temp) != VOIDmode) ! 5643: comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)), ! 5644: NE, 1, GET_MODE (temp), 0, 0); ! 5645: else ! 5646: abort (); ! 5647: } ! 5648: ! 5649: /* Do any postincrements in the expression that was tested. */ ! 5650: emit_queue (); ! 5651: ! 5652: /* If COMPARISON is nonzero here, it is an rtx that can be substituted ! 5653: straight into a conditional jump instruction as the jump condition. ! 5654: Otherwise, all the work has been done already. */ ! 5655: ! 5656: if (comparison == const_true_rtx) ! 5657: { ! 5658: if (if_true_label) ! 5659: emit_jump (if_true_label); ! 5660: } ! 5661: else if (comparison == const0_rtx) ! 5662: { ! 5663: if (if_false_label) ! 5664: emit_jump (if_false_label); ! 5665: } ! 5666: else if (comparison) ! 5667: do_jump_for_compare (comparison, if_false_label, if_true_label); ! 5668: ! 5669: free_temp_slots (); ! 5670: ! 5671: if (drop_through_label) ! 5672: emit_label (drop_through_label); ! 5673: } ! 5674: ! 5675: /* Given a comparison expression EXP for values too wide to be compared ! 5676: with one insn, test the comparison and jump to the appropriate label. ! 5677: The code of EXP is ignored; we always test GT if SWAP is 0, ! 5678: and LT if SWAP is 1. */ ! 5679: ! 5680: static void ! 5681: do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label) ! 5682: tree exp; ! 5683: int swap; ! 5684: rtx if_false_label, if_true_label; ! 5685: { ! 5686: rtx op0 = expand_expr (TREE_OPERAND (exp, swap), 0, VOIDmode, 0); ! 5687: rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), 0, VOIDmode, 0); ! 5688: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 5689: int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); ! 5690: rtx drop_through_label = 0; ! 5691: int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 5692: int i; ! 5693: ! 5694: if (! if_true_label || ! if_false_label) ! 5695: drop_through_label = gen_label_rtx (); ! 5696: if (! if_true_label) ! 5697: if_true_label = drop_through_label; ! 5698: if (! if_false_label) ! 5699: if_false_label = drop_through_label; ! 5700: ! 5701: /* Compare a word at a time, high order first. */ ! 5702: for (i = 0; i < nwords; i++) ! 5703: { ! 5704: rtx comp; ! 5705: rtx op0_word, op1_word; ! 5706: ! 5707: if (WORDS_BIG_ENDIAN) ! 5708: { ! 5709: op0_word = operand_subword_force (op0, i, mode); ! 5710: op1_word = operand_subword_force (op1, i, mode); ! 5711: } ! 5712: else ! 5713: { ! 5714: op0_word = operand_subword_force (op0, nwords - 1 - i, mode); ! 5715: op1_word = operand_subword_force (op1, nwords - 1 - i, mode); ! 5716: } ! 5717: ! 5718: /* All but high-order word must be compared as unsigned. */ ! 5719: comp = compare_from_rtx (op0_word, op1_word, ! 5720: (unsignedp || i > 0) ? GTU : GT, ! 5721: unsignedp, word_mode, 0, 0); ! 5722: if (comp == const_true_rtx) ! 5723: emit_jump (if_true_label); ! 5724: else if (comp != const0_rtx) ! 5725: do_jump_for_compare (comp, 0, if_true_label); ! 5726: ! 5727: /* Consider lower words only if these are equal. */ ! 5728: comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode, ! 5729: 0, 0); ! 5730: if (comp == const_true_rtx) ! 5731: emit_jump (if_false_label); ! 5732: else if (comp != const0_rtx) ! 5733: do_jump_for_compare (comp, 0, if_false_label); ! 5734: } ! 5735: ! 5736: if (if_false_label) ! 5737: emit_jump (if_false_label); ! 5738: if (drop_through_label) ! 5739: emit_label (drop_through_label); ! 5740: } ! 5741: ! 5742: /* Given an EQ_EXPR expression EXP for values too wide to be compared ! 5743: with one insn, test the comparison and jump to the appropriate label. */ ! 5744: ! 5745: static void ! 5746: do_jump_by_parts_equality (exp, if_false_label, if_true_label) ! 5747: tree exp; ! 5748: rtx if_false_label, if_true_label; ! 5749: { ! 5750: rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5751: rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 5752: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 5753: int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); ! 5754: int i; ! 5755: rtx drop_through_label = 0; ! 5756: ! 5757: if (! if_false_label) ! 5758: drop_through_label = if_false_label = gen_label_rtx (); ! 5759: ! 5760: for (i = 0; i < nwords; i++) ! 5761: { ! 5762: rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode), ! 5763: operand_subword_force (op1, i, mode), ! 5764: EQ, 0, word_mode, 0, 0); ! 5765: if (comp == const_true_rtx) ! 5766: emit_jump (if_false_label); ! 5767: else if (comp != const0_rtx) ! 5768: do_jump_for_compare (comp, if_false_label, 0); ! 5769: } ! 5770: ! 5771: if (if_true_label) ! 5772: emit_jump (if_true_label); ! 5773: if (drop_through_label) ! 5774: emit_label (drop_through_label); ! 5775: } ! 5776: ! 5777: /* Jump according to whether OP0 is 0. ! 5778: We assume that OP0 has an integer mode that is too wide ! 5779: for the available compare insns. */ ! 5780: ! 5781: static void ! 5782: do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label) ! 5783: rtx op0; ! 5784: rtx if_false_label, if_true_label; ! 5785: { ! 5786: int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD; ! 5787: int i; ! 5788: rtx drop_through_label = 0; ! 5789: ! 5790: if (! if_false_label) ! 5791: drop_through_label = if_false_label = gen_label_rtx (); ! 5792: ! 5793: for (i = 0; i < nwords; i++) ! 5794: { ! 5795: rtx comp = compare_from_rtx (operand_subword_force (op0, i, ! 5796: GET_MODE (op0)), ! 5797: const0_rtx, EQ, 0, word_mode, 0, 0); ! 5798: if (comp == const_true_rtx) ! 5799: emit_jump (if_false_label); ! 5800: else if (comp != const0_rtx) ! 5801: do_jump_for_compare (comp, if_false_label, 0); ! 5802: } ! 5803: ! 5804: if (if_true_label) ! 5805: emit_jump (if_true_label); ! 5806: if (drop_through_label) ! 5807: emit_label (drop_through_label); ! 5808: } ! 5809: ! 5810: /* Given a comparison expression in rtl form, output conditional branches to ! 5811: IF_TRUE_LABEL, IF_FALSE_LABEL, or both. */ ! 5812: ! 5813: static void ! 5814: do_jump_for_compare (comparison, if_false_label, if_true_label) ! 5815: rtx comparison, if_false_label, if_true_label; ! 5816: { ! 5817: if (if_true_label) ! 5818: { ! 5819: if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) ! 5820: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label)); ! 5821: else ! 5822: abort (); ! 5823: ! 5824: if (if_false_label) ! 5825: emit_jump (if_false_label); ! 5826: } ! 5827: else if (if_false_label) ! 5828: { ! 5829: rtx insn; ! 5830: rtx prev = PREV_INSN (get_last_insn ()); ! 5831: rtx branch = 0; ! 5832: ! 5833: /* Output the branch with the opposite condition. Then try to invert ! 5834: what is generated. If more than one insn is a branch, or if the ! 5835: branch is not the last insn written, abort. If we can't invert ! 5836: the branch, emit make a true label, redirect this jump to that, ! 5837: emit a jump to the false label and define the true label. */ ! 5838: ! 5839: if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) ! 5840: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_false_label)); ! 5841: else ! 5842: abort (); ! 5843: ! 5844: /* Here we get the insn before what was just emitted. ! 5845: On some machines, emitting the branch can discard ! 5846: the previous compare insn and emit a replacement. */ ! 5847: if (prev == 0) ! 5848: /* If there's only one preceding insn... */ ! 5849: insn = get_insns (); ! 5850: else ! 5851: insn = NEXT_INSN (prev); ! 5852: ! 5853: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) ! 5854: if (GET_CODE (insn) == JUMP_INSN) ! 5855: { ! 5856: if (branch) ! 5857: abort (); ! 5858: branch = insn; ! 5859: } ! 5860: ! 5861: if (branch != get_last_insn ()) ! 5862: abort (); ! 5863: ! 5864: if (! invert_jump (branch, if_false_label)) ! 5865: { ! 5866: if_true_label = gen_label_rtx (); ! 5867: redirect_jump (branch, if_true_label); ! 5868: emit_jump (if_false_label); ! 5869: emit_label (if_true_label); ! 5870: } ! 5871: } ! 5872: } ! 5873: ! 5874: /* Generate code for a comparison expression EXP ! 5875: (including code to compute the values to be compared) ! 5876: and set (CC0) according to the result. ! 5877: SIGNED_CODE should be the rtx operation for this comparison for ! 5878: signed data; UNSIGNED_CODE, likewise for use if data is unsigned. ! 5879: ! 5880: We force a stack adjustment unless there are currently ! 5881: things pushed on the stack that aren't yet used. */ ! 5882: ! 5883: static rtx ! 5884: compare (exp, signed_code, unsigned_code) ! 5885: register tree exp; ! 5886: enum rtx_code signed_code, unsigned_code; ! 5887: { ! 5888: register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5889: register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 5890: register tree type = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 5891: register enum machine_mode mode = TYPE_MODE (type); ! 5892: int unsignedp = TREE_UNSIGNED (type); ! 5893: enum rtx_code code = unsignedp ? unsigned_code : signed_code; ! 5894: ! 5895: return compare_from_rtx (op0, op1, code, unsignedp, mode, ! 5896: ((mode == BLKmode) ! 5897: ? expr_size (TREE_OPERAND (exp, 0)) : 0), ! 5898: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 5899: } ! 5900: ! 5901: /* Like compare but expects the values to compare as two rtx's. ! 5902: The decision as to signed or unsigned comparison must be made by the caller. ! 5903: ! 5904: If MODE is BLKmode, SIZE is an RTX giving the size of the objects being ! 5905: compared. ! 5906: ! 5907: If ALIGN is non-zero, it is the alignment of this type; if zero, the ! 5908: size of MODE should be used. */ ! 5909: ! 5910: rtx ! 5911: compare_from_rtx (op0, op1, code, unsignedp, mode, size, align) ! 5912: register rtx op0, op1; ! 5913: enum rtx_code code; ! 5914: int unsignedp; ! 5915: enum machine_mode mode; ! 5916: rtx size; ! 5917: int align; ! 5918: { ! 5919: /* If one operand is constant, make it the second one. */ ! 5920: ! 5921: if (GET_CODE (op0) == CONST_INT || GET_CODE (op0) == CONST_DOUBLE) ! 5922: { ! 5923: rtx tem = op0; ! 5924: op0 = op1; ! 5925: op1 = tem; ! 5926: code = swap_condition (code); ! 5927: } ! 5928: ! 5929: if (flag_force_mem) ! 5930: { ! 5931: op0 = force_not_mem (op0); ! 5932: op1 = force_not_mem (op1); ! 5933: } ! 5934: ! 5935: do_pending_stack_adjust (); ! 5936: ! 5937: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! 5938: return simplify_relational_operation (code, mode, op0, op1); ! 5939: ! 5940: /* If this is a signed equality comparison, we can do it as an ! 5941: unsigned comparison since zero-extension is cheaper than sign ! 5942: extension and comparisons with zero are done as unsigned. If we ! 5943: are comparing against a constant, we must convert it to what it ! 5944: would look like unsigned. */ ! 5945: if ((code == EQ || code == NE) && ! unsignedp ! 5946: && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT) ! 5947: { ! 5948: if (GET_CODE (op1) == CONST_INT ! 5949: && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) ! 5950: op1 = gen_rtx (CONST_INT, VOIDmode, ! 5951: INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); ! 5952: unsignedp = 1; ! 5953: } ! 5954: ! 5955: emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align); ! 5956: ! 5957: return gen_rtx (code, VOIDmode, cc0_rtx, const0_rtx); ! 5958: } ! 5959: ! 5960: /* Generate code to calculate EXP using a store-flag instruction ! 5961: and return an rtx for the result. ! 5962: If TARGET is nonzero, store the result there if convenient. ! 5963: ! 5964: If ONLY_CHEAP is non-zero, only do this if it is likely to be very ! 5965: cheap. ! 5966: ! 5967: Return zero if there is no suitable set-flag instruction ! 5968: available on this machine. ! 5969: ! 5970: Once expand_expr has been called on the arguments of the comparison, ! 5971: we are committed to doing the store flag, since it is not safe to ! 5972: re-evaluate the expression. We emit the store-flag insn by calling ! 5973: emit_store_flag, but only expand the arguments if we have a reason ! 5974: to believe that emit_store_flag will be successful. If we think that ! 5975: it will, but it isn't, we have to simulate the store-flag with a ! 5976: set/jump/set sequence. */ ! 5977: ! 5978: static rtx ! 5979: do_store_flag (exp, target, mode, only_cheap) ! 5980: tree exp; ! 5981: rtx target; ! 5982: enum machine_mode mode; ! 5983: int only_cheap; ! 5984: { ! 5985: enum rtx_code code; ! 5986: tree arg0 = TREE_OPERAND (exp, 0); ! 5987: tree arg1 = TREE_OPERAND (exp, 1); ! 5988: tree tem; ! 5989: tree type = TREE_TYPE (arg0); ! 5990: enum machine_mode operand_mode = TYPE_MODE (type); ! 5991: int unsignedp = TREE_UNSIGNED (type); ! 5992: rtx op0, op1; ! 5993: enum insn_code icode; ! 5994: rtx subtarget = target; ! 5995: rtx result, label, pattern, jump_pat; ! 5996: ! 5997: /* We won't bother with BLKmode store-flag operations because it would mean ! 5998: passing a lot of information to emit_store_flag. */ ! 5999: if (operand_mode == BLKmode) ! 6000: return 0; ! 6001: ! 6002: while (TREE_CODE (arg0) == NON_LVALUE_EXPR) ! 6003: arg0 = TREE_OPERAND (arg0, 0); ! 6004: ! 6005: while (TREE_CODE (arg1) == NON_LVALUE_EXPR) ! 6006: arg1 = TREE_OPERAND (arg1, 0); ! 6007: ! 6008: /* Put a constant second. */ ! 6009: if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST) ! 6010: { ! 6011: tem = arg0; arg0 = arg1; arg1 = tem; ! 6012: } ! 6013: ! 6014: /* Get the rtx comparison code to use. We know that EXP is a comparison ! 6015: operation of some type. Some comparisons against 1 and -1 can be ! 6016: converted to comparisons with zero. Do so here so that the tests ! 6017: below will be aware that we have a comparison with zero. */ ! 6018: ! 6019: switch (TREE_CODE (exp)) ! 6020: { ! 6021: case EQ_EXPR: ! 6022: code = EQ; ! 6023: break; ! 6024: case NE_EXPR: ! 6025: code = NE; ! 6026: break; ! 6027: case LT_EXPR: ! 6028: if (integer_onep (arg1)) ! 6029: arg1 = integer_zero_node, code = unsignedp ? LEU : LE; ! 6030: else ! 6031: code = unsignedp ? LTU : LT; ! 6032: break; ! 6033: case LE_EXPR: ! 6034: if (integer_all_onesp (arg1)) ! 6035: arg1 = integer_zero_node, code = unsignedp ? LTU : LT; ! 6036: else ! 6037: code = unsignedp ? LEU : LE; ! 6038: break; ! 6039: case GT_EXPR: ! 6040: if (integer_all_onesp (arg1)) ! 6041: arg1 = integer_zero_node, code = unsignedp ? GEU : GE; ! 6042: else ! 6043: code = unsignedp ? GTU : GT; ! 6044: break; ! 6045: case GE_EXPR: ! 6046: if (integer_onep (arg1)) ! 6047: arg1 = integer_zero_node, code = unsignedp ? GTU : GT; ! 6048: else ! 6049: code = unsignedp ? GEU : GE; ! 6050: break; ! 6051: default: ! 6052: abort (); ! 6053: } ! 6054: ! 6055: /* If this is an equality or inequality test of a single bit, we can ! 6056: do this by shifting the bit being tested to the low-order bit and ! 6057: masking the result with the constant 1. If the condition was EQ, ! 6058: we xor it with 1. This does not require an scc insn and is faster ! 6059: than an scc insn even if we have it. */ ! 6060: ! 6061: if ((code == NE || code == EQ) ! 6062: && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) ! 6063: && integer_pow2p (TREE_OPERAND (arg0, 1)) ! 6064: && TYPE_PRECISION (type) <= HOST_BITS_PER_INT) ! 6065: { ! 6066: int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1), ! 6067: 0, VOIDmode, 0))); ! 6068: ! 6069: if (subtarget == 0 || GET_CODE (subtarget) != REG ! 6070: || GET_MODE (subtarget) != operand_mode ! 6071: || ! safe_from_p (subtarget, TREE_OPERAND (arg0, 0))) ! 6072: subtarget = 0; ! 6073: ! 6074: op0 = expand_expr (TREE_OPERAND (arg0, 0), subtarget, VOIDmode, 0); ! 6075: ! 6076: if (bitnum != 0) ! 6077: op0 = expand_shift (RSHIFT_EXPR, GET_MODE (op0), op0, ! 6078: size_int (bitnum), target, 1); ! 6079: ! 6080: if (GET_MODE (op0) != mode) ! 6081: op0 = convert_to_mode (mode, op0, 1); ! 6082: ! 6083: if (bitnum != TYPE_PRECISION (type) - 1) ! 6084: op0 = expand_and (op0, const1_rtx, target); ! 6085: ! 6086: if (code == EQ) ! 6087: op0 = expand_binop (mode, xor_optab, op0, const1_rtx, target, 0, ! 6088: OPTAB_LIB_WIDEN); ! 6089: ! 6090: return op0; ! 6091: } ! 6092: ! 6093: /* Now see if we are likely to be able to do this. Return if not. */ ! 6094: if (! can_compare_p (operand_mode)) ! 6095: return 0; ! 6096: icode = setcc_gen_code[(int) code]; ! 6097: if (icode == CODE_FOR_nothing ! 6098: || (only_cheap && insn_operand_mode[(int) icode][0] != mode)) ! 6099: { ! 6100: /* We can only do this if it is one of the special cases that ! 6101: can be handled without an scc insn. */ ! 6102: if ((code == LT && integer_zerop (arg1)) ! 6103: || (! only_cheap && code == GE && integer_zerop (arg1))) ! 6104: ; ! 6105: else if (BRANCH_COST >= 0 ! 6106: && ! only_cheap && (code == NE || code == EQ) ! 6107: && TREE_CODE (type) != REAL_TYPE ! 6108: && ((abs_optab->handlers[(int) operand_mode].insn_code ! 6109: != CODE_FOR_nothing) ! 6110: || (ffs_optab->handlers[(int) operand_mode].insn_code ! 6111: != CODE_FOR_nothing))) ! 6112: ; ! 6113: else ! 6114: return 0; ! 6115: } ! 6116: ! 6117: preexpand_calls (exp); ! 6118: if (subtarget == 0 || GET_CODE (subtarget) != REG ! 6119: || GET_MODE (subtarget) != operand_mode ! 6120: || ! safe_from_p (subtarget, arg1)) ! 6121: subtarget = 0; ! 6122: ! 6123: op0 = expand_expr (arg0, subtarget, VOIDmode, 0); ! 6124: op1 = expand_expr (arg1, 0, VOIDmode, 0); ! 6125: ! 6126: if (target == 0) ! 6127: target = gen_reg_rtx (mode); ! 6128: ! 6129: result = emit_store_flag (target, code, op0, op1, operand_mode, ! 6130: unsignedp, 1); ! 6131: ! 6132: if (result) ! 6133: return result; ! 6134: ! 6135: /* If this failed, we have to do this with set/compare/jump/set code. */ ! 6136: if (target == 0 || GET_CODE (target) != REG ! 6137: || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1)) ! 6138: target = gen_reg_rtx (GET_MODE (target)); ! 6139: ! 6140: emit_move_insn (target, const1_rtx); ! 6141: result = compare_from_rtx (op0, op1, code, unsignedp, operand_mode, 0, 0); ! 6142: if (GET_CODE (result) == CONST_INT) ! 6143: return result == const0_rtx ? const0_rtx : const1_rtx; ! 6144: ! 6145: label = gen_label_rtx (); ! 6146: if (bcc_gen_fctn[(int) code] == 0) ! 6147: abort (); ! 6148: ! 6149: emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label)); ! 6150: emit_move_insn (target, const0_rtx); ! 6151: emit_label (label); ! 6152: ! 6153: return target; ! 6154: } ! 6155: ! 6156: /* Generate a tablejump instruction (used for switch statements). */ ! 6157: ! 6158: #ifdef HAVE_tablejump ! 6159: ! 6160: /* INDEX is the value being switched on, with the lowest value ! 6161: in the table already subtracted. ! 6162: RANGE is the length of the jump table. ! 6163: TABLE_LABEL is a CODE_LABEL rtx for the table itself. ! 6164: ! 6165: DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the ! 6166: index value is out of range. */ ! 6167: ! 6168: void ! 6169: do_tablejump (index, range, table_label, default_label) ! 6170: rtx index, range, table_label, default_label; ! 6171: { ! 6172: register rtx temp, vector; ! 6173: ! 6174: emit_cmp_insn (range, index, LTU, 0, GET_MODE (index), 0, 0); ! 6175: emit_jump_insn (gen_bltu (default_label)); ! 6176: /* If flag_force_addr were to affect this address ! 6177: it could interfere with the tricky assumptions made ! 6178: about addresses that contain label-refs, ! 6179: which may be valid only very near the tablejump itself. */ ! 6180: /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the ! 6181: GET_MODE_SIZE, because this indicates how large insns are. The other ! 6182: uses should all be Pmode, because they are addresses. This code ! 6183: could fail if addresses and insns are not the same size. */ ! 6184: index = memory_address_noforce ! 6185: (CASE_VECTOR_MODE, ! 6186: gen_rtx (PLUS, Pmode, ! 6187: gen_rtx (MULT, Pmode, index, ! 6188: gen_rtx (CONST_INT, VOIDmode, ! 6189: GET_MODE_SIZE (CASE_VECTOR_MODE))), ! 6190: gen_rtx (LABEL_REF, Pmode, table_label))); ! 6191: temp = gen_reg_rtx (CASE_VECTOR_MODE); ! 6192: vector = gen_rtx (MEM, CASE_VECTOR_MODE, index); ! 6193: RTX_UNCHANGING_P (vector) = 1; ! 6194: convert_move (temp, vector, 0); ! 6195: ! 6196: emit_jump_insn (gen_tablejump (temp, table_label)); ! 6197: ! 6198: #ifndef CASE_VECTOR_PC_RELATIVE ! 6199: /* If we are generating PIC code or if the table is PC-relative, the ! 6200: table and JUMP_INSN must be adjacent, so don't output a BARRIER. */ ! 6201: if (! flag_pic) ! 6202: emit_barrier (); ! 6203: #endif ! 6204: } ! 6205: ! 6206: #endif /* HAVE_tablejump */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.