|
|
1.1 root 1: /* Convert tree expression to rtl instructions, for GNU compiler. 1.1.1.2 ! root 2: Copyright (C) 1988 Free Software Foundation, Inc. 1.1 root 3: 4: This file is part of GNU CC. 5: 6: GNU CC is distributed in the hope that it will be useful, 7: but WITHOUT ANY WARRANTY. No author or distributor 8: accepts responsibility to anyone for the consequences of using it 9: or for whether it serves any particular purpose or works at all, 10: unless he says so in writing. Refer to the GNU CC General Public 11: License for full details. 12: 13: Everyone is granted permission to copy, modify and redistribute 14: GNU CC, but only under the conditions described in the 15: GNU CC General Public License. A copy of this license is 16: supposed to have been given to you along with GNU CC so you 17: can know your rights and responsibilities. It should be in a 18: file named COPYING. Among other things, the copyright notice 19: and this notice must be preserved on all copies. */ 20: 21: 22: #include "config.h" 23: #include "rtl.h" 24: #include "tree.h" 1.1.1.2 ! root 25: #include "flags.h" 1.1 root 26: #include "insn-flags.h" 27: #include "insn-codes.h" 28: #include "expr.h" 1.1.1.2 ! root 29: #include "insn-config.h" ! 30: #include "recog.h" ! 31: #include "varargs.h" ! 32: ! 33: /* Decide whether a function's arguments should be processed ! 34: from first to last or from last to first. */ ! 35: ! 36: #ifdef STACK_GROWS_DOWNWARD ! 37: #ifdef PUSH_ROUNDING ! 38: #define PUSH_ARGS_REVERSED /* If it's last to first */ ! 39: #endif ! 40: #endif ! 41: ! 42: /* Like STACK_BOUNDARY but in units of bytes, not bits. */ ! 43: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT) 1.1 root 44: 45: /* If this is nonzero, we do not bother generating VOLATILE 46: around volatile memory references, and we are willing to 47: output indirect addresses. If cse is to follow, we reject 48: indirect addresses so a useful potential cse is generated; 49: if it is used only once, instruction combination will produce 50: the same indirect address eventually. */ 51: int cse_not_expected; 52: 53: /* Nonzero to generate code for all the subroutines within an 54: expression before generating the upper levels of the expression. 55: Nowadays this is never zero. */ 56: int do_preexpand_calls = 1; 57: 58: /* Number of units that we should eventually pop off the stack. 59: These are the arguments to function calls that have already returned. */ 60: int pending_stack_adjust; 61: 62: /* Total size of arguments already pushed for function calls that 63: have not happened yet. Also counts 1 for each level of conditional 64: expression that we are inside. When this is nonzero, 65: args passed to function calls must be popped right away 66: to ensure contiguity of argument lists for future calls. */ 1.1.1.2 ! root 67: static int current_args_size; 1.1 root 68: 1.1.1.2 ! root 69: /* Nonzero means current function may call alloca. */ ! 70: int may_call_alloca; ! 71: ! 72: rtx store_expr (); ! 73: static void store_constructor (); ! 74: static rtx store_field (); 1.1 root 75: static rtx expand_call (); 1.1.1.2 ! root 76: static void emit_call_1 (); ! 77: static rtx prepare_call_address (); ! 78: static rtx expand_builtin (); 1.1 root 79: static rtx compare (); 1.1.1.2 ! root 80: static rtx compare_constants (); 1.1 root 81: static rtx compare1 (); 82: static rtx do_store_flag (); 83: static void preexpand_calls (); 1.1.1.2 ! root 84: static rtx expand_increment (); ! 85: static void move_by_pieces_1 (); ! 86: static void init_queue (); ! 87: ! 88: void do_pending_stack_adjust (); 1.1 root 89: 90: /* MOVE_RATIO is the number of move instructions that is better than 91: a block move. */ 92: 93: #if defined (HAVE_movstrhi) || defined (HAVE_movstrsi) 94: #define MOVE_RATIO 2 95: #else 96: #define MOVE_RATIO 6 97: #endif 98: 99: /* Table indexed by tree code giving 1 if the code is for a 100: comparison operation, or anything that is most easily 101: computed with a conditional branch. 102: 103: We include tree.def to give it the proper length. 104: The contents thus created are irrelevant. 105: The real contents are initialized in init_comparisons. */ 106: 1.1.1.2 ! root 107: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) 0, 1.1 root 108: 109: static char comparison_code[] = { 110: #include "tree.def" 111: }; 112: #undef DEFTREECODE 113: 1.1.1.2 ! root 114: /* This is run once per compilation. */ ! 115: ! 116: void 1.1 root 117: init_comparisons () 118: { 119: comparison_code[(int) EQ_EXPR] = 1; 120: comparison_code[(int) NE_EXPR] = 1; 121: comparison_code[(int) LT_EXPR] = 1; 122: comparison_code[(int) GT_EXPR] = 1; 123: comparison_code[(int) LE_EXPR] = 1; 124: comparison_code[(int) GE_EXPR] = 1; 125: } 1.1.1.2 ! root 126: ! 127: /* This is run at the start of compiling a function. */ ! 128: ! 129: void ! 130: init_expr () ! 131: { ! 132: init_queue (); ! 133: may_call_alloca = 0; ! 134: } 1.1 root 135: 136: /* Manage the queue of increment instructions to be output 137: for POSTINCREMENT_EXPR expressions, etc. */ 138: 139: static rtx pending_chain; 140: 141: /* Queue up to increment (or change) VAR later. BODY says how: 142: BODY should be the same thing you would pass to emit_insn 143: to increment right away. It will go to emit_insn later on. 144: 145: The value is a QUEUED expression to be used in place of VAR 1.1.1.2 ! root 146: where you want to guarantee the pre-incrementation value of VAR. */ 1.1 root 147: 148: static rtx 149: enqueue_insn (var, body) 150: rtx var, body; 151: { 152: pending_chain = gen_rtx (QUEUED, GET_MODE (var), 153: var, 0, 0, body, pending_chain); 154: return pending_chain; 155: } 156: 157: /* Use protect_from_queue to convert a QUEUED expression 158: into something that you can put immediately into an instruction. 159: If the queued incrementation has not happened yet, 160: protect_from_queue returns the variable itself. 161: If the incrementation has happened, protect_from_queue returns a temp 162: that contains a copy of the old value of the variable. 163: 164: Any time an rtx which might possibly be a QUEUED is to be put 165: into an instruction, it must be passed through protect_from_queue first. 166: QUEUED expressions are not meaningful in instructions. 167: 168: Do not pass a value through protect_from_queue and then hold 169: on to it for a while before putting it in an instruction! 170: If the queue is flushed in between, incorrect code will result. */ 171: 172: rtx 173: protect_from_queue (x, modify) 174: register rtx x; 175: int modify; 176: { 177: register RTX_CODE code = GET_CODE (x); 178: if (code != QUEUED) 179: { 180: /* A special hack for read access to (MEM (QUEUED ...)) 181: to facilitate use of autoincrement. 182: Make a copy of the contents of the memory location 183: rather than a copy of the address. */ 184: if (code == MEM && GET_CODE (XEXP (x, 0)) == QUEUED && !modify) 185: { 186: register rtx y = XEXP (x, 0); 187: XEXP (x, 0) = QUEUED_VAR (y); 188: if (QUEUED_INSN (y)) 189: { 190: register rtx temp = gen_reg_rtx (GET_MODE (x)); 191: emit_insn_before (gen_move_insn (temp, x), 192: QUEUED_INSN (y)); 193: return temp; 194: } 195: return x; 196: } 197: /* Otherwise, recursively protect the subexpressions of all 198: the kinds of rtx's that can contain a QUEUED. */ 199: if (code == MEM) 200: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0); 201: else if (code == PLUS || code == MULT) 202: { 203: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0); 204: XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0); 205: } 206: return x; 207: } 208: /* If the increment has not happened, use the variable itself. */ 209: if (QUEUED_INSN (x) == 0) 210: return QUEUED_VAR (x); 211: /* If the increment has happened and a pre-increment copy exists, 212: use that copy. */ 213: if (QUEUED_COPY (x) != 0) 214: return QUEUED_COPY (x); 215: /* The increment has happened but we haven't set up a pre-increment copy. 216: Set one up now, and use it. */ 217: QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x))); 218: emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)), 219: QUEUED_INSN (x)); 220: return QUEUED_COPY (x); 221: } 222: 1.1.1.2 ! root 223: /* Return nonzero if X contains a QUEUED expression: ! 224: if it contains anything that will be altered by a queued increment. */ ! 225: ! 226: static int ! 227: queued_subexp_p (x) ! 228: rtx x; ! 229: { ! 230: register enum rtx_code code = GET_CODE (x); ! 231: switch (code) ! 232: { ! 233: case QUEUED: ! 234: return 1; ! 235: case MEM: ! 236: return queued_subexp_p (XEXP (x, 0)); ! 237: case MULT: ! 238: case PLUS: ! 239: case MINUS: ! 240: return queued_subexp_p (XEXP (x, 0)) ! 241: || queued_subexp_p (XEXP (x, 1)); ! 242: } ! 243: return 0; ! 244: } ! 245: ! 246: /* Perform all the pending incrementations. */ 1.1 root 247: 248: void 249: emit_queue () 250: { 251: register rtx p; 252: while (p = pending_chain) 253: { 254: QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p)); 255: pending_chain = QUEUED_NEXT (p); 256: } 257: } 258: 1.1.1.2 ! root 259: static void 1.1 root 260: init_queue () 261: { 262: if (pending_chain) 263: abort (); 264: } 265: 266: /* Copy data from FROM to TO, where the machine modes are not the same. 267: Both modes may be integer, or both may be floating. 268: UNSIGNEDP should be nonzero if FROM is an unsigned type. 269: This causes zero-extension instead of sign-extension. */ 270: 271: void 272: convert_move (to, from, unsignedp) 273: register rtx to, from; 274: int unsignedp; 275: { 276: enum machine_mode to_mode = GET_MODE (to); 277: enum machine_mode from_mode = GET_MODE (from); 278: int to_real = to_mode == SFmode || to_mode == DFmode; 279: int from_real = from_mode == SFmode || from_mode == DFmode; 280: int extending = (int) to_mode > (int) from_mode; 281: 282: to = protect_from_queue (to, 1); 283: from = protect_from_queue (from, 0); 284: 285: if (to_real != from_real) 286: abort (); 287: 1.1.1.2 ! root 288: if (to_mode == from_mode ! 289: || (from_mode == VOIDmode && CONSTANT_P (from))) 1.1 root 290: { 291: emit_move_insn (to, from); 292: return; 293: } 294: 295: if (to_real) 296: { 297: #ifdef HAVE_extendsfdf2 298: if (HAVE_extendsfdf2 && extending) 299: { 1.1.1.2 ! root 300: emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN); 1.1 root 301: return; 302: } 303: #endif 304: #ifdef HAVE_truncdfsf2 305: if (HAVE_truncdfsf2 && ! extending) 306: { 1.1.1.2 ! root 307: emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN); 1.1 root 308: return; 309: } 310: #endif 311: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, (extending 1.1.1.2 ! root 312: ? "_extendsfdf2" ! 313: : "_truncdfsf2")), ! 314: GET_MODE (to), 1, ! 315: from, (extending ? SFmode : DFmode)); ! 316: emit_move_insn (to, hard_libcall_value (GET_MODE (to))); 1.1 root 317: return; 318: } 319: 1.1.1.2 ! root 320: /* Now both modes are integers. */ ! 321: 1.1 root 322: if (to_mode == DImode) 323: { 324: emit_insn (gen_rtx (CLOBBER, VOIDmode, to)); 325: 326: if (unsignedp) 327: { 328: convert_move (gen_lowpart (SImode, to), from, unsignedp); 329: emit_clr_insn (gen_highpart (SImode, to)); 330: } 1.1.1.2 ! root 331: #ifdef HAVE_slt ! 332: else if (HAVE_slt && insn_operand_mode[(int) CODE_FOR_slt][0] == SImode) 1.1 root 333: { 334: convert_move (gen_lowpart (SImode, to), from, unsignedp); 1.1.1.2 ! root 335: emit_insn (gen_slt (gen_highpart (SImode, to))); 1.1 root 336: } 337: #endif 338: else 339: { 340: register rtx label = gen_label_rtx (); 341: 342: emit_clr_insn (gen_highpart (SImode, to)); 343: convert_move (gen_lowpart (SImode, to), from, unsignedp); 344: emit_cmp_insn (gen_lowpart (SImode, to), 345: gen_rtx (CONST_INT, VOIDmode, 0), 346: 0, 0); 347: emit_jump_insn (gen_bge (label)); 348: expand_unop (SImode, one_cmpl_optab, 349: gen_highpart (SImode, to), gen_highpart (SImode, to), 350: 1); 351: emit_label (label); 352: } 353: return; 354: } 355: 356: if (from_mode == DImode) 357: { 358: convert_move (to, gen_lowpart (SImode, from), 0); 359: return; 360: } 361: 362: /* Now follow all the conversions between integers 363: no more than a word long. */ 364: 1.1.1.2 ! root 365: /* For truncation, usually we can just refer to FROM in a narrower mode. */ ! 366: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode) ! 367: && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode), ! 368: GET_MODE_BITSIZE (from_mode)) ! 369: && ((GET_CODE (from) == MEM ! 370: && ! mode_dependent_address_p (XEXP (from, 0))) ! 371: || GET_CODE (from) == REG)) ! 372: { ! 373: emit_move_insn (to, gen_lowpart (to_mode, from)); ! 374: return; ! 375: } ! 376: 1.1 root 377: if (to_mode == SImode && from_mode == HImode) 378: { 379: if (unsignedp) 380: { 381: #ifdef HAVE_zero_extendhisi2 382: if (HAVE_zero_extendhisi2) 1.1.1.2 ! root 383: emit_unop_insn (CODE_FOR_zero_extendhisi2, to, from, ZERO_EXTEND); 1.1 root 384: else 385: #endif 386: abort (); 387: } 388: else 389: { 390: #ifdef HAVE_extendhisi2 391: if (HAVE_extendhisi2) 1.1.1.2 ! root 392: emit_unop_insn (CODE_FOR_extendhisi2, to, from, SIGN_EXTEND); 1.1 root 393: else 394: #endif 395: abort (); 396: } 397: return; 398: } 399: 400: if (to_mode == SImode && from_mode == QImode) 401: { 402: if (unsignedp) 403: { 404: #ifdef HAVE_zero_extendqisi2 405: if (HAVE_zero_extendqisi2) 406: { 1.1.1.2 ! root 407: emit_unop_insn (CODE_FOR_zero_extendqisi2, to, from, ZERO_EXTEND); 1.1 root 408: return; 409: } 410: #endif 411: #if defined (HAVE_zero_extendqihi2) && defined (HAVE_extendhisi2) 412: if (HAVE_zero_extendqihi2 && HAVE_extendhisi2) 413: { 414: register rtx temp = gen_reg_rtx (HImode); 1.1.1.2 ! root 415: emit_unop_insn (CODE_FOR_zero_extendqihi2, temp, from, ZERO_EXTEND); ! 416: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND); 1.1 root 417: return; 418: } 419: #endif 420: } 421: else 422: { 423: #ifdef HAVE_extendqisi2 424: if (HAVE_extendqisi2) 425: { 1.1.1.2 ! root 426: emit_unop_insn (CODE_FOR_extendqisi2, to, from, SIGN_EXTEND); 1.1 root 427: return; 428: } 429: #endif 430: #if defined (HAVE_extendqihi2) && defined (HAVE_extendhisi2) 431: if (HAVE_extendqihi2 && HAVE_extendhisi2) 432: { 433: register rtx temp = gen_reg_rtx (HImode); 1.1.1.2 ! root 434: emit_unop_insn (CODE_FOR_extendqihi2, temp, from, SIGN_EXTEND); ! 435: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND); 1.1 root 436: return; 437: } 438: #endif 439: } 440: abort (); 441: } 442: 443: if (to_mode == HImode && from_mode == QImode) 444: { 445: if (unsignedp) 446: { 447: #ifdef HAVE_zero_extendqihi2 448: if (HAVE_zero_extendqihi2) 449: { 1.1.1.2 ! root 450: emit_unop_insn (CODE_FOR_zero_extendqihi2, to, from, ZERO_EXTEND); 1.1 root 451: return; 452: } 453: #endif 454: } 455: else 456: { 457: #ifdef HAVE_extendqihi2 458: if (HAVE_extendqihi2) 459: { 1.1.1.2 ! root 460: emit_unop_insn (CODE_FOR_extendqihi2, to, from, SIGN_EXTEND); 1.1 root 461: return; 462: } 463: #endif 464: } 465: abort (); 466: } 467: 468: /* Now we are truncating an integer to a smaller one. 469: If the result is a temporary, we might as well just copy it, 470: since only the low-order part of the result needs to be valid 471: and it is valid with no change. */ 472: 473: if (GET_CODE (to) == REG) 474: { 475: if (GET_CODE (from) == REG) 476: { 477: emit_move_insn (to, gen_lowpart (GET_MODE (to), from)); 478: return; 479: } 1.1.1.2 ! root 480: else if (GET_CODE (from) == SUBREG) ! 481: { ! 482: from = copy_rtx (from); ! 483: /* This is safe since FROM is not more than one word. */ ! 484: PUT_MODE (from, GET_MODE (to)); ! 485: emit_move_insn (to, from); ! 486: return; ! 487: } 1.1 root 488: #ifndef BYTES_BIG_ENDIAN 489: else if (GET_CODE (from) == MEM) 490: { 491: register rtx addr = XEXP (from, 0); 1.1.1.2 ! root 492: if (memory_address_p (GET_MODE (to), addr)) 1.1 root 493: { 494: emit_move_insn (to, gen_rtx (MEM, GET_MODE (to), addr)); 495: return; 496: } 497: } 498: #endif /* not BYTES_BIG_ENDIAN */ 499: } 500: 501: if (from_mode == SImode && to_mode == HImode) 502: { 503: #ifdef HAVE_truncsihi2 504: if (HAVE_truncsihi2) 505: { 1.1.1.2 ! root 506: emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN); 1.1 root 507: return; 508: } 509: #endif 510: abort (); 511: } 512: 513: if (from_mode == SImode && to_mode == QImode) 514: { 515: #ifdef HAVE_truncsiqi2 516: if (HAVE_truncsiqi2) 517: { 1.1.1.2 ! root 518: emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN); 1.1 root 519: return; 520: } 521: #endif 522: abort (); 523: } 524: 525: if (from_mode == HImode && to_mode == QImode) 526: { 527: #ifdef HAVE_trunchiqi2 528: if (HAVE_trunchiqi2) 529: { 1.1.1.2 ! root 530: emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN); 1.1 root 531: return; 532: } 533: #endif 534: abort (); 535: } 1.1.1.2 ! root 536: ! 537: /* Mode combination is not recognized. */ ! 538: abort (); 1.1 root 539: } 540: 541: /* Return an rtx for a value that would result 542: from converting X to mode MODE. 543: Both X and MODE may be floating, or both integer. 544: UNSIGNEDP is nonzero if X is an unsigned value. 545: This can be done by referring to a part of X in place 546: or by copying to a new temporary with conversion. */ 547: 548: rtx 549: convert_to_mode (mode, x, unsignedp) 550: enum machine_mode mode; 551: rtx x; 552: int unsignedp; 553: { 554: register rtx temp; 555: if (mode == GET_MODE (x)) 556: return x; 1.1.1.2 ! root 557: if (integer_mode_p (mode) ! 558: && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x))) 1.1 root 559: return gen_lowpart (mode, x); 560: temp = gen_reg_rtx (mode); 561: convert_move (temp, x, unsignedp); 562: return temp; 563: } 1.1.1.2 ! root 564: ! 565: int ! 566: integer_mode_p (mode) ! 567: enum machine_mode mode; ! 568: { ! 569: return (int) mode > (int) VOIDmode && (int) mode <= (int) TImode; ! 570: } 1.1 root 571: 572: /* Generate several move instructions to copy LEN bytes 1.1.1.2 ! root 573: from block FROM to block TO. (These are MEM rtx's with BLKmode). ! 574: The caller must pass FROM and TO 1.1 root 575: through protect_from_queue before calling. 576: ALIGN (in bytes) is maximum alignment we can assume. */ 577: 578: struct move_by_pieces 579: { 580: rtx to; 1.1.1.2 ! root 581: rtx to_addr; 1.1 root 582: int autinc_to; 583: int explicit_inc_to; 584: rtx from; 1.1.1.2 ! root 585: rtx from_addr; 1.1 root 586: int autinc_from; 587: int explicit_inc_from; 588: int len; 589: int offset; 590: int reverse; 591: }; 592: 593: static void 1.1.1.2 ! root 594: move_by_pieces (to, from, len, align) 1.1 root 595: rtx to, from; 596: int len, align; 597: { 598: struct move_by_pieces data; 1.1.1.2 ! root 599: rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0); 1.1 root 600: 601: data.offset = 0; 1.1.1.2 ! root 602: data.to_addr = to_addr; ! 603: data.from_addr = from_addr; 1.1 root 604: data.to = to; 605: data.from = from; 1.1.1.2 ! root 606: data.autinc_to ! 607: = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC ! 608: || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC); ! 609: data.autinc_from ! 610: = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC ! 611: || GET_CODE (from_addr) == POST_INC ! 612: || GET_CODE (from_addr) == POST_DEC); 1.1 root 613: 614: data.explicit_inc_from = 0; 615: data.explicit_inc_to = 0; 1.1.1.2 ! root 616: data.reverse ! 617: = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC); 1.1 root 618: if (data.reverse) data.offset = len; 619: data.len = len; 620: 621: /* If copying requires more than two move insns, 622: copy addresses to registers (to make displacements shorter) 623: and use post-increment if available. */ 624: if (!(data.autinc_from && data.autinc_to) 625: && move_by_pieces_ninsns (len, align) > 2) 626: { 627: #ifdef HAVE_PRE_DECREMENT 628: if (data.reverse && ! data.autinc_from) 629: { 1.1.1.2 ! root 630: data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len)); 1.1 root 631: data.autinc_from = 1; 632: data.explicit_inc_from = -1; 633: } 634: #endif 635: #ifdef HAVE_POST_INCREMENT 636: if (! data.autinc_from) 637: { 1.1.1.2 ! root 638: data.from_addr = copy_addr_to_reg (from_addr); 1.1 root 639: data.autinc_from = 1; 640: data.explicit_inc_from = 1; 641: } 642: #endif 1.1.1.2 ! root 643: if (!data.autinc_from && CONSTANT_P (from_addr)) ! 644: data.from_addr = copy_addr_to_reg (from_addr); 1.1 root 645: #ifdef HAVE_PRE_DECREMENT 646: if (data.reverse && ! data.autinc_to) 647: { 1.1.1.2 ! root 648: data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len)); 1.1 root 649: data.autinc_to = 1; 650: data.explicit_inc_to = -1; 651: } 652: #endif 653: #ifdef HAVE_POST_INCREMENT 654: if (! data.reverse && ! data.autinc_to) 655: { 1.1.1.2 ! root 656: data.to_addr = copy_addr_to_reg (to_addr); 1.1 root 657: data.autinc_to = 1; 658: data.explicit_inc_to = 1; 659: } 660: #endif 1.1.1.2 ! root 661: if (!data.autinc_to && CONSTANT_P (to_addr)) ! 662: data.to_addr = copy_addr_to_reg (to_addr); 1.1 root 663: } 664: 665: #ifdef STRICT_ALIGNMENT 1.1.1.2 ! root 666: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) 1.1 root 667: align = MOVE_MAX; 668: #else 669: align = MOVE_MAX; 670: #endif 671: 672: #ifdef HAVE_movti 673: if (HAVE_movti && align >= GET_MODE_SIZE (TImode)) 674: move_by_pieces_1 (gen_movti, TImode, &data); 675: #endif 676: #ifdef HAVE_movdi 677: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode)) 678: move_by_pieces_1 (gen_movdi, DImode, &data); 679: #endif 1.1.1.2 ! root 680: #ifdef HAVE_movsi 1.1 root 681: if (align >= GET_MODE_SIZE (SImode)) 682: move_by_pieces_1 (gen_movsi, SImode, &data); 1.1.1.2 ! root 683: #endif ! 684: #ifdef HAVE_movhi ! 685: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode)) 1.1 root 686: move_by_pieces_1 (gen_movhi, HImode, &data); 1.1.1.2 ! root 687: #endif ! 688: #ifdef HAVE_movqi 1.1 root 689: move_by_pieces_1 (gen_movqi, QImode, &data); 1.1.1.2 ! root 690: #else ! 691: movqi instruction required in machine description ! 692: #endif 1.1 root 693: } 694: 695: /* Return number of insns required to move L bytes by pieces. 696: ALIGN (in bytes) is maximum alignment we can assume. */ 697: 1.1.1.2 ! root 698: static int 1.1 root 699: move_by_pieces_ninsns (l, align) 700: unsigned int l; 701: int align; 702: { 703: register int n_insns = 0; 704: 705: #ifdef STRICT_ALIGNMENT 1.1.1.2 ! root 706: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) 1.1 root 707: align = MOVE_MAX; 708: #else 709: align = MOVE_MAX; 710: #endif 711: 712: #ifdef HAVE_movti 713: if (HAVE_movti && align >= GET_MODE_SIZE (TImode)) 714: n_insns += l / GET_MODE_SIZE (TImode), l %= GET_MODE_SIZE (TImode); 715: #endif 716: #ifdef HAVE_movdi 717: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode)) 718: n_insns += l / GET_MODE_SIZE (DImode), l %= GET_MODE_SIZE (DImode); 719: #endif 1.1.1.2 ! root 720: #ifdef HAVE_movsi 1.1 root 721: if (HAVE_movsi && align >= GET_MODE_SIZE (SImode)) 722: n_insns += l / GET_MODE_SIZE (SImode), l %= GET_MODE_SIZE (SImode); 1.1.1.2 ! root 723: #endif ! 724: #ifdef HAVE_movhi 1.1 root 725: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode)) 726: n_insns += l / GET_MODE_SIZE (HImode), l %= GET_MODE_SIZE (HImode); 1.1.1.2 ! root 727: #endif 1.1 root 728: n_insns += l; 729: 730: return n_insns; 731: } 732: 733: /* Subroutine of move_by_pieces. Move as many bytes as appropriate 734: with move instructions for mode MODE. GENFUN is the gen_... function 735: to make a move insn for that mode. DATA has all the other info. */ 736: 1.1.1.2 ! root 737: static void 1.1 root 738: move_by_pieces_1 (genfun, mode, data) 739: rtx (*genfun) (); 740: enum machine_mode mode; 741: struct move_by_pieces *data; 742: { 743: register int size = GET_MODE_SIZE (mode); 744: register rtx to1, from1; 745: 1.1.1.2 ! root 746: #define add_offset(FLAG,X) \ ! 747: (FLAG ? (X) : plus_constant ((X), data->offset)) 1.1 root 748: 749: while (data->len >= size) 750: { 1.1.1.2 ! root 751: if (data->reverse) data->offset -= size; 1.1 root 752: 1.1.1.2 ! root 753: to1 = change_address (data->to, mode, ! 754: add_offset (data->autinc_to, data->to_addr)); ! 755: from1 = change_address (data->from, mode, ! 756: add_offset (data->autinc_from, data->from_addr)); 1.1 root 757: 758: #ifdef HAVE_PRE_DECREMENT 759: if (data->explicit_inc_to < 0) 1.1.1.2 ! root 760: emit_insn (gen_sub2_insn (data->to_addr, 1.1 root 761: gen_rtx (CONST_INT, VOIDmode, size))); 762: if (data->explicit_inc_from < 0) 1.1.1.2 ! root 763: emit_insn (gen_sub2_insn (data->from_addr, 1.1 root 764: gen_rtx (CONST_INT, VOIDmode, size))); 765: #endif 766: 767: emit_insn (genfun (to1, from1)); 768: #ifdef HAVE_POST_INCREMENT 769: if (data->explicit_inc_to > 0) 1.1.1.2 ! root 770: emit_insn (gen_add2_insn (data->to_addr, 1.1 root 771: gen_rtx (CONST_INT, VOIDmode, size))); 772: if (data->explicit_inc_from > 0) 1.1.1.2 ! root 773: emit_insn (gen_add2_insn (data->from_addr, 1.1 root 774: gen_rtx (CONST_INT, VOIDmode, size))); 775: #endif 776: 777: if (! data->reverse) data->offset += size; 1.1.1.2 ! root 778: 1.1 root 779: data->len -= size; 780: } 781: } 782: 783: /* Emit code to move a block Y to a block X. 784: This may be done with string-move instructions, 785: with multiple scalar move instructions, or with a library call. 786: 787: Both X and Y must be MEM rtx's (perhaps inside VOLATILE) 788: with mode BLKmode. 789: SIZE is an rtx that says how long they are. 790: ALIGN is the maximum alignment we can assume they have, 791: measured in bytes. */ 792: 793: static void 794: emit_block_move (x, y, size, align) 795: rtx x, y; 796: rtx size; 797: int align; 798: { 799: if (GET_MODE (x) != BLKmode) 800: abort (); 801: 802: if (GET_MODE (y) != BLKmode) 803: abort (); 804: 805: x = protect_from_queue (x, 1); 806: y = protect_from_queue (y, 0); 807: 1.1.1.2 ! root 808: if (GET_CODE (x) != MEM) 1.1 root 809: abort (); 1.1.1.2 ! root 810: if (GET_CODE (y) != MEM) 1.1 root 811: abort (); 812: if (size == 0) 813: abort (); 814: 815: if (GET_CODE (size) == CONST_INT 816: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) 817: < MOVE_RATIO)) 1.1.1.2 ! root 818: move_by_pieces (x, y, INTVAL (size), align); 1.1 root 819: else 820: { 821: #ifdef HAVE_movstrsi 822: if (HAVE_movstrsi) 823: { 824: emit_insn (gen_movstrsi (x, y, size)); 825: return; 826: } 827: #endif 828: #ifdef HAVE_movstrhi 829: if (HAVE_movstrhi 830: && GET_CODE (size) == CONST_INT 831: && ((unsigned) INTVAL (size) 832: < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1)))) 833: { 834: emit_insn (gen_movstrhi (x, y, size)); 835: return; 836: } 837: #endif 1.1.1.2 ! root 838: ! 839: #ifdef TARGET_MEM_FUNCTIONS ! 840: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), ! 841: VOIDmode, 3, XEXP (x, 0), Pmode, ! 842: XEXP (y, 0), Pmode, ! 843: size, Pmode); ! 844: #else 1.1 root 845: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 1.1.1.2 ! root 846: VOIDmode, 3, XEXP (y, 0), Pmode, ! 847: XEXP (x, 0), Pmode, 1.1 root 848: size, Pmode); 1.1.1.2 ! root 849: #endif ! 850: } ! 851: } ! 852: ! 853: /* Copy all or part of a BLKmode value X into registers starting at REGNO. ! 854: The number of registers to be filled is NREGS. */ ! 855: ! 856: static void ! 857: move_block_to_reg (regno, x, nregs) ! 858: int regno; ! 859: rtx x; ! 860: int nregs; ! 861: { ! 862: int i; ! 863: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx) ! 864: x = force_const_double_mem (x); ! 865: for (i = 0; i < nregs; i++) ! 866: { ! 867: if (GET_CODE (x) == REG) ! 868: emit_move_insn (gen_rtx (REG, SImode, regno + i), ! 869: gen_rtx (SUBREG, SImode, x, i)); ! 870: else if (x == dconst0_rtx) ! 871: emit_move_insn (gen_rtx (REG, SImode, regno + i), ! 872: const0_rtx); ! 873: else ! 874: emit_move_insn (gen_rtx (REG, SImode, regno + i), ! 875: gen_rtx (MEM, SImode, ! 876: plus_constant (XEXP (x, 0), ! 877: i * GET_MODE_SIZE (SImode)))); ! 878: } ! 879: } ! 880: ! 881: /* Copy all or part of a BLKmode value X out of registers starting at REGNO. ! 882: The number of registers to be filled is NREGS. */ ! 883: ! 884: void ! 885: move_block_from_reg (regno, x, nregs) ! 886: int regno; ! 887: rtx x; ! 888: int nregs; ! 889: { ! 890: int i; ! 891: for (i = 0; i < nregs; i++) ! 892: { ! 893: if (GET_CODE (x) == REG) ! 894: emit_move_insn (gen_rtx (SUBREG, SImode, x, i), ! 895: gen_rtx (REG, SImode, regno + i)); ! 896: else ! 897: emit_move_insn (gen_rtx (MEM, SImode, ! 898: plus_constant (XEXP (x, 0), ! 899: i * GET_MODE_SIZE (SImode))), ! 900: gen_rtx (REG, SImode, regno + i)); 1.1 root 901: } 902: } 1.1.1.2 ! root 903: ! 904: /* Mark NREGS consecutive regs, starting at REGNO, as being live now. */ ! 905: ! 906: static void ! 907: use_regs (regno, nregs) ! 908: int regno; ! 909: int nregs; ! 910: { ! 911: int i; ! 912: for (i = 0; i < nregs; i++) ! 913: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, regno + i))); ! 914: } 1.1 root 915: 1.1.1.2 ! root 916: /* Write zeros through the storage of OBJECT. ! 917: If OBJECT has BLKmode, SIZE is its length in bytes. */ ! 918: ! 919: void ! 920: clear_storage (object, size) ! 921: rtx object; ! 922: int size; ! 923: { ! 924: if (GET_MODE (object) == BLKmode) ! 925: { ! 926: #ifdef TARGET_MEM_FUNCTIONS ! 927: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memset"), ! 928: VOIDmode, 3, ! 929: XEXP (object, 0), Pmode, const0_rtx, Pmode, ! 930: gen_rtx (CONST_INT, VOIDmode, size), Pmode); ! 931: #else ! 932: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bzero"), ! 933: VOIDmode, 2, ! 934: XEXP (object, 0), Pmode, ! 935: gen_rtx (CONST_INT, VOIDmode, size), Pmode); ! 936: #endif ! 937: } ! 938: else ! 939: emit_move_insn (object, const0_rtx, 0); ! 940: } ! 941: 1.1 root 942: /* Generate code to copy Y into X. 943: Both Y and X must have the same mode, except that 944: Y can be a constant with VOIDmode. 1.1.1.2 ! root 945: This mode cannot be BLKmode; use emit_block_move for that. 1.1 root 946: 1.1.1.2 ! root 947: Return the last instruction emitted. */ ! 948: ! 949: rtx 1.1 root 950: emit_move_insn (x, y) 951: rtx x, y; 952: { 953: enum machine_mode mode = GET_MODE (x); 954: x = protect_from_queue (x, 1); 955: y = protect_from_queue (y, 0); 956: 1.1.1.2 ! root 957: if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y)) ! 958: y = force_const_mem (mode, y); ! 959: 1.1 root 960: if (mode == BLKmode) 961: abort (); 1.1.1.2 ! root 962: if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 963: return ! 964: emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); ! 965: #if 0 ! 966: /* It turns out you get much better optimization (in cse and flow) ! 967: if you define movdi and movdf instruction patterns ! 968: even if they must turn into multiple assembler instructions. */ 1.1 root 969: else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode)) 970: { 971: register int count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode); 972: register int i; 1.1.1.2 ! root 973: if (GET_CODE (y) == CONST_DOUBLE && y != dconst0_rtx) ! 974: y = force_const_double_mem (y); 1.1 root 975: for (i = 0; i < count; i++) 976: { 977: rtx x1, y1; 978: if (GET_CODE (x) == REG) 979: x1 = gen_rtx (SUBREG, SImode, x, i); 980: else 981: x1 = gen_rtx (MEM, SImode, 982: memory_address (SImode, 983: plus_constant (XEXP (x, 0), 984: i * GET_MODE_SIZE (SImode)))); 985: if (GET_CODE (y) == REG) 986: y1 = gen_rtx (SUBREG, SImode, y, i); 1.1.1.2 ! root 987: else if (y == dconst0_rtx) ! 988: y1 = const0_rtx; 1.1 root 989: else 990: y1 = gen_rtx (MEM, SImode, 991: memory_address (SImode, 992: plus_constant (XEXP (y, 0), 993: i * GET_MODE_SIZE (SImode)))); 994: emit_insn (gen_movsi (protect_from_queue (x1, 1), protect_from_queue (y1, 0))); 995: } 996: } 1.1.1.2 ! root 997: #endif 1.1 root 998: else 999: abort (); 1000: } 1001: 1002: /* Pushing data onto the stack. */ 1003: 1004: /* Push a block of length SIZE (perhaps variable) 1005: and return an rtx to address the beginning of the block. 1006: Note that it is not possible for the value returned to be a QUEUED. */ 1007: 1008: static rtx 1009: push_block (size) 1010: rtx size; 1011: { 1012: register rtx temp; 1.1.1.2 ! root 1013: if (CONSTANT_P (size) || GET_CODE (size) == REG) ! 1014: anti_adjust_stack (size); ! 1015: else ! 1016: anti_adjust_stack (copy_to_mode_reg (Pmode, size)); 1.1 root 1017: 1018: #ifdef STACK_GROWS_DOWNWARD 1.1.1.2 ! root 1019: temp = stack_pointer_rtx; 1.1 root 1020: #else 1021: temp = gen_rtx (PLUS, Pmode, 1.1.1.2 ! root 1022: stack_pointer_rtx, 1.1 root 1023: size); 1024: if (GET_CODE (size) != CONST_INT) 1025: temp = force_operand (temp, 0); 1026: #endif 1027: return memory_address (QImode, temp); 1028: } 1029: 1030: static rtx 1031: gen_push_operand () 1032: { 1033: return gen_rtx ( 1034: #ifdef STACK_GROWS_DOWNWARD 1035: PRE_DEC, 1036: #else 1037: PRE_INC, 1038: #endif 1039: Pmode, 1.1.1.2 ! root 1040: stack_pointer_rtx); 1.1 root 1041: } 1042: 1043: /* Generate code to push X onto the stack, assuming it has mode MODE. 1044: MODE is redundant except when X is a CONST_INT (since they don't 1045: carry mode info). 1046: SIZE is an rtx for the size of data to be copied (in bytes), 1047: needed only if X is BLKmode. 1.1.1.2 ! root 1048: ALIGN (in bytes) is maximum alignment we can assume. ! 1049: ! 1050: If PARTIAL is nonzero, then copy that many of the first words ! 1051: of X into registers starting with REG, and push the rest of X. ! 1052: The amount of space pushed is decreased by PARTIAL words, ! 1053: rounded *down* to a multiple of PARM_BOUNDARY. ! 1054: REG must be a hard register in this case. ! 1055: ! 1056: EXTRA is the amount in bytes of extra space to leave next to this arg. ! 1057: ! 1058: On a machine that lacks real push insns, ARGS_ADDR is the address of ! 1059: the bottom of the argument block for this call. We use indexing off there ! 1060: to store the arg. On machines with push insns, ARGS_ADDR is 0. ! 1061: ! 1062: ARGS_SO_FAR is the size of args previously pushed for this call. */ 1.1 root 1063: 1064: static void 1.1.1.2 ! root 1065: emit_push_insn (x, mode, size, align, partial, reg, extra, args_addr, args_so_far) 1.1 root 1066: register rtx x; 1067: enum machine_mode mode; 1068: rtx size; 1069: int align; 1.1.1.2 ! root 1070: int partial; ! 1071: rtx reg; ! 1072: int extra; ! 1073: rtx args_addr; ! 1074: rtx args_so_far; 1.1 root 1075: { 1076: rtx xinner; 1077: 1078: xinner = x = protect_from_queue (x, 0); 1079: 1.1.1.2 ! root 1080: /* If part should go in registers, copy that part ! 1081: into the appropriate registers. */ ! 1082: if (partial > 0) ! 1083: move_block_to_reg (REGNO (reg), x, partial); ! 1084: ! 1085: #ifdef STACK_GROWS_DOWNWARD ! 1086: if (extra && args_addr == 0) ! 1087: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1088: #endif 1.1 root 1089: 1090: if (mode == BLKmode) 1091: { 1092: register rtx temp; 1.1.1.2 ! root 1093: int used = partial * UNITS_PER_WORD; ! 1094: int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); ! 1095: ! 1096: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT); ! 1097: 1.1 root 1098: if (size == 0) 1099: abort (); 1100: 1.1.1.2 ! root 1101: if (partial != 0) ! 1102: xinner = change_address (xinner, BLKmode, ! 1103: plus_constant (XEXP (xinner, 0), used)); ! 1104: ! 1105: #ifdef PUSH_ROUNDING ! 1106: /* Do it with several push insns if that doesn't take lots of insns ! 1107: and if there is no difficulty with push insns that skip bytes ! 1108: on the stack for alignment purposes. */ ! 1109: if (args_addr == 0 ! 1110: && GET_CODE (size) == CONST_INT ! 1111: && args_addr == 0 ! 1112: && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align) ! 1113: < MOVE_RATIO) ! 1114: && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size)) ! 1115: move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, ! 1116: INTVAL (size) - used, align); 1.1 root 1117: else 1.1.1.2 ! root 1118: #endif /* PUSH_ROUNDING */ 1.1 root 1119: { 1.1.1.2 ! root 1120: /* Otherwise make space on the stack and copy the data ! 1121: to the address of that space. */ ! 1122: ! 1123: /* First deduct part put into registers from the size we need. */ ! 1124: if (partial != 0) ! 1125: { ! 1126: if (GET_CODE (size) == CONST_INT) ! 1127: size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used); ! 1128: else ! 1129: size = expand_binop (GET_MODE (size), sub_optab, size, ! 1130: gen_rtx (CONST_INT, VOIDmode, used), ! 1131: 0, 0, OPTAB_LIB_WIDEN); ! 1132: } ! 1133: ! 1134: /* Get the address of the stack space. */ ! 1135: if (! args_addr) ! 1136: temp = push_block (size); ! 1137: else if (GET_CODE (args_so_far) == CONST_INT) ! 1138: temp = memory_address (BLKmode, ! 1139: plus_constant (args_addr, ! 1140: offset + INTVAL (args_so_far))); ! 1141: else ! 1142: temp = memory_address (BLKmode, ! 1143: plus_constant (gen_rtx (PLUS, Pmode, ! 1144: args_addr, args_so_far), ! 1145: offset)); ! 1146: ! 1147: ! 1148: /* TEMP is the address of the block. Copy the data there. */ ! 1149: if (GET_CODE (size) == CONST_INT ! 1150: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) ! 1151: < MOVE_RATIO)) ! 1152: { ! 1153: move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner, ! 1154: INTVAL (size), align); ! 1155: return; ! 1156: } 1.1 root 1157: #ifdef HAVE_movstrsi 1158: if (HAVE_movstrsi) 1159: { 1160: emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), x, size)); 1161: return; 1162: } 1163: #endif 1164: #ifdef HAVE_movstrhi 1165: if (HAVE_movstrhi 1166: && GET_CODE (size) == CONST_INT 1167: && ((unsigned) INTVAL (size) 1168: < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1)))) 1169: { 1170: emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), 1171: x, size)); 1172: return; 1173: } 1174: #endif 1.1.1.2 ! root 1175: ! 1176: if (reg_mentioned_p (stack_pointer_rtx, temp)) ! 1177: { ! 1178: /* Correct TEMP so it holds what will be a description of ! 1179: the address to copy to, valid after one arg is pushed. */ 1.1 root 1180: #ifdef STACK_GROWS_DOWNWARD 1.1.1.2 ! root 1181: temp = plus_constant (temp, GET_MODE_SIZE (Pmode)); 1.1 root 1182: #else 1.1.1.2 ! root 1183: temp = plus_constant (temp, - GET_MODE_SIZE (Pmode)); 1.1 root 1184: #endif 1.1.1.2 ! root 1185: } ! 1186: ! 1187: /* Make current_args_size nonzero around the library call ! 1188: to force it to pop the bcopy-arguments right away. */ ! 1189: current_args_size += 1; ! 1190: #ifdef TARGET_MEM_FUNCTIONS ! 1191: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), ! 1192: VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode, ! 1193: size, Pmode); ! 1194: #else 1.1 root 1195: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 1.1.1.2 ! root 1196: VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode, 1.1 root 1197: size, Pmode); 1.1.1.2 ! root 1198: #endif ! 1199: current_args_size -= 1; 1.1 root 1200: } 1201: } 1.1.1.2 ! root 1202: else if (partial > 0) 1.1 root 1203: { 1.1.1.2 ! root 1204: int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD; ! 1205: int i; ! 1206: int used = partial * UNITS_PER_WORD; ! 1207: /* # words of start of argument ! 1208: that we must make space for but need not store. */ ! 1209: int skip = partial % (PARM_BOUNDARY / BITS_PER_WORD); ! 1210: int args_offset = INTVAL (args_so_far); ! 1211: ! 1212: /* If we make space by pushing it, we might as well push ! 1213: the real data. Otherwise, we can leave SKIP nonzero ! 1214: and leave the space uninitialized. */ ! 1215: if (args_addr == 0) ! 1216: skip = 0; ! 1217: ! 1218: /* Deduct all the rest of PARTIAL words from SIZE in any case. ! 1219: This is space that we don't even allocate in the stack. */ ! 1220: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT); ! 1221: size -= used / UNITS_PER_WORD; ! 1222: ! 1223: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx) ! 1224: x = force_const_double_mem (x); ! 1225: ! 1226: #ifndef PUSH_ARGS_REVERSED ! 1227: for (i = skip; i < size; i++) ! 1228: #else ! 1229: for (i = size - 1; i >= skip; i--) ! 1230: #endif ! 1231: if (GET_CODE (x) == MEM) ! 1232: emit_push_insn (gen_rtx (MEM, SImode, ! 1233: plus_constant (XEXP (x, 0), ! 1234: i * UNITS_PER_WORD)), ! 1235: SImode, 0, align, 0, 0, 0, args_addr, ! 1236: gen_rtx (CONST_INT, VOIDmode, ! 1237: args_offset + i * UNITS_PER_WORD)); ! 1238: else if (GET_CODE (x) == REG) ! 1239: emit_push_insn (gen_rtx (SUBREG, SImode, x, i), ! 1240: SImode, 0, align, 0, 0, 0, args_addr, ! 1241: gen_rtx (CONST_INT, VOIDmode, ! 1242: args_offset + i * UNITS_PER_WORD)); ! 1243: else if (x == dconst0_rtx) ! 1244: emit_push_insn (const0_rtx, ! 1245: SImode, 0, align, 0, 0, 0, args_addr, ! 1246: gen_rtx (CONST_INT, VOIDmode, ! 1247: args_offset + i * UNITS_PER_WORD)); ! 1248: else ! 1249: abort (); 1.1 root 1250: } 1251: else 1.1.1.2 ! root 1252: { ! 1253: rtx addr; ! 1254: #ifdef PUSH_ROUNDING ! 1255: if (args_addr == 0) ! 1256: addr = gen_push_operand (); ! 1257: else ! 1258: #endif ! 1259: if (GET_CODE (args_so_far) == CONST_INT) ! 1260: addr ! 1261: = memory_address (mode, ! 1262: plus_constant (args_addr, INTVAL (args_so_far))); ! 1263: else ! 1264: addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr, ! 1265: args_so_far)); ! 1266: ! 1267: emit_move_insn (gen_rtx (MEM, mode, addr), x); ! 1268: } ! 1269: ! 1270: #ifndef STACK_GROWS_DOWNWARD ! 1271: if (extra && args_addr == 0) ! 1272: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); ! 1273: #endif 1.1 root 1274: } 1275: 1276: /* Output a library call to function FUN (a SYMBOL_REF rtx) 1.1.1.2 ! root 1277: for a value of mode OUTMODE 1.1 root 1278: with NARGS different arguments, passed as alternating rtx values 1279: and machine_modes to convert them to. 1280: The rtx values should have been passed through protect_from_queue already. */ 1281: 1282: void 1.1.1.2 ! root 1283: emit_library_call (va_alist) ! 1284: va_dcl 1.1 root 1285: { 1.1.1.2 ! root 1286: register va_list p; 1.1 root 1287: register int args_size = 0; 1288: register int argnum; 1.1.1.2 ! root 1289: enum machine_mode outmode; ! 1290: int nargs; ! 1291: rtx fun; ! 1292: rtx orgfun; ! 1293: int inc; ! 1294: int count; ! 1295: rtx *regvec; ! 1296: rtx argblock = 0; ! 1297: CUMULATIVE_ARGS args_so_far; ! 1298: struct arg { rtx value; enum machine_mode mode; }; ! 1299: struct arg *argvec; ! 1300: int old_args_size = current_args_size; ! 1301: ! 1302: va_start (p); ! 1303: orgfun = fun = va_arg (p, rtx); ! 1304: outmode = va_arg (p, enum machine_mode); ! 1305: nargs = va_arg (p, int); ! 1306: ! 1307: regvec = (rtx *) alloca (nargs * sizeof (rtx)); ! 1308: ! 1309: /* Copy all the libcall-arguments out of the varargs data ! 1310: and into a vector ARGVEC. */ ! 1311: argvec = (struct arg *) alloca (nargs * sizeof (struct arg)); ! 1312: for (count = 0; count < nargs; count++) ! 1313: { ! 1314: argvec[count].value = va_arg (p, rtx); ! 1315: argvec[count].mode = va_arg (p, enum machine_mode); ! 1316: } ! 1317: va_end (p); ! 1318: ! 1319: /* If we have no actual push instructions, make space for all the args ! 1320: right now. */ ! 1321: #ifndef PUSH_ROUNDING ! 1322: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0); ! 1323: for (count = 0; count < nargs; count++) ! 1324: { ! 1325: register enum machine_mode mode = argvec[count].mode; ! 1326: register rtx reg; ! 1327: register int partial; ! 1328: ! 1329: reg = FUNCTION_ARG (args_so_far, mode, 0, 1); ! 1330: #ifdef FUNCTION_ARG_PARTIAL_NREGS ! 1331: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1); ! 1332: #else ! 1333: partial = 0; ! 1334: #endif ! 1335: if (reg == 0 || partial != 0) ! 1336: args_size += GET_MODE_SIZE (mode); ! 1337: if (partial != 0) ! 1338: args_size -= partial * GET_MODE_SIZE (SImode); ! 1339: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1); ! 1340: } ! 1341: ! 1342: if (args_size != 0) ! 1343: argblock ! 1344: = push_block (round_push (gen_rtx (CONST_INT, VOIDmode, args_size))); ! 1345: #endif ! 1346: ! 1347: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0); ! 1348: ! 1349: #ifdef PUSH_ARGS_REVERSED ! 1350: inc = -1; ! 1351: argnum = nargs - 1; 1.1 root 1352: #else 1.1.1.2 ! root 1353: inc = 1; ! 1354: argnum = 0; 1.1 root 1355: #endif 1.1.1.2 ! root 1356: args_size = 0; ! 1357: ! 1358: for (count = 0; count < nargs; count++, argnum += inc) 1.1 root 1359: { 1.1.1.2 ! root 1360: register enum machine_mode mode = argvec[argnum].mode; ! 1361: register rtx val = argvec[argnum].value; ! 1362: rtx reg; ! 1363: int partial; ! 1364: int arg_size; ! 1365: 1.1 root 1366: /* Convert the arg value to the mode the library wants. */ 1367: /* ??? It is wrong to do it here; must do it earlier 1368: where we know the signedness of the arg. */ 1369: if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode) 1370: { 1371: val = gen_reg_rtx (mode); 1.1.1.2 ! root 1372: convert_move (val, argvec[argnum].value, 0); 1.1 root 1373: } 1.1.1.2 ! root 1374: reg = FUNCTION_ARG (args_so_far, mode, 0, 1); ! 1375: regvec[argnum] = reg; ! 1376: #ifdef FUNCTION_ARG_PARTIAL_NREGS ! 1377: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1); ! 1378: #else ! 1379: partial = 0; ! 1380: #endif ! 1381: ! 1382: if (reg != 0 && partial == 0) ! 1383: emit_move_insn (reg, val); ! 1384: else ! 1385: emit_push_insn (val, mode, 0, 0, partial, reg, 0, argblock, ! 1386: gen_rtx (CONST_INT, VOIDmode, args_size)); ! 1387: ! 1388: /* Compute size of stack space used by this argument. */ ! 1389: if (reg == 0 || partial != 0) ! 1390: arg_size = GET_MODE_SIZE (mode); ! 1391: else ! 1392: arg_size = 0; ! 1393: if (partial != 0) ! 1394: arg_size ! 1395: -= ((partial * UNITS_PER_WORD) ! 1396: / (PARM_BOUNDARY / BITS_PER_UNIT) ! 1397: * (PARM_BOUNDARY / BITS_PER_UNIT)); ! 1398: ! 1399: args_size += arg_size; ! 1400: current_args_size += arg_size; ! 1401: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1); 1.1 root 1402: } 1403: 1404: emit_queue (); 1.1.1.2 ! root 1405: ! 1406: fun = prepare_call_address (fun, 0); ! 1407: ! 1408: /* Any regs containing parms remain in use through the call. ! 1409: ??? This is not quite correct, since it doesn't indicate ! 1410: that they are in use immediately before the call insn. ! 1411: Currently that doesn't matter since explicitly-used regs ! 1412: won't be used for reloading. But if the reloader becomes smarter, ! 1413: this will have to change somehow. */ ! 1414: for (count = 0; count < nargs; count++) ! 1415: if (regvec[count] != 0) ! 1416: emit_insn (gen_rtx (USE, VOIDmode, regvec[count])); ! 1417: ! 1418: #ifdef STACK_BOUNDARY ! 1419: args_size = (args_size + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES; ! 1420: #endif ! 1421: ! 1422: current_args_size += 1; ! 1423: emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size, ! 1424: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), ! 1425: outmode != VOIDmode ? hard_libcall_value (outmode) : 0, ! 1426: old_args_size); 1.1 root 1427: } 1428: 1429: /* Expand an assignment that stores the value of FROM into TO. 1.1.1.2 ! root 1430: If WANT_VALUE is nonzero, return an rtx for the value of TO. ! 1431: (This may contain a QUEUED rtx.) ! 1432: Otherwise, the returned value is not meaningful. ! 1433: ! 1434: SUGGEST_REG is no longer actually used. ! 1435: It used to mean, copy the value through a register ! 1436: and return that register, if that is possible. ! 1437: But now we do this if WANT_VALUE. ! 1438: ! 1439: If the value stored is a constant, we return the constant. */ 1.1 root 1440: 1441: rtx 1.1.1.2 ! root 1442: expand_assignment (to, from, want_value, suggest_reg) 1.1 root 1443: tree to, from; 1.1.1.2 ! root 1444: int want_value; ! 1445: int suggest_reg; 1.1 root 1446: { 1447: register rtx to_rtx = 0; 1448: 1449: /* Don't crash if the lhs of the assignment was erroneous. */ 1450: 1451: if (TREE_CODE (to) == ERROR_MARK) 1452: return expand_expr (from, 0, VOIDmode, 0); 1453: 1454: /* Assignment of a structure component needs special treatment 1.1.1.2 ! root 1455: if the structure component's rtx is not simply a MEM. ! 1456: Assignment of an array element at a constant index ! 1457: has the same problem. */ ! 1458: ! 1459: if (TREE_CODE (to) == COMPONENT_REF ! 1460: || (TREE_CODE (to) == ARRAY_REF ! 1461: && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST ! 1462: && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST)) 1.1 root 1463: { 1.1.1.2 ! root 1464: register enum machine_mode mode1; ! 1465: int bitsize; 1.1 root 1466: int volstruct = 0; 1.1.1.2 ! root 1467: tree tem = to; ! 1468: int bitpos = 0; ! 1469: int unsignedp; 1.1 root 1470: 1.1.1.2 ! root 1471: if (TREE_CODE (to) == COMPONENT_REF) 1.1 root 1472: { 1473: tree field = TREE_OPERAND (to, 1); 1.1.1.2 ! root 1474: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field); ! 1475: mode1 = DECL_MODE (TREE_OPERAND (to, 1)); ! 1476: unsignedp = TREE_UNSIGNED (field); 1.1 root 1477: } 1.1.1.2 ! root 1478: else 1.1 root 1479: { 1.1.1.2 ! root 1480: mode1 = TYPE_MODE (TREE_TYPE (to)); ! 1481: bitsize = GET_MODE_BITSIZE (mode1); ! 1482: unsignedp = TREE_UNSIGNED (TREE_TYPE (to)); 1.1 root 1483: } 1484: 1.1.1.2 ! root 1485: /* Compute cumulative bit-offset for nested component-refs ! 1486: and array-refs, and find the ultimate containing object. */ 1.1 root 1487: 1.1.1.2 ! root 1488: while (1) 1.1 root 1489: { 1.1.1.2 ! root 1490: if (TREE_CODE (tem) == COMPONENT_REF) ! 1491: { ! 1492: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1)); ! 1493: if (TREE_THIS_VOLATILE (tem)) ! 1494: volstruct = 1; ! 1495: } ! 1496: else if (TREE_CODE (tem) == ARRAY_REF ! 1497: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST ! 1498: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST) ! 1499: { ! 1500: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)) ! 1501: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem))) ! 1502: * TYPE_SIZE_UNIT (TREE_TYPE (tem))); ! 1503: } ! 1504: else ! 1505: break; ! 1506: tem = TREE_OPERAND (tem, 0); 1.1 root 1507: } 1508: 1.1.1.2 ! root 1509: /* If we are going to use store_bit_field and extract_bit_field, ! 1510: make sure to_rtx will be safe for multiple use. */ ! 1511: if (mode1 == BImode && want_value) ! 1512: tem = stabilize_reference (tem); 1.1 root 1513: 1.1.1.2 ! root 1514: to_rtx = expand_expr (tem, 0, VOIDmode, 0); ! 1515: ! 1516: return store_field (to_rtx, bitsize, bitpos, mode1, from, ! 1517: want_value ? TYPE_MODE (TREE_TYPE (to)) : VOIDmode, ! 1518: unsignedp); 1.1 root 1519: } 1520: 1521: /* Ordinary treatment. Expand TO to get a REG or MEM rtx. 1522: Don't re-expand if it was expanded already (in COMPONENT_REF case). */ 1523: 1524: if (to_rtx == 0) 1525: to_rtx = expand_expr (to, 0, VOIDmode, 0); 1526: 1527: /* Compute FROM and store the value in the rtx we got. */ 1528: 1.1.1.2 ! root 1529: return store_expr (from, to_rtx, want_value); 1.1 root 1530: } 1531: 1532: /* Generate code for computing expression EXP, 1.1.1.2 ! root 1533: and storing the value into TARGET. ! 1534: Returns TARGET or an equivalent value. ! 1535: TARGET may contain a QUEUED rtx. 1.1 root 1536: 1.1.1.2 ! root 1537: If SUGGEST_REG is nonzero, copy the value through a register ! 1538: and return that register, if that is possible. ! 1539: ! 1540: If the value stored is a constant, we return the constant. */ ! 1541: ! 1542: rtx ! 1543: store_expr (exp, target, suggest_reg) 1.1 root 1544: register tree exp; 1545: register rtx target; 1.1.1.2 ! root 1546: int suggest_reg; 1.1 root 1547: { 1.1.1.2 ! root 1548: register rtx temp; ! 1549: int dont_return_target = 0; ! 1550: ! 1551: /* Copying a non-constant CONSTRUCTOR needs special treatment. */ ! 1552: ! 1553: if (TREE_CODE (exp) == CONSTRUCTOR && ! TREE_LITERAL (exp)) ! 1554: { ! 1555: store_constructor (exp, target); ! 1556: return target; ! 1557: } ! 1558: ! 1559: if (suggest_reg && GET_CODE (target) == MEM && GET_MODE (target) != BLKmode) ! 1560: /* If target is in memory and caller wants value in a register instead, ! 1561: arrange that. Pass TARGET as target for expand_expr so that, ! 1562: if EXP is another assignment, SUGGEST_REG will be nonzero for it. ! 1563: We know expand_expr will not use the target in that case. */ ! 1564: { ! 1565: temp = expand_expr (exp, cse_not_expected ? 0 : target, ! 1566: GET_MODE (target), 0); ! 1567: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) ! 1568: temp = copy_to_reg (temp); ! 1569: dont_return_target = 1; ! 1570: } ! 1571: else if (queued_subexp_p (target)) ! 1572: /* If target contains a postincrement, it is not safe ! 1573: to use as the returned value. It would access the wrong ! 1574: place by the time the queued increment gets output. ! 1575: So copy the value through a temporary and use that temp ! 1576: as the result. */ ! 1577: { ! 1578: temp = expand_expr (exp, 0, GET_MODE (target), 0); ! 1579: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) ! 1580: temp = copy_to_reg (temp); ! 1581: dont_return_target = 1; ! 1582: } ! 1583: else ! 1584: { ! 1585: temp = expand_expr (exp, target, GET_MODE (target), 0); ! 1586: /* DO return TARGET if it's a specified hardware register. ! 1587: expand_return relies on this. */ ! 1588: if (!(target && GET_CODE (target) == REG ! 1589: && REGNO (target) < FIRST_PSEUDO_REGISTER) ! 1590: && (CONSTANT_P (temp) || GET_CODE (temp) == CONST_DOUBLE)) ! 1591: dont_return_target = 1; ! 1592: } ! 1593: ! 1594: /* If value was not generated in the target, store it there. */ ! 1595: 1.1 root 1596: if (temp != target && TREE_CODE (exp) != ERROR_MARK) 1597: { 1598: target = protect_from_queue (target, 1); 1599: if (GET_MODE (temp) != GET_MODE (target) 1600: && GET_MODE (temp) != VOIDmode) 1.1.1.2 ! root 1601: { ! 1602: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 1603: if (dont_return_target) ! 1604: temp = convert_to_mode (GET_MODE (target), temp, unsignedp); ! 1605: else ! 1606: convert_move (target, temp, unsignedp); ! 1607: } ! 1608: 1.1 root 1609: else if (GET_MODE (temp) == BLKmode) 1610: emit_block_move (target, temp, expr_size (exp), 1611: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); 1612: else 1613: emit_move_insn (target, temp); 1614: } 1.1.1.2 ! root 1615: if (dont_return_target) ! 1616: return temp; 1.1 root 1617: return target; 1618: } 1619: 1.1.1.2 ! root 1620: /* Store the value of constructor EXP into the rtx TARGET. ! 1621: TARGET is either a REG or a MEM. */ 1.1 root 1622: 1.1.1.2 ! root 1623: static void ! 1624: store_constructor (exp, target) ! 1625: tree exp; ! 1626: rtx target; 1.1 root 1627: { 1.1.1.2 ! root 1628: if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) 1.1 root 1629: { 1.1.1.2 ! root 1630: register tree elt; 1.1 root 1631: 1.1.1.2 ! root 1632: /* If the constructor has fewer fields than the structure, ! 1633: clear the whole structure first. */ 1.1 root 1634: 1.1.1.2 ! root 1635: if (list_length (CONSTRUCTOR_ELTS (exp)) ! 1636: != list_length (TYPE_FIELDS (TREE_TYPE (exp)))) ! 1637: clear_storage (target, int_size_in_bytes (TREE_TYPE (exp))); ! 1638: else ! 1639: /* Inform later passes that the old value is dead. */ ! 1640: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 1641: ! 1642: /* Store each element of the constructor into ! 1643: the corresponding field of TARGET. */ ! 1644: ! 1645: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 1646: { ! 1647: register tree field = TREE_PURPOSE (elt); ! 1648: register enum machine_mode mode; ! 1649: int bitsize; ! 1650: int bitpos; ! 1651: int unsignedp; ! 1652: ! 1653: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field); ! 1654: mode = DECL_MODE (field); ! 1655: unsignedp = TREE_UNSIGNED (field); ! 1656: ! 1657: bitpos = DECL_OFFSET (field); ! 1658: ! 1659: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! 1660: VOIDmode, 0); ! 1661: } ! 1662: } ! 1663: else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) ! 1664: { ! 1665: register tree elt; ! 1666: register int i; ! 1667: tree domain = TYPE_DOMAIN (TREE_TYPE (exp)); ! 1668: int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! 1669: int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); ! 1670: tree elttype = TREE_TYPE (TREE_TYPE (exp)); ! 1671: ! 1672: /* If the constructor has fewer fields than the structure, ! 1673: clear the whole structure first. */ ! 1674: ! 1675: if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1) ! 1676: clear_storage (target, maxelt - minelt + 1); ! 1677: else ! 1678: /* Inform later passes that the old value is dead. */ ! 1679: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 1680: ! 1681: /* Store each element of the constructor into ! 1682: the corresponding element of TARGET, determined ! 1683: by counting the elements. */ ! 1684: for (elt = CONSTRUCTOR_ELTS (exp), i = 0; ! 1685: elt; ! 1686: elt = TREE_CHAIN (elt), i++) ! 1687: { ! 1688: register enum machine_mode mode; ! 1689: int bitsize; ! 1690: int bitpos; ! 1691: int unsignedp; ! 1692: ! 1693: mode = TYPE_MODE (elttype); ! 1694: bitsize = GET_MODE_BITSIZE (mode); ! 1695: unsignedp = TREE_UNSIGNED (elttype); ! 1696: ! 1697: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)) ! 1698: * TYPE_SIZE_UNIT (elttype)); ! 1699: ! 1700: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt), ! 1701: VOIDmode, 0); ! 1702: } ! 1703: } ! 1704: } ! 1705: ! 1706: /* Store the value of EXP (an expression tree) ! 1707: into a subfield of TARGET which has mode MODE and occupies ! 1708: BITSIZE bits, starting BITPOS bits from the start of TARGET. ! 1709: ! 1710: If VALUE_MODE is VOIDmode, return nothing in particular. ! 1711: UNSIGNEDP is not used in this case. ! 1712: ! 1713: Otherwise, return an rtx for the value stored. This rtx ! 1714: has mode VALUE_MODE if that is convenient to do. ! 1715: In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. */ ! 1716: ! 1717: static rtx ! 1718: store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp) ! 1719: rtx target; ! 1720: int bitsize, bitpos; ! 1721: enum machine_mode mode; ! 1722: tree exp; ! 1723: enum machine_mode value_mode; ! 1724: int unsignedp; ! 1725: { ! 1726: /* If the structure is in a register or if the component ! 1727: is a bit field, we cannot use addressing to access it. ! 1728: Use bit-field techniques or SUBREG to store in it. */ ! 1729: ! 1730: if (mode == BImode || GET_CODE (target) == REG ! 1731: || GET_CODE (target) == SUBREG) ! 1732: { ! 1733: store_bit_field (target, bitsize, bitpos, ! 1734: mode, ! 1735: expand_expr (exp, 0, VOIDmode, 0)); ! 1736: if (value_mode != VOIDmode) ! 1737: return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 1738: 0, value_mode, 0); ! 1739: return const0_rtx; ! 1740: } ! 1741: else ! 1742: { ! 1743: rtx addr = XEXP (target, 0); ! 1744: rtx to_rtx; ! 1745: ! 1746: /* If a value is wanted, it must be the lhs; ! 1747: so make the address stable for multiple use. */ ! 1748: ! 1749: if (value_mode != VOIDmode && GET_CODE (addr) != REG ! 1750: && ! CONSTANT_ADDRESS_P (addr)) ! 1751: addr = copy_to_reg (addr); ! 1752: ! 1753: /* Now build a reference to just the desired component. */ ! 1754: ! 1755: to_rtx = change_address (target, mode, ! 1756: plus_constant (addr, ! 1757: (bitpos / BITS_PER_UNIT))); ! 1758: to_rtx->in_struct = 1; ! 1759: ! 1760: return store_expr (exp, to_rtx, value_mode != VOIDmode); ! 1761: } ! 1762: } ! 1763: ! 1764: /* Given an rtx VALUE that may contain additions and multiplications, ! 1765: return an equivalent value that just refers to a register or memory. ! 1766: This is done by generating instructions to perform the arithmetic ! 1767: and returning a pseudo-register containing the value. */ ! 1768: ! 1769: rtx ! 1770: force_operand (value, target) ! 1771: rtx value, target; ! 1772: { ! 1773: register optab binoptab = 0; ! 1774: register rtx op2; ! 1775: /* Use subtarget as the target for operand 0 of a binary operation. */ ! 1776: register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); ! 1777: ! 1778: if (GET_CODE (value) == PLUS) ! 1779: binoptab = add_optab; ! 1780: else if (GET_CODE (value) == MINUS) ! 1781: binoptab = sub_optab; ! 1782: else if (GET_CODE (value) == MULT) ! 1783: { ! 1784: op2 = XEXP (value, 1); ! 1785: if (!CONSTANT_P (op2) ! 1786: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 1787: subtarget = 0; ! 1788: return expand_mult (GET_MODE (value), ! 1789: force_operand (XEXP (value, 0), subtarget), ! 1790: force_operand (op2, 0), ! 1791: target, 0); ! 1792: } ! 1793: ! 1794: if (binoptab) ! 1795: { ! 1796: op2 = XEXP (value, 1); ! 1797: if (!CONSTANT_P (op2) ! 1798: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 1799: subtarget = 0; ! 1800: if (binoptab == sub_optab ! 1801: && GET_CODE (op2) == CONST_INT && INTVAL (op2) < 0) ! 1802: { ! 1803: binoptab = add_optab; ! 1804: op2 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op2)); ! 1805: } ! 1806: return expand_binop (GET_MODE (value), binoptab, ! 1807: force_operand (XEXP (value, 0), subtarget), ! 1808: force_operand (op2, 0), ! 1809: target, 0, OPTAB_LIB_WIDEN); ! 1810: /* We give UNSIGNEP = 0 to expand_binop ! 1811: because the only operations we are expanding here are signed ones. */ ! 1812: } ! 1813: return value; ! 1814: } ! 1815: ! 1816: /* expand_expr: generate code for computing expression EXP. ! 1817: An rtx for the computed value is returned. ! 1818: ! 1819: The value may be stored in TARGET if TARGET is nonzero. 1.1 root 1820: TARGET is just a suggestion; callers must assume that 1821: the rtx returned may not be the same as TARGET. 1822: 1.1.1.2 ! root 1823: If TARGET is CONST0_RTX, it means that the value will be ignored. ! 1824: 1.1 root 1825: If TMODE is not VOIDmode, it suggests generating the 1826: result in mode TMODE. But this is done only when convenient. 1827: Otherwise, TMODE is ignored and the value generated in its natural mode. 1828: TMODE is just a suggestion; callers must assume that 1829: the rtx returned may not have mode TMODE. 1830: 1.1.1.2 ! root 1831: If MODIFIER is EXPAND_SUM then when EXP is an addition 1.1 root 1832: we can return an rtx of the form (MULT (REG ...) (CONST_INT ...)) 1833: or a nest of (PLUS ...) and (MINUS ...) where the terms are 1834: products as above, or REG or MEM, or constant. 1.1.1.2 ! root 1835: Ordinarily in such cases we would output mul or add instructions ! 1836: and then return a pseudo reg containing the sum. ! 1837: ! 1838: If MODIFIER is EXPAND_CONST_ADDRESS then it is ok to return ! 1839: a MEM rtx whose address is a constant that isn't a legitimate address. */ 1.1 root 1840: 1841: /* Subroutine of expand_expr: 1842: return the target to use when recursively expanding 1843: the first operand of an arithmetic operation. */ 1844: 1845: static rtx 1846: validate_subtarget (subtarget, otherop) 1847: rtx subtarget; 1848: tree otherop; 1849: { 1850: if (TREE_LITERAL (otherop)) 1851: return subtarget; 1852: if (TREE_CODE (otherop) == VAR_DECL 1853: && DECL_RTL (otherop) != subtarget) 1854: return subtarget; 1855: return 0; 1856: } 1857: 1858: rtx 1.1.1.2 ! root 1859: expand_expr (exp, target, tmode, modifier) 1.1 root 1860: register tree exp; 1861: rtx target; 1862: enum machine_mode tmode; 1.1.1.2 ! root 1863: enum expand_modifier modifier; 1.1 root 1864: { 1865: register rtx op0, op1, temp; 1866: tree type = TREE_TYPE (exp); 1867: register enum machine_mode mode = TYPE_MODE (type); 1868: register enum tree_code code = TREE_CODE (exp); 1.1.1.2 ! root 1869: optab this_optab; 1.1 root 1870: int negate_1; 1871: /* Use subtarget as the target for operand 0 of a binary operation. */ 1872: rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); 1.1.1.2 ! root 1873: rtx original_target = target; ! 1874: int ignore = target == const0_rtx; ! 1875: ! 1876: if (ignore) target = 0, original_target = 0; 1.1 root 1877: 1878: /* If will do cse, generate all results into registers 1879: since 1) that allows cse to find more things 1880: and 2) otherwise cse could produce an insn the machine 1881: cannot support. */ 1882: 1883: if (! cse_not_expected && mode != BLKmode) 1884: target = subtarget; 1885: 1.1.1.2 ! root 1886: /* No sense saving up arithmetic to be done ! 1887: if it's all in the wrong mode to form part of an address. ! 1888: And force_operand won't know whether to sign-extend or zero-extend. */ ! 1889: ! 1890: if (mode != Pmode && modifier == EXPAND_SUM) ! 1891: modifier = (enum expand_modifier) 0; ! 1892: 1.1 root 1893: switch (code) 1894: { 1895: case FUNCTION_DECL: 1896: case VAR_DECL: 1897: case PARM_DECL: 1898: case RESULT_DECL: 1899: if (DECL_RTL (exp) == 0) 1900: abort (); 1901: if (GET_CODE (DECL_RTL (exp)) == SYMBOL_REF) 1902: abort (); 1.1.1.2 ! root 1903: if (GET_CODE (DECL_RTL (exp)) == MEM ! 1904: && modifier != EXPAND_CONST_ADDRESS) ! 1905: { ! 1906: /* DECL_RTL probably contains a constant address. ! 1907: On RISC machines where a constant address isn't valid, ! 1908: make some insns to get that address into a register. */ ! 1909: if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0))) ! 1910: return change_address (DECL_RTL (exp), VOIDmode, ! 1911: copy_rtx (XEXP (DECL_RTL (exp), 0))); ! 1912: } 1.1 root 1913: return DECL_RTL (exp); 1914: 1915: case INTEGER_CST: 1916: return gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (exp)); 1917: 1918: case CONST_DECL: 1919: return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); 1920: 1921: case REAL_CST: 1922: if (TREE_CST_RTL (exp)) 1923: return TREE_CST_RTL (exp); 1924: /* If optimized, generate immediate float 1925: which will be turned into memory float if necessary. */ 1926: if (!cse_not_expected) 1927: return immed_real_const (exp); 1928: output_constant_def (exp); 1929: return TREE_CST_RTL (exp); 1930: 1931: case COMPLEX_CST: 1932: case STRING_CST: 1933: if (TREE_CST_RTL (exp)) 1934: return TREE_CST_RTL (exp); 1935: output_constant_def (exp); 1936: return TREE_CST_RTL (exp); 1937: 1938: case SAVE_EXPR: 1939: if (SAVE_EXPR_RTL (exp) == 0) 1940: { 1941: SAVE_EXPR_RTL (exp) = gen_reg_rtx (mode); 1.1.1.2 ! root 1942: store_expr (TREE_OPERAND (exp, 0), SAVE_EXPR_RTL (exp), 0); 1.1 root 1943: } 1.1.1.2 ! root 1944: /* Don't let the same rtl node appear in two places. */ 1.1 root 1945: return SAVE_EXPR_RTL (exp); 1946: 1.1.1.2 ! root 1947: case RTL_EXPR: ! 1948: emit_insn (RTL_EXPR_SEQUENCE (exp)); ! 1949: return RTL_EXPR_RTL (exp); ! 1950: ! 1951: case CONSTRUCTOR: ! 1952: /* All elts simple constants => refer to a constant in memory. */ ! 1953: if (TREE_STATIC (exp)) ! 1954: /* For aggregate types with non-BLKmode modes, ! 1955: this should ideally construct a CONST_INT. */ ! 1956: return output_constant_def (exp); ! 1957: ! 1958: if (ignore) ! 1959: { ! 1960: tree elt; ! 1961: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 1962: expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); ! 1963: return const0_rtx; ! 1964: } ! 1965: else ! 1966: { ! 1967: if (target == 0) ! 1968: target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), ! 1969: get_structure_value_addr (expr_size (exp))); ! 1970: store_expr (exp, target, 0); ! 1971: return target; ! 1972: } ! 1973: 1.1 root 1974: case INDIRECT_REF: 1975: { 1976: tree exp1 = TREE_OPERAND (exp, 0); 1977: tree exp2; 1978: 1979: /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated 1980: for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR. 1981: This code has the same general effect as simply doing 1982: expand_expr on the save expr, except that the expression PTR 1983: is computed for use as a memory address. This means different 1984: code, suitable for indexing, may be generated. */ 1985: if (TREE_CODE (exp1) == SAVE_EXPR 1986: && SAVE_EXPR_RTL (exp1) == 0 1987: && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK 1988: && TYPE_MODE (TREE_TYPE (exp1)) == Pmode 1989: && TYPE_MODE (TREE_TYPE (exp2)) == Pmode) 1990: { 1.1.1.2 ! root 1991: temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM); 1.1 root 1992: op0 = memory_address (mode, temp); 1993: op0 = copy_all_regs (op0); 1994: SAVE_EXPR_RTL (exp1) = op0; 1995: } 1996: else 1997: { 1.1.1.2 ! root 1998: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, EXPAND_SUM); 1.1 root 1999: op0 = memory_address (mode, op0); 2000: } 2001: } 2002: temp = gen_rtx (MEM, mode, op0); 1.1.1.2 ! root 2003: /* If address was computed by addition, ! 2004: mark this as an element of an aggregate. */ ! 2005: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR ! 2006: || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR ! 2007: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR)) ! 2008: temp->in_struct = 1; ! 2009: temp->volatil = TREE_THIS_VOLATILE (exp) | flag_volatile; ! 2010: temp->unchanging = TREE_READONLY (exp); ! 2011: return temp; ! 2012: ! 2013: case ARRAY_REF: ! 2014: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST ! 2015: || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST) ! 2016: { ! 2017: /* Nonconstant array index or nonconstant element size. ! 2018: Generate the tree for *(&array+index) and expand that, ! 2019: except do it in a language-independent way ! 2020: and don't complain about non-lvalue arrays. ! 2021: `mark_addressable' should already have been called ! 2022: for any array for which this case will be reached. */ ! 2023: ! 2024: tree array_adr = build (ADDR_EXPR, TYPE_POINTER_TO (type), ! 2025: TREE_OPERAND (exp, 0)); ! 2026: tree index = TREE_OPERAND (exp, 1); ! 2027: tree elt; ! 2028: ! 2029: /* Convert the integer argument to a type the same size as a pointer ! 2030: so the multiply won't overflow spuriously. */ ! 2031: if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE) ! 2032: index = convert (type_for_size (POINTER_SIZE, 0), index); ! 2033: ! 2034: /* The array address isn't volatile even if the array is. */ ! 2035: TREE_VOLATILE (array_adr) = 0; ! 2036: ! 2037: elt = build (INDIRECT_REF, type, ! 2038: fold (build (PLUS_EXPR, TYPE_POINTER_TO (type), ! 2039: array_adr, ! 2040: fold (build (MULT_EXPR, ! 2041: TYPE_POINTER_TO (type), ! 2042: index, size_in_bytes (type)))))); ! 2043: ! 2044: return expand_expr (elt, target, tmode, modifier); ! 2045: } ! 2046: /* Treat array-ref with constant index as a component-ref. */ 1.1 root 2047: 2048: case COMPONENT_REF: 2049: { 1.1.1.2 ! root 2050: register enum machine_mode mode1; 1.1 root 2051: int volstruct = 0; 2052: tree dbg1 = TREE_OPERAND (exp, 0); /* For debugging */ 1.1.1.2 ! root 2053: int bitsize; ! 2054: tree tem = exp; ! 2055: int bitpos = 0; ! 2056: int unsignedp; 1.1 root 2057: 1.1.1.2 ! root 2058: if (TREE_CODE (exp) == COMPONENT_REF) 1.1 root 2059: { 2060: tree field = TREE_OPERAND (exp, 1); 1.1.1.2 ! root 2061: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field); ! 2062: mode1 = DECL_MODE (TREE_OPERAND (exp, 1)); ! 2063: unsignedp = TREE_UNSIGNED (field); 1.1 root 2064: } 1.1.1.2 ! root 2065: else 1.1 root 2066: { 1.1.1.2 ! root 2067: mode1 = TYPE_MODE (TREE_TYPE (exp)); ! 2068: bitsize = GET_MODE_BITSIZE (mode1); ! 2069: unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); 1.1 root 2070: } 2071: 1.1.1.2 ! root 2072: /* Compute cumulative bit-offset for nested component-refs ! 2073: and array-refs, and find the ultimate containing object. */ ! 2074: ! 2075: while (1) 1.1 root 2076: { 1.1.1.2 ! root 2077: if (TREE_CODE (tem) == COMPONENT_REF) ! 2078: { ! 2079: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1)); ! 2080: if (TREE_THIS_VOLATILE (tem)) ! 2081: volstruct = 1; ! 2082: } ! 2083: else if (TREE_CODE (tem) == ARRAY_REF ! 2084: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST ! 2085: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST) ! 2086: { ! 2087: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)) ! 2088: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem))) ! 2089: * TYPE_SIZE_UNIT (TREE_TYPE (tem))); ! 2090: } ! 2091: else ! 2092: break; ! 2093: tem = TREE_OPERAND (tem, 0); 1.1 root 2094: } 2095: 1.1.1.2 ! root 2096: op0 = expand_expr (tem, 0, VOIDmode, ! 2097: (modifier == EXPAND_CONST_ADDRESS ! 2098: ? modifier : EXPAND_NORMAL)); 1.1 root 2099: 1.1.1.2 ! root 2100: if (mode1 == BImode || GET_CODE (op0) == REG ! 2101: || GET_CODE (op0) == SUBREG) ! 2102: { ! 2103: return extract_bit_field (op0, bitsize, bitpos, unsignedp, ! 2104: target, mode, tmode); ! 2105: } ! 2106: /* Get a reference to just this component. */ ! 2107: if (modifier == EXPAND_CONST_ADDRESS) ! 2108: op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0), ! 2109: (bitpos / BITS_PER_UNIT))); ! 2110: else ! 2111: op0 = change_address (op0, mode1, ! 2112: plus_constant (XEXP (op0, 0), ! 2113: (bitpos / BITS_PER_UNIT))); ! 2114: op0->in_struct = 1; ! 2115: op0->volatil = volstruct; ! 2116: /* If OP0 is in the shared structure-value stack slot, ! 2117: and it is not BLKmode, copy it into a register. ! 2118: The shared slot may be clobbered at any time by another call. ! 2119: BLKmode is safe because our caller will either copy the value away ! 2120: or take another component and come back here. */ ! 2121: if (mode != BLKmode ! 2122: && TREE_CODE (TREE_OPERAND (exp, 0)) == CALL_EXPR ! 2123: && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == BLKmode) ! 2124: op0 = copy_to_reg (op0); ! 2125: if (mode == mode1 || mode1 == BLKmode || mode1 == tmode) ! 2126: return op0; ! 2127: if (target == 0) ! 2128: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); ! 2129: convert_move (target, op0, unsignedp); ! 2130: return target; 1.1 root 2131: } 2132: 2133: /* Intended for a reference to a buffer of a file-object in Pascal. 2134: But it's not certain that a special tree code will really be 2135: necessary for these. INDIRECT_REF might work for them. */ 2136: case BUFFER_REF: 2137: abort (); 2138: 2139: case CALL_EXPR: 1.1.1.2 ! root 2140: /* Check for a built-in function. */ ! 2141: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR ! 2142: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL ! 2143: && DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 2144: return expand_builtin (exp, target, subtarget, tmode); 1.1 root 2145: /* If this call was expanded already by preexpand_calls, 2146: just return the result we got. */ 2147: if (CALL_EXPR_RTL (exp) != 0) 2148: return CALL_EXPR_RTL (exp); 1.1.1.2 ! root 2149: return expand_call (exp, target, ignore); 1.1 root 2150: 2151: case NOP_EXPR: 2152: case CONVERT_EXPR: 1.1.1.2 ! root 2153: if (TREE_CODE (type) == VOID_TYPE || ignore) 1.1 root 2154: { 1.1.1.2 ! root 2155: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier); 1.1 root 2156: return const0_rtx; 2157: } 2158: if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) 1.1.1.2 ! root 2159: return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier); 1.1 root 2160: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0); 1.1.1.2 ! root 2161: if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode) 1.1 root 2162: return op0; 1.1.1.2 ! root 2163: if (flag_force_mem && GET_CODE (op0) == MEM) ! 2164: op0 = copy_to_reg (op0); 1.1 root 2165: if (target == 0) 2166: target = gen_reg_rtx (mode); 1.1.1.2 ! root 2167: convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); 1.1 root 2168: return target; 2169: 2170: case PLUS_EXPR: 2171: preexpand_calls (exp); 1.1.1.2 ! root 2172: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST ! 2173: && modifier == EXPAND_SUM) 1.1 root 2174: { 1.1.1.2 ! root 2175: op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, EXPAND_SUM); 1.1 root 2176: op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0))); 1.1.1.2 ! root 2177: return op1; 1.1 root 2178: } 2179: negate_1 = 1; 2180: plus_minus: 1.1.1.2 ! root 2181: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 2182: && modifier == EXPAND_SUM) 1.1 root 2183: { 1.1.1.2 ! root 2184: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); 1.1 root 2185: op0 = plus_constant (op0, 2186: negate_1 * TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))); 1.1.1.2 ! root 2187: return op0; 1.1 root 2188: } 2189: this_optab = add_optab; 1.1.1.2 ! root 2190: if (modifier != EXPAND_SUM) goto binop; 1.1 root 2191: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 1.1.1.2 ! root 2192: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); ! 2193: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, EXPAND_SUM); 1.1 root 2194: /* Put a sum last, to simplify what follows. */ 2195: #ifdef OLD_INDEXING 2196: if (GET_CODE (op1) == MULT) 2197: { 2198: temp = op0; 2199: op0 = op1; 2200: op1 = temp; 2201: } 2202: #endif 2203: #ifndef OLD_INDEXING 2204: /* Make sure any term that's a sum with a constant comes last. */ 2205: if (GET_CODE (op0) == PLUS 1.1.1.2 ! root 2206: && CONSTANT_P (XEXP (op0, 1))) 1.1 root 2207: { 2208: temp = op0; 2209: op0 = op1; 2210: op1 = temp; 2211: } 2212: /* If adding to a sum including a constant, 2213: associate it to put the constant outside. */ 2214: if (GET_CODE (op1) == PLUS 1.1.1.2 ! root 2215: && CONSTANT_P (XEXP (op1, 1))) 1.1 root 2216: { 2217: op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0); 2218: if (GET_CODE (XEXP (op1, 1)) == CONST_INT) 2219: return plus_constant (op0, INTVAL (XEXP (op1, 1))); 2220: else 2221: return gen_rtx (PLUS, mode, op0, XEXP (op1, 1)); 2222: } 2223: #endif 2224: return gen_rtx (PLUS, mode, op0, op1); 2225: 2226: case MINUS_EXPR: 2227: preexpand_calls (exp); 2228: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) 2229: { 1.1.1.2 ! root 2230: if (modifier == EXPAND_SUM) ! 2231: { ! 2232: negate_1 = -1; ! 2233: goto plus_minus; ! 2234: } ! 2235: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); ! 2236: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 2237: op1 = gen_rtx (CONST_INT, VOIDmode, ! 2238: - TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))); ! 2239: this_optab = add_optab; ! 2240: goto binop2; 1.1 root 2241: } 2242: this_optab = sub_optab; 2243: goto binop; 2244: 2245: case MULT_EXPR: 2246: preexpand_calls (exp); 2247: /* If first operand is constant, swap them. 2248: Thus the following special case checks need only 2249: check the second operand. */ 2250: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST) 2251: { 2252: register tree t1 = TREE_OPERAND (exp, 0); 2253: TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1); 2254: TREE_OPERAND (exp, 1) = t1; 2255: } 2256: 2257: /* Attempt to return something suitable for generating an 2258: indexed address, for machines that support that. */ 2259: 1.1.1.2 ! root 2260: if (modifier == EXPAND_SUM ! 2261: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) 1.1 root 2262: { 1.1.1.2 ! root 2263: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); ! 2264: ! 2265: /* Apply distributive law if OP0 is x+c. */ ! 2266: if (GET_CODE (op0) == PLUS ! 2267: && GET_CODE (XEXP (op0, 1)) == CONST_INT) ! 2268: return gen_rtx (PLUS, mode, ! 2269: gen_rtx (MULT, mode, XEXP (op0, 0), ! 2270: gen_rtx (CONST_INT, VOIDmode, ! 2271: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), ! 2272: gen_rtx (CONST_INT, VOIDmode, ! 2273: (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! 2274: * INTVAL (XEXP (op0, 1))))); ! 2275: 1.1 root 2276: if (GET_CODE (op0) != REG) 1.1.1.2 ! root 2277: op0 = force_operand (op0, 0); ! 2278: if (GET_CODE (op0) != REG) ! 2279: op0 = copy_to_mode_reg (mode, op0); ! 2280: 1.1 root 2281: return gen_rtx (MULT, mode, op0, 2282: gen_rtx (CONST_INT, VOIDmode, 2283: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); 2284: } 2285: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 2286: /* Check for multiplying things that have been extended 2287: from a narrower type. If this machine supports multiplying 2288: in that narrower type with a result in the desired type, 2289: do it that way, and avoid the explicit type-conversion. */ 2290: if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR 2291: && TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE 2292: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) 2293: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))) 2294: && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST 2295: && int_fits_type_p (TREE_OPERAND (exp, 1), 1.1.1.2 ! root 2296: TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 2297: /* Don't use a widening multiply if a shift will do. */ ! 2298: && exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0) 1.1 root 2299: || 2300: (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR 2301: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) 2302: == 1.1.1.2 ! root 2303: TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))) ! 2304: /* If both operands are extended, they must either both ! 2305: be zero-extended or both be sign-extended. */ ! 2306: && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) ! 2307: == ! 2308: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))))) 1.1 root 2309: { 2310: enum machine_mode innermode 2311: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))); 1.1.1.2 ! root 2312: this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) 1.1 root 2313: ? umul_widen_optab : smul_widen_optab); 2314: if ((int) innermode + 1 == (int) mode 1.1.1.2 ! root 2315: && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1.1 root 2316: { 2317: op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), 2318: 0, VOIDmode, 0); 2319: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) 2320: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2321: else 2322: op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 2323: 0, VOIDmode, 0); 2324: goto binop2; 2325: } 2326: } 2327: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2328: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 1.1.1.2 ! root 2329: return expand_mult (mode, op0, op1, target, TREE_UNSIGNED (type)); 1.1 root 2330: 2331: case TRUNC_DIV_EXPR: 2332: case FLOOR_DIV_EXPR: 2333: case CEIL_DIV_EXPR: 2334: case ROUND_DIV_EXPR: 2335: preexpand_calls (exp); 2336: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 1.1.1.2 ! root 2337: /* Possible optimization: compute the dividend with EXPAND_SUM 1.1 root 2338: then if the divisor is constant can optimize the case 2339: where some terms of the dividend have coeffs divisible by it. */ 2340: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2341: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2342: return expand_divmod (0, code, mode, op0, op1, target, 1.1.1.2 ! root 2343: TREE_UNSIGNED (type)); 1.1 root 2344: 2345: case RDIV_EXPR: 2346: preexpand_calls (exp); 2347: this_optab = flodiv_optab; 2348: goto binop; 2349: 2350: case TRUNC_MOD_EXPR: 2351: case FLOOR_MOD_EXPR: 2352: case CEIL_MOD_EXPR: 2353: case ROUND_MOD_EXPR: 2354: preexpand_calls (exp); 2355: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 2356: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2357: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2358: return expand_divmod (1, code, mode, op0, op1, target, 1.1.1.2 ! root 2359: TREE_UNSIGNED (type)); 1.1 root 2360: #if 0 2361: #ifdef HAVE_divmoddisi4 2362: if (GET_MODE (op0) != DImode) 2363: { 2364: temp = gen_reg_rtx (DImode); 2365: convert_move (temp, op0, 0); 2366: op0 = temp; 2367: if (GET_MODE (op1) != SImode && GET_CODE (op1) != CONST_INT) 2368: { 2369: temp = gen_reg_rtx (SImode); 2370: convert_move (temp, op1, 0); 2371: op1 = temp; 2372: } 2373: temp = gen_reg_rtx (SImode); 2374: if (target == 0) 2375: target = gen_reg_rtx (SImode); 2376: emit_insn (gen_divmoddisi4 (temp, protect_from_queue (op0, 0), 2377: protect_from_queue (op1, 0), 2378: protect_from_queue (target, 1))); 2379: return target; 2380: } 2381: #endif 2382: #endif 2383: 2384: case FIX_ROUND_EXPR: 2385: case FIX_FLOOR_EXPR: 2386: case FIX_CEIL_EXPR: 2387: abort (); /* Not used for C. */ 2388: 2389: case FIX_TRUNC_EXPR: 2390: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); 2391: if (target == 0) 2392: target = gen_reg_rtx (mode); 1.1.1.2 ! root 2393: { ! 2394: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 2395: if (mode == HImode || mode == QImode) ! 2396: { ! 2397: register rtx temp = gen_reg_rtx (SImode); ! 2398: expand_fix (temp, op0, unsignedp); ! 2399: convert_move (target, temp, unsignedp); ! 2400: } ! 2401: else ! 2402: expand_fix (target, op0, unsignedp); ! 2403: } 1.1 root 2404: return target; 2405: 2406: case FLOAT_EXPR: 2407: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); 2408: if (target == 0) 2409: target = gen_reg_rtx (mode); 1.1.1.2 ! root 2410: { ! 2411: int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 2412: if (GET_MODE (op0) == HImode ! 2413: || GET_MODE (op0) == QImode) ! 2414: { ! 2415: register rtx temp = gen_reg_rtx (SImode); ! 2416: convert_move (temp, op0, unsignedp); ! 2417: expand_float (target, temp, 0); ! 2418: } ! 2419: else ! 2420: expand_float (target, op0, unsignedp); ! 2421: } 1.1 root 2422: return target; 2423: 2424: case NEGATE_EXPR: 2425: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); 2426: temp = expand_unop (mode, neg_optab, op0, target, 0); 2427: if (temp == 0) 2428: abort (); 2429: return temp; 2430: 2431: case ABS_EXPR: 2432: /* First try to do it with a special abs instruction. 2433: If that does not win, use conditional jump and negate. */ 1.1.1.2 ! root 2434: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 1.1 root 2435: temp = expand_unop (mode, abs_optab, op0, target, 0); 2436: if (temp != 0) 2437: return temp; 2438: temp = gen_label_rtx (); 2439: if (target == 0 || GET_CODE (target) != REG) 1.1.1.2 ! root 2440: target = gen_reg_rtx (mode); 1.1 root 2441: emit_move_insn (target, op0); 1.1.1.2 ! root 2442: emit_cmp_insn (target, ! 2443: expand_expr (convert (TREE_TYPE (exp), integer_zero_node), ! 2444: 0, VOIDmode, 0), ! 2445: 0, 0); 1.1 root 2446: emit_jump_insn (gen_bge (temp)); 2447: op0 = expand_unop (mode, neg_optab, target, target, 0); 2448: if (op0 != target) 2449: emit_move_insn (target, op0); 2450: emit_label (temp); 2451: return target; 2452: 2453: case MAX_EXPR: 2454: case MIN_EXPR: 1.1.1.2 ! root 2455: mode = TYPE_MODE (TREE_OPERAND (exp, 1)); 1.1 root 2456: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2457: if (target == 0 || GET_CODE (target) != REG || target == op1) 1.1.1.2 ! root 2458: target = gen_reg_rtx (mode); 1.1 root 2459: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); 2460: if (target != op0) 2461: emit_move_insn (target, op0); 2462: op0 = gen_label_rtx (); 2463: if (code == MAX_EXPR) 1.1.1.2 ! root 2464: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 2465: ? compare1 (target, op1, GEU, LEU, 1, mode) ! 2466: : compare1 (target, op1, GE, LE, 0, mode)); ! 2467: else ! 2468: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 2469: ? compare1 (target, op1, LEU, GEU, 1, mode) ! 2470: : compare1 (target, op1, LE, GE, 0, mode)); ! 2471: if (temp == const0_rtx) ! 2472: emit_move_insn (target, op1); ! 2473: else if (temp != const1_rtx) ! 2474: { ! 2475: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, ! 2476: gen_rtx (IF_THEN_ELSE, VOIDmode, ! 2477: temp, ! 2478: gen_rtx (LABEL_REF, VOIDmode, op0), ! 2479: pc_rtx))); ! 2480: emit_move_insn (target, op1); ! 2481: } ! 2482: emit_label (op0); 1.1 root 2483: return target; 2484: 2485: /* ??? Can optimize when the operand of this is a bitwise operation, 2486: by using a different bitwise operation. */ 2487: case BIT_NOT_EXPR: 2488: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2489: temp = expand_unop (mode, one_cmpl_optab, op0, target, 1); 2490: if (temp == 0) 2491: abort (); 2492: return temp; 2493: 1.1.1.2 ! root 2494: case FFS_EXPR: ! 2495: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 2496: temp = expand_unop (mode, ffs_optab, op0, target, 1); ! 2497: if (temp == 0) ! 2498: abort (); ! 2499: return temp; ! 2500: 1.1 root 2501: /* ??? Can optimize bitwise operations with one arg constant. 2502: Pastel optimizes (a bitwise1 n) bitwise2 (a bitwise3 b) 2503: and (a bitwise1 b) bitwise2 b (etc) 2504: but that is probably not worth while. */ 2505: 1.1.1.2 ! root 2506: /* BIT_AND_EXPR is for bitwise anding. 1.1 root 2507: TRUTH_AND_EXPR is for anding two boolean values 2508: when we want in all cases to compute both of them. 2509: In general it is fastest to do TRUTH_AND_EXPR by 2510: computing both operands as actual zero-or-1 values 2511: and then bitwise anding. In cases where there cannot 2512: be any side effects, better code would be made by 2513: treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR; 2514: but the question is how to recognize those cases. */ 2515: 2516: case TRUTH_AND_EXPR: 2517: case BIT_AND_EXPR: 2518: preexpand_calls (exp); 2519: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 2520: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2521: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2522: return expand_bit_and (mode, op0, op1, target); 2523: 2524: /* See comment above about TRUTH_AND_EXPR; it applies here too. */ 2525: case TRUTH_OR_EXPR: 2526: case BIT_IOR_EXPR: 2527: preexpand_calls (exp); 2528: this_optab = ior_optab; 2529: goto binop; 2530: 2531: case BIT_XOR_EXPR: 2532: preexpand_calls (exp); 2533: this_optab = xor_optab; 2534: goto binop; 2535: 2536: case LSHIFT_EXPR: 2537: case RSHIFT_EXPR: 2538: case LROTATE_EXPR: 2539: case RROTATE_EXPR: 2540: preexpand_calls (exp); 2541: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 2542: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2543: return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, 1.1.1.2 ! root 2544: TREE_UNSIGNED (type)); 1.1 root 2545: 2546: /* ??? cv's were used to effect here to combine additive constants 2547: and to determine the answer when only additive constants differ. 2548: Also, the addition of one can be handled by changing the condition. */ 2549: case LT_EXPR: 2550: case LE_EXPR: 2551: case GT_EXPR: 2552: case GE_EXPR: 2553: case EQ_EXPR: 2554: case NE_EXPR: 2555: preexpand_calls (exp); 1.1.1.2 ! root 2556: temp = do_store_flag (exp, target, mode); 1.1 root 2557: if (temp != 0) 2558: return temp; 1.1.1.2 ! root 2559: /* For foo != 0, load foo, and if it is nonzero load 1 instead. */ ! 2560: if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1)) ! 2561: && subtarget ! 2562: && (GET_MODE (subtarget) ! 2563: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) 1.1 root 2564: { 2565: temp = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2566: if (temp != subtarget) 2567: temp = copy_to_reg (temp); 2568: op1 = gen_label_rtx (); 1.1.1.2 ! root 2569: emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type)); 1.1 root 2570: emit_jump_insn (gen_beq (op1)); 2571: emit_move_insn (temp, const1_rtx); 2572: emit_label (op1); 2573: return temp; 2574: } 2575: /* If no set-flag instruction, must generate a conditional 2576: store into a temporary variable. Drop through 2577: and handle this like && and ||. */ 2578: 2579: case TRUTH_ANDIF_EXPR: 2580: case TRUTH_ORIF_EXPR: 2581: temp = gen_reg_rtx (mode); 2582: emit_clr_insn (temp); 2583: op1 = gen_label_rtx (); 2584: jumpifnot (exp, op1); 2585: emit_0_to_1_insn (temp); 2586: emit_label (op1); 2587: return temp; 2588: 2589: case TRUTH_NOT_EXPR: 2590: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); 2591: /* The parser is careful to generate TRUTH_NOT_EXPR 2592: only with operands that are always zero or one. */ 2593: temp = expand_binop (mode, xor_optab, op0, 2594: gen_rtx (CONST_INT, mode, 1), 2595: target, 1, OPTAB_LIB_WIDEN); 2596: if (temp == 0) 2597: abort (); 2598: return temp; 2599: 2600: case COMPOUND_EXPR: 1.1.1.2 ! root 2601: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); 1.1 root 2602: emit_queue (); 2603: return expand_expr (TREE_OPERAND (exp, 1), target, VOIDmode, 0); 2604: 2605: case COND_EXPR: 2606: /* Note that COND_EXPRs whose type is a structure or union 2607: are required to be constructed to contain assignments of 2608: a temporary variable, so that we can evaluate them here 2609: for side effect only. If type is void, we must do likewise. */ 2610: op0 = gen_label_rtx (); 2611: op1 = gen_label_rtx (); 2612: 1.1.1.2 ! root 2613: if (mode == VOIDmode || ignore) 1.1 root 2614: temp = 0; 2615: else if (target) 2616: temp = target; 1.1.1.2 ! root 2617: else if (mode == BLKmode) ! 2618: { ! 2619: if (TYPE_SIZE (type) == 0 || ! TREE_LITERAL (TYPE_SIZE (type))) ! 2620: abort (); ! 2621: temp = assign_stack_local (BLKmode, ! 2622: (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! 2623: * TYPE_SIZE_UNIT (type) ! 2624: + BITS_PER_UNIT - 1) ! 2625: / BITS_PER_UNIT); ! 2626: } 1.1 root 2627: else 2628: temp = gen_reg_rtx (mode); 2629: 2630: jumpifnot (TREE_OPERAND (exp, 0), op0); 2631: current_args_size += 1; 2632: if (temp != 0) 1.1.1.2 ! root 2633: store_expr (TREE_OPERAND (exp, 1), temp, 0); 1.1 root 2634: else 1.1.1.2 ! root 2635: expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0, ! 2636: VOIDmode, 0); 1.1 root 2637: emit_queue (); 2638: emit_jump_insn (gen_jump (op1)); 2639: emit_barrier (); 2640: emit_label (op0); 2641: if (temp != 0) 1.1.1.2 ! root 2642: store_expr (TREE_OPERAND (exp, 2), temp, 0); 1.1 root 2643: else 1.1.1.2 ! root 2644: expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0, ! 2645: VOIDmode, 0); 1.1 root 2646: emit_queue (); 2647: emit_label (op1); 2648: current_args_size -= 1; 2649: return temp; 2650: 2651: case MODIFY_EXPR: 2652: /* If lhs is complex, expand calls in rhs before computing it. 2653: That's so we don't compute a pointer and save it over a call. 2654: If lhs is simple, compute it first so we can give it as a 2655: target if the rhs is just a call. This avoids an extra temp and copy 2656: and that prevents a partial-subsumption which makes bad code. 2657: Actually we could treat component_ref's of vars like vars. */ 1.1.1.2 ! root 2658: if (TREE_CODE (TREE_OPERAND (exp, 0)) != VAR_DECL ! 2659: && TREE_CODE (TREE_OPERAND (exp, 0)) != RESULT_DECL ! 2660: && TREE_CODE (TREE_OPERAND (exp, 0)) != PARM_DECL) 1.1 root 2661: preexpand_calls (exp); 2662: temp = expand_assignment (TREE_OPERAND (exp, 0), 1.1.1.2 ! root 2663: TREE_OPERAND (exp, 1), ! 2664: ! ignore, ! 2665: original_target != 0); 1.1 root 2666: return temp; 2667: 2668: case PREINCREMENT_EXPR: 2669: case PREDECREMENT_EXPR: 1.1.1.2 ! root 2670: return expand_increment (exp, 0); 1.1 root 2671: 2672: case POSTINCREMENT_EXPR: 2673: case POSTDECREMENT_EXPR: 1.1.1.2 ! root 2674: return expand_increment (exp, 1); 1.1 root 2675: 2676: case ADDR_EXPR: 1.1.1.2 ! root 2677: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, ! 2678: EXPAND_CONST_ADDRESS); 1.1 root 2679: if (GET_CODE (op0) != MEM) 2680: abort (); 1.1.1.2 ! root 2681: if (modifier == EXPAND_SUM) 1.1 root 2682: return XEXP (op0, 0); 1.1.1.2 ! root 2683: op0 = force_operand (XEXP (op0, 0), target); ! 2684: if (flag_force_addr && GET_CODE (op0) != REG) ! 2685: return force_reg (Pmode, op0); ! 2686: return op0; 1.1 root 2687: 2688: case ENTRY_VALUE_EXPR: 2689: abort (); 2690: 2691: case ERROR_MARK: 1.1.1.2 ! root 2692: return const0_rtx; 1.1 root 2693: 2694: default: 2695: abort (); 2696: } 2697: 2698: /* Here to do an ordinary binary operator, generating an instruction 2699: from the optab already placed in `this_optab'. */ 2700: binop: 2701: /* Detect things like x = y | (a == b) 2702: and do them as (x = y), (a == b ? x |= 1 : 0), x. */ 2703: /* First, get the comparison or conditional into the second arg. */ 2704: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 0))] 2705: || (TREE_CODE (TREE_OPERAND (exp, 0)) == COND_EXPR 2706: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) 2707: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 2))))) 2708: { 2709: if (this_optab == ior_optab || this_optab == add_optab 2710: || this_optab == xor_optab) 2711: { 2712: tree exch = TREE_OPERAND (exp, 1); 2713: TREE_OPERAND (exp, 1) = TREE_OPERAND (exp, 0); 2714: TREE_OPERAND (exp, 0) = exch; 2715: } 2716: } 2717: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 1))] 2718: || (TREE_CODE (TREE_OPERAND (exp, 1)) == COND_EXPR 2719: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 1)) 2720: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2))))) 2721: { 2722: if (this_optab == ior_optab || this_optab == add_optab 2723: || this_optab == xor_optab || this_optab == sub_optab 2724: || this_optab == lshl_optab || this_optab == ashl_optab 2725: || this_optab == lshr_optab || this_optab == ashr_optab 2726: || this_optab == rotl_optab || this_optab == rotr_optab) 2727: { 1.1.1.2 ! root 2728: tree thenexp; 1.1 root 2729: rtx thenv = 0; 2730: 2731: if (target == 0) target = gen_reg_rtx (mode); 1.1.1.2 ! root 2732: store_expr (TREE_OPERAND (exp, 0), target, 0); 1.1 root 2733: op0 = gen_label_rtx (); 2734: 2735: if (TREE_CODE (TREE_OPERAND (exp, 1)) != COND_EXPR) 2736: { 2737: do_jump (TREE_OPERAND (exp, 1), op0, 0); 2738: thenv = const1_rtx; 2739: } 2740: else if (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2))) 2741: { 2742: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), op0, 0); 2743: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 1); 2744: } 2745: else 2746: { 2747: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0, op0); 2748: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 2); 2749: } 2750: 2751: if (thenv == 0) 2752: thenv = expand_expr (thenexp, 0, VOIDmode, 0); 2753: 2754: if (this_optab == rotl_optab || this_optab == rotr_optab) 2755: temp = expand_binop (mode, this_optab, target, thenv, target, 2756: -1, OPTAB_LIB); 2757: else if (this_optab == lshl_optab || this_optab == lshr_optab) 2758: temp = expand_binop (mode, this_optab, target, thenv, target, 2759: 1, OPTAB_LIB_WIDEN); 2760: else 2761: temp = expand_binop (mode, this_optab, target, thenv, target, 2762: 0, OPTAB_LIB_WIDEN); 2763: if (target != temp) 2764: emit_move_insn (target, temp); 2765: 2766: emit_label (op0); 2767: return target; 2768: } 2769: } 2770: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1)); 2771: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); 2772: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 2773: binop2: 2774: temp = expand_binop (mode, this_optab, op0, op1, target, 1.1.1.2 ! root 2775: TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); 1.1 root 2776: binop1: 2777: if (temp == 0) 2778: abort (); 2779: return temp; 2780: } 2781: 1.1.1.2 ! root 2782: /* Expand an expression EXP that calls a built-in function, ! 2783: with result going to TARGET if that's convenient ! 2784: (and in mode MODE if that's convenient). ! 2785: SUBTARGET may be used as the target for computing one of EXP's operands. */ ! 2786: ! 2787: static rtx ! 2788: expand_builtin (exp, target, subtarget, mode) ! 2789: tree exp; ! 2790: rtx target; ! 2791: rtx subtarget; ! 2792: enum machine_mode mode; ! 2793: { ! 2794: tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); ! 2795: tree arglist = TREE_OPERAND (exp, 1); ! 2796: rtx op0; ! 2797: rtx temp; ! 2798: ! 2799: switch (DECL_FUNCTION_CODE (fndecl)) ! 2800: { ! 2801: case BUILT_IN_ABS: ! 2802: case BUILT_IN_LABS: ! 2803: case BUILT_IN_FABS: ! 2804: /* build_function_call changes these into ABS_EXPR. */ ! 2805: abort (); ! 2806: ! 2807: case BUILT_IN_ALLOCA: ! 2808: if (arglist == 0) ! 2809: return const0_rtx; ! 2810: frame_pointer_needed = 1; ! 2811: /* Compute the argument. */ ! 2812: op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0); ! 2813: if (! CONSTANT_P (op0)) ! 2814: { ! 2815: op0 = force_reg (GET_MODE (op0), op0); ! 2816: if (GET_MODE (op0) != Pmode) ! 2817: op0 = convert_to_mode (Pmode, op0); ! 2818: } ! 2819: /* Push that much space (rounding it up). */ ! 2820: anti_adjust_stack (round_push (op0)); ! 2821: /* Return a copy of current stack ptr, in TARGET if possible. */ ! 2822: if (target) ! 2823: emit_move_insn (target, stack_pointer_rtx); ! 2824: else ! 2825: target = copy_to_reg (stack_pointer_rtx); ! 2826: return target; ! 2827: ! 2828: case BUILT_IN_FFS: ! 2829: if (arglist == 0) ! 2830: return const0_rtx; ! 2831: ! 2832: /* Compute the argument. */ ! 2833: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); ! 2834: /* Compute ffs, into TARGET if possible. ! 2835: Set TARGET to wherever the result comes back. */ ! 2836: target = expand_unop (mode, ffs_optab, op0, target, 1); ! 2837: if (target == 0) ! 2838: abort (); ! 2839: return target; ! 2840: ! 2841: default: ! 2842: abort (); ! 2843: } ! 2844: } ! 2845: ! 2846: /* Expand code for a post- or pre- increment or decrement ! 2847: and return the RTX for the result. ! 2848: POST is 1 for postinc/decrements and 0 for preinc/decrements. */ ! 2849: ! 2850: static rtx ! 2851: expand_increment (exp, post) ! 2852: register tree exp; ! 2853: int post; ! 2854: { ! 2855: register rtx op0, op1; ! 2856: register rtx temp; ! 2857: register tree incremented = TREE_OPERAND (exp, 0); ! 2858: optab this_optab = add_optab; ! 2859: int icode; ! 2860: enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); ! 2861: int op0_is_copy = 0; ! 2862: ! 2863: /* Stabilize any component ref that might need to be ! 2864: evaluated more than once below. */ ! 2865: if (TREE_CODE (incremented) == COMPONENT_REF ! 2866: && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF ! 2867: || DECL_MODE (TREE_OPERAND (exp, 1)) == BImode)) ! 2868: incremented = stabilize_reference (incremented); ! 2869: ! 2870: /* Compute the operands as RTX. ! 2871: Note whether OP0 is the actual lvalue or a copy of it: ! 2872: I believe it is a copy iff it is a register and insns were ! 2873: generated in computing it. */ ! 2874: temp = get_last_insn (); ! 2875: op0 = expand_expr (incremented, 0, VOIDmode, 0); ! 2876: if (temp != get_last_insn ()) ! 2877: op0_is_copy = (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG); ! 2878: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 2879: ! 2880: /* Decide whether incrementing or decrementing. */ ! 2881: if (TREE_CODE (exp) == POSTDECREMENT_EXPR ! 2882: || TREE_CODE (exp) == PREDECREMENT_EXPR) ! 2883: this_optab = sub_optab; ! 2884: ! 2885: /* If OP0 is not the actual lvalue, but rather a copy in a register, ! 2886: then we cannot just increment OP0. We must ! 2887: therefore contrive to increment the original value. ! 2888: Then we can return OP0 since it is a copy of the old value. */ ! 2889: if (op0_is_copy) ! 2890: { ! 2891: /* This is the easiest way to increment the value wherever it is. ! 2892: Problems with multiple evaluation of INCREMENTED ! 2893: are prevented because either (1) it is a component_ref, ! 2894: in which case it was stabilized above, or (2) it is an array_ref ! 2895: with constant index in an array in a register, which is ! 2896: safe to reevaluate. */ ! 2897: tree newexp = build ((this_optab == add_optab ! 2898: ? PLUS_EXPR : MINUS_EXPR), ! 2899: TREE_TYPE (exp), ! 2900: incremented, ! 2901: TREE_OPERAND (exp, 1)); ! 2902: temp = expand_assignment (incremented, newexp, ! post, 0); ! 2903: return post ? op0 : temp; ! 2904: } ! 2905: ! 2906: /* Convert decrement by a constant into a negative increment. */ ! 2907: if (this_optab == sub_optab ! 2908: && GET_CODE (op1) == CONST_INT) ! 2909: { ! 2910: op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1)); ! 2911: this_optab = add_optab; ! 2912: } ! 2913: ! 2914: if (post) ! 2915: { ! 2916: /* We have a true reference to the value in OP0. ! 2917: If there is an insn to add or subtract in this mode, queue it. */ ! 2918: ! 2919: /* I'm not sure this is still necessary. */ ! 2920: op0 = stabilize (op0); ! 2921: ! 2922: icode = (int) this_optab->handlers[(int) mode].insn_code; ! 2923: if (icode != (int) CODE_FOR_nothing ! 2924: /* Make sure that OP0 is valid for operands 0 and 1 ! 2925: of the insn we want to queue. */ ! 2926: && (*insn_operand_predicate[icode][0]) (op0, mode) ! 2927: && (*insn_operand_predicate[icode][1]) (op0, mode)) ! 2928: { ! 2929: if (! (*insn_operand_predicate[icode][2]) (op1, mode)) ! 2930: op1 = force_reg (mode, op1); ! 2931: ! 2932: return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1)); ! 2933: } ! 2934: } ! 2935: ! 2936: /* Preincrement, or we can't increment with one simple insn. */ ! 2937: if (post) ! 2938: /* Save a copy of the value before inc or dec, to return it later. */ ! 2939: temp = copy_to_reg (op0); ! 2940: else ! 2941: /* Arrange to return the incremented value. */ ! 2942: temp = op0; ! 2943: ! 2944: /* Increment however we can. */ ! 2945: op1 = expand_binop (mode, this_optab, op0, op1, op0, ! 2946: 0, OPTAB_LIB_WIDEN); ! 2947: /* Make sure the value is stored into OP0. */ ! 2948: if (op1 != op0) ! 2949: emit_move_insn (op0, op1); ! 2950: ! 2951: return temp; ! 2952: } ! 2953: 1.1 root 2954: /* Expand all function calls contained within EXP, innermost ones first. 2955: But don't look within expressions that have sequence points. 2956: For each CALL_EXPR, record the rtx for its value 1.1.1.2 ! root 2957: in the CALL_EXPR_RTL field. ! 2958: ! 2959: Calls that return large structures for which a structure return ! 2960: stack slot is needed are not preexpanded. Preexpanding them loses ! 2961: because if more than one were preexpanded they would try to use the ! 2962: same stack slot. */ 1.1 root 2963: 2964: static void 2965: preexpand_calls (exp) 2966: tree exp; 2967: { 2968: register int nops, i; 2969: 2970: if (! do_preexpand_calls) 2971: return; 2972: 1.1.1.2 ! root 2973: /* Only expressions and references can contain calls. */ ! 2974: ! 2975: if (tree_code_type[(int) TREE_CODE (exp)][0] != 'e' ! 2976: && tree_code_type[(int) TREE_CODE (exp)][0] != 'r') ! 2977: return; ! 2978: 1.1 root 2979: switch (TREE_CODE (exp)) 2980: { 2981: case CALL_EXPR: 1.1.1.2 ! root 2982: /* Do nothing to built-in functions. */ ! 2983: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR ! 2984: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL ! 2985: && DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 2986: return; ! 2987: if (CALL_EXPR_RTL (exp) == 0 ! 2988: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode) ! 2989: CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0); 1.1 root 2990: return; 2991: 2992: case COMPOUND_EXPR: 2993: case COND_EXPR: 2994: case TRUTH_ANDIF_EXPR: 2995: case TRUTH_ORIF_EXPR: 2996: /* If we find one of these, then we can be sure 2997: the adjust will be done for it (since it makes jumps). 2998: Do it now, so that if this is inside an argument 2999: of a function, we don't get the stack adjustment 3000: after some other args have already been pushed. */ 3001: do_pending_stack_adjust (); 3002: return; 3003: 1.1.1.2 ! root 3004: case RTL_EXPR: ! 3005: return; ! 3006: 1.1 root 3007: case SAVE_EXPR: 3008: if (SAVE_EXPR_RTL (exp) != 0) 3009: return; 3010: } 3011: 3012: nops = tree_code_length[(int) TREE_CODE (exp)]; 3013: for (i = 0; i < nops; i++) 3014: if (TREE_OPERAND (exp, i) != 0) 3015: { 3016: register int type = *tree_code_type[(int) TREE_CODE (TREE_OPERAND (exp, i))]; 3017: if (type == 'e' || type == 'r') 3018: preexpand_calls (TREE_OPERAND (exp, i)); 3019: } 3020: } 3021: 1.1.1.2 ! root 3022: /* Force FUNEXP into a form suitable for the address of a CALL, ! 3023: and return that as an rtx. Also load the static chain register ! 3024: from either FUNEXP or CONTEXT. */ 1.1 root 3025: 1.1.1.2 ! root 3026: static rtx ! 3027: prepare_call_address (funexp, context) 1.1 root 3028: rtx funexp; 3029: rtx context; 3030: { 3031: funexp = protect_from_queue (funexp, 0); 1.1.1.2 ! root 3032: if (context != 0) 1.1 root 3033: context = protect_from_queue (context, 0); 3034: 3035: /* Function variable in language with nested functions. */ 3036: if (GET_MODE (funexp) == EPmode) 3037: { 1.1.1.2 ! root 3038: emit_move_insn (static_chain_rtx, gen_highpart (Pmode, funexp)); ! 3039: funexp = memory_address (FUNCTION_MODE, gen_lowpart (Pmode, funexp)); ! 3040: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); 1.1 root 3041: } 3042: else 3043: { 3044: if (context != 0) 1.1.1.2 ! root 3045: /* Unless function variable in C, or top level function constant */ ! 3046: emit_move_insn (static_chain_rtx, lookup_static_chain (context)); ! 3047: ! 3048: /* Make a valid memory address and copy constants thru pseudo-regs, ! 3049: but not for a constant address if -fno-function-cse. */ ! 3050: if (GET_CODE (funexp) != SYMBOL_REF) ! 3051: funexp = memory_address (FUNCTION_MODE, funexp); ! 3052: else 1.1 root 3053: { 1.1.1.2 ! root 3054: #ifndef NO_FUNCTION_CSE ! 3055: if (! flag_no_function_cse) ! 3056: funexp = copy_to_mode_reg (Pmode, funexp); ! 3057: #endif ! 3058: } ! 3059: ! 3060: if (context != 0) ! 3061: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx)); 1.1 root 3062: } 1.1.1.2 ! root 3063: return funexp; ! 3064: } ! 3065: ! 3066: /* Generate instructions to call function FUNEXP, ! 3067: and optionally pop the results. ! 3068: The CALL_INSN is the first insn generated. ! 3069: ! 3070: FUNTYPE is the data type of the function, or, for a library call, ! 3071: the identifier for the name of the call. This is given to the ! 3072: macro RETURN_POPS_ARGS to determine whether this function pops its own args. ! 3073: ! 3074: STACK_SIZE is the number of bytes of arguments on the stack, ! 3075: rounded up to STACK_BOUNDARY; zero if the size is variable. ! 3076: This is both to put into the call insn and ! 3077: to generate explicit popping code if necessary. ! 3078: ! 3079: NEXT_ARG_REG is the rtx that results from executing ! 3080: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1) ! 3081: just after all the args have had their registers assigned. ! 3082: This could be whatever you like, but normally it is the first ! 3083: arg-register beyond those used for args in this call, ! 3084: or 0 if all the arg-registers are used in this call. ! 3085: It is passed on to `gen_call' so you can put this info in the call insn. ! 3086: ! 3087: VALREG is a hard register in which a value is returned, ! 3088: or 0 if the call does not return a value. ! 3089: ! 3090: OLD_ARGS_SIZE is the value that `current_args_size' had before ! 3091: the args to this call were processed. ! 3092: We restore `current_args_size' to that value. */ ! 3093: ! 3094: static void ! 3095: emit_call_1 (funexp, funtype, stack_size, next_arg_reg, valreg, old_args_size) ! 3096: rtx funexp; ! 3097: tree funtype; ! 3098: int stack_size; ! 3099: rtx next_arg_reg; ! 3100: rtx valreg; ! 3101: int old_args_size; ! 3102: { ! 3103: rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size); ! 3104: ! 3105: if (valreg) ! 3106: emit_call_insn (gen_call_value (valreg, ! 3107: gen_rtx (MEM, FUNCTION_MODE, funexp), ! 3108: stack_size_rtx, next_arg_reg)); ! 3109: else ! 3110: emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp), ! 3111: stack_size_rtx, next_arg_reg)); ! 3112: ! 3113: current_args_size = old_args_size; ! 3114: 1.1 root 3115: /* If returning from the subroutine does not automatically pop the args, 3116: we need an instruction to pop them sooner or later. 3117: Perhaps do it now; perhaps just record how much space to pop later. */ 1.1.1.2 ! root 3118: ! 3119: if (! RETURN_POPS_ARGS (TREE_TYPE (funtype)) ! 3120: && stack_size != 0) 1.1 root 3121: { 1.1.1.2 ! root 3122: if (flag_defer_pop && current_args_size == 0) ! 3123: pending_stack_adjust += stack_size; 1.1 root 3124: else 1.1.1.2 ! root 3125: adjust_stack (gen_rtx (CONST_INT, VOIDmode, stack_size)); 1.1 root 3126: } 3127: } 3128: 3129: /* At the start of a function, record that we have no previously-pushed 3130: arguments waiting to be popped. */ 3131: 1.1.1.2 ! root 3132: void ! 3133: init_pending_stack_adjust () 1.1 root 3134: { 3135: pending_stack_adjust = 0; 3136: } 3137: 1.1.1.2 ! root 3138: /* When exiting from function, if safe, clear out any pending stack adjust ! 3139: so the adjustment won't get done. */ ! 3140: ! 3141: void ! 3142: clear_pending_stack_adjust () ! 3143: { ! 3144: #if 0 ! 3145: /* Right now it's never considered safe, because ! 3146: it loses in an inline function. */ ! 3147: #ifdef EXIT_IGNORE_STACK ! 3148: if (!flag_omit_frame_pointer && EXIT_IGNORE_STACK) ! 3149: pending_stack_adjust = 0; ! 3150: #endif ! 3151: #endif ! 3152: } ! 3153: 1.1 root 3154: /* At start of function, initialize. */ 1.1.1.2 ! root 3155: void 1.1 root 3156: clear_current_args_size () 3157: { 3158: current_args_size = 0; 3159: } 3160: 3161: /* Pop any previously-pushed arguments that have not been popped yet. */ 3162: 1.1.1.2 ! root 3163: void 1.1 root 3164: do_pending_stack_adjust () 3165: { 3166: if (current_args_size == 0) 3167: { 3168: if (pending_stack_adjust != 0) 3169: adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust)); 3170: pending_stack_adjust = 0; 3171: } 3172: } 3173: 3174: /* Generate all the code for a function call 3175: and return an rtx for its value. 3176: Store the value in TARGET (specified as an rtx) if convenient. 1.1.1.2 ! root 3177: If the value is stored in TARGET then TARGET is returned. ! 3178: If IGNORE is nonzero, then we ignore the value of the function call. */ 1.1 root 3179: 3180: static rtx 1.1.1.2 ! root 3181: expand_call (exp, target, ignore) 1.1 root 3182: tree exp; 3183: rtx target; 1.1.1.2 ! root 3184: int ignore; 1.1 root 3185: { 3186: tree actparms = TREE_OPERAND (exp, 1); 1.1.1.2 ! root 3187: tree funtype; ! 3188: rtx funexp; ! 3189: register tree p = TREE_OPERAND (exp, 0); ! 3190: struct args_size args_size; 1.1 root 3191: register int i; 3192: register tree *argvec; 1.1.1.2 ! root 3193: rtx *regvec; ! 3194: rtx *valvec; ! 3195: int *partial; ! 3196: struct args_size *arg_offset; ! 3197: struct args_size *arg_size; 1.1 root 3198: int num_actuals; 3199: rtx structure_value_addr = 0; 1.1.1.2 ! root 3200: tree fndecl = 0; ! 3201: int may_be_alloca; ! 3202: int inc; ! 3203: int is_setjmp; ! 3204: int is_integrable = 0; ! 3205: rtx argblock = 0; ! 3206: CUMULATIVE_ARGS args_so_far; ! 3207: int reg_parm_seen = 0; ! 3208: rtx valreg; ! 3209: rtx old_stack_level; ! 3210: int old_pending_adj; ! 3211: int old_current_args_size = current_args_size; ! 3212: ! 3213: /* Number of named args. Args after this are anonymous ones ! 3214: and they must all go on the stack. */ ! 3215: int n_named_args; ! 3216: ! 3217: args_size.constant = 0; ! 3218: args_size.var = 0; ! 3219: ! 3220: /* See if we can find a DECL-node for the actual function. ! 3221: As a result, decide whether this is a call to an integrable function. */ ! 3222: ! 3223: if (TREE_CODE (p) == ADDR_EXPR) ! 3224: { ! 3225: fndecl = TREE_OPERAND (p, 0); ! 3226: if (TREE_CODE (fndecl) != FUNCTION_DECL) ! 3227: fndecl = 0; ! 3228: else ! 3229: { ! 3230: extern tree current_function_decl; 1.1 root 3231: 1.1.1.2 ! root 3232: if (fndecl != current_function_decl ! 3233: && DECL_SAVED_INSNS (fndecl)) ! 3234: is_integrable = 1; ! 3235: else ! 3236: /* In case this function later becomes inlineable, ! 3237: record that there was already a non-inline call to it. */ ! 3238: TREE_ADDRESSABLE (fndecl) = 1; ! 3239: } ! 3240: } 1.1 root 3241: 1.1.1.2 ! root 3242: /* Set up a place to return a structure. */ 1.1 root 3243: 3244: if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode) 3245: { 3246: /* This call returns a big structure. */ 3247: if (target) 3248: structure_value_addr = XEXP (target, 0); 3249: else 3250: /* Make room on the stack to hold the value. */ 3251: structure_value_addr = get_structure_value_addr (expr_size (exp)); 3252: } 3253: 1.1.1.2 ! root 3254: if (is_integrable) ! 3255: { ! 3256: extern int integration_time; ! 3257: extern rtx expand_inline_function (); ! 3258: rtx temp; ! 3259: ! 3260: temp = expand_inline_function (fndecl, actparms, target, ! 3261: ignore, TREE_TYPE (exp), ! 3262: structure_value_addr); ! 3263: ! 3264: /* If the inlining failed for whatever reason, we will just ! 3265: issue a normal call. */ ! 3266: if (temp == (rtx)-1) ! 3267: { ! 3268: warning_with_decl (fndecl, "inlining function `%s' failed, reverting to function call"); ! 3269: } ! 3270: else ! 3271: return temp; ! 3272: } ! 3273: ! 3274: #if 0 ! 3275: /* Unless it's a call to a specific function that isn't alloca, ! 3276: if it has one argument, we must assume it might be alloca. */ ! 3277: ! 3278: may_be_alloca = ! 3279: (!(fndecl != 0 ! 3280: && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), ! 3281: "alloca")) ! 3282: && actparms != 0 ! 3283: && TREE_CHAIN (actparms) == 0); ! 3284: #else ! 3285: /* We assume that alloca will always be called by name. It ! 3286: makes no sense to pass it as a pointer-to-function to ! 3287: anything that does not understand its behavior. */ ! 3288: may_be_alloca = ! 3289: (fndecl && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "alloca")); ! 3290: #endif ! 3291: ! 3292: /* See if this is a call to a function that can return more than once. */ ! 3293: ! 3294: is_setjmp ! 3295: = (fndecl != 0 ! 3296: && (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "setjmp") ! 3297: || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "_setjmp"))); ! 3298: ! 3299: if (may_be_alloca) ! 3300: { ! 3301: frame_pointer_needed = 1; ! 3302: may_call_alloca = 1; ! 3303: } ! 3304: ! 3305: /* Don't let pending stack adjusts add up to too much. ! 3306: Also, do all pending adjustments now ! 3307: if there is any chance this might be a call to alloca. */ ! 3308: ! 3309: if (pending_stack_adjust >= 32 ! 3310: || (pending_stack_adjust > 0 && may_be_alloca)) ! 3311: do_pending_stack_adjust (); ! 3312: ! 3313: /* Operand 0 is a pointer-to-function; get the type of the function. */ ! 3314: funtype = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 3315: if (TREE_CODE (funtype) != POINTER_TYPE) ! 3316: abort (); ! 3317: funtype = TREE_TYPE (funtype); ! 3318: ! 3319: /* Count the arguments and set NUM_ACTUALS. */ 1.1 root 3320: for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++; 3321: num_actuals = i; 1.1.1.2 ! root 3322: ! 3323: /* Compute number of named args. ! 3324: This may actually be 1 too large, but that happens ! 3325: only in the case when all args are named, so no trouble results. */ ! 3326: if (TYPE_ARG_TYPES (funtype) != 0) ! 3327: n_named_args = list_length (TYPE_ARG_TYPES (funtype)); ! 3328: else ! 3329: /* If we know nothing, treat all args as named. */ ! 3330: n_named_args = num_actuals; ! 3331: ! 3332: /* Make a vector of the args, in the order we want to compute them, ! 3333: and a parallel vector of where we want to put them. ! 3334: regvec[I] is 0 to if should push argvec[I] or else a reg to put it in. ! 3335: valvec[i] is the arg value as an rtx. */ 1.1 root 3336: argvec = (tree *) alloca (i * sizeof (tree)); 1.1.1.2 ! root 3337: regvec = (rtx *) alloca (i * sizeof (rtx)); ! 3338: valvec = (rtx *) alloca (i * sizeof (rtx)); ! 3339: partial = (int *) alloca (i * sizeof (int)); ! 3340: arg_size = (struct args_size *) alloca (i * sizeof (struct args_size)); ! 3341: arg_offset = (struct args_size *) alloca (i * sizeof (struct args_size)); ! 3342: ! 3343: /* In this loop, we consider args in the order they are written. ! 3344: We fill up argvec from the front of from the back ! 3345: so that the first arg to be pushed ends up at the front. */ 1.1 root 3346: 1.1.1.2 ! root 3347: #ifdef PUSH_ARGS_REVERSED ! 3348: i = num_actuals - 1, inc = -1; 1.1 root 3349: /* In this case, must reverse order of args 1.1.1.2 ! root 3350: so that we compute and push the last arg first. */ 1.1 root 3351: #else 1.1.1.2 ! root 3352: i = 0, inc = 1; ! 3353: #endif ! 3354: ! 3355: INIT_CUMULATIVE_ARGS (args_so_far, funtype); ! 3356: ! 3357: for (p = actparms; p; p = TREE_CHAIN (p), i += inc) ! 3358: { ! 3359: tree type = TREE_TYPE (TREE_VALUE (p)); ! 3360: argvec[i] = p; ! 3361: regvec[i] = 0; ! 3362: valvec[i] = 0; ! 3363: partial[i] = 0; ! 3364: arg_size[i].constant = 0; ! 3365: arg_size[i].var = 0; ! 3366: arg_offset[i] = args_size; ! 3367: ! 3368: if (type == error_mark_node) ! 3369: continue; ! 3370: ! 3371: /* Decide where to pass this arg. */ ! 3372: /* regvec[i] is nonzero if all or part is passed in registers. ! 3373: partial[i] is nonzero if part but not all is passed in registers, ! 3374: and the exact value says how many words are passed in registers. */ ! 3375: ! 3376: if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST ! 3377: || args_size.var != 0) ! 3378: { ! 3379: regvec[i] = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type, ! 3380: i < n_named_args); ! 3381: #ifdef FUNCTION_ARG_PARTIAL_NREGS ! 3382: partial[i] = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, ! 3383: TYPE_MODE (type), type, ! 3384: i < n_named_args); ! 3385: #endif ! 3386: } ! 3387: ! 3388: /* Once we see at least one parm that is being passed in a register, ! 3389: precompute that parm and all remaining parms (if they do arithmetic) ! 3390: before loading any of them into their specified registers. ! 3391: That way we don't lose if one of them involves ! 3392: a function call OR a library routine that needs the same regs. */ ! 3393: if (regvec[i] != 0) ! 3394: reg_parm_seen = 1; ! 3395: ! 3396: if (reg_parm_seen) ! 3397: { ! 3398: valvec[i] = expand_expr (TREE_VALUE (p), 0, VOIDmode, 0); ! 3399: if (GET_CODE (valvec[i]) != MEM ! 3400: && ! CONSTANT_P (valvec[i]) ! 3401: && GET_CODE (valvec[i]) != CONST_DOUBLE) ! 3402: valvec[i] = force_reg (TYPE_MODE (type), valvec[i]); ! 3403: } ! 3404: ! 3405: /* Increment ARGS_SO_FAR, which has info about which arg-registers ! 3406: have been used, etc. */ ! 3407: ! 3408: FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type, ! 3409: i < n_named_args); ! 3410: ! 3411: /* Increment ARGS_SIZE, which is the size of all args so far. */ ! 3412: ! 3413: if (regvec[i] != 0 && partial[i] == 0) ! 3414: /* A register-arg doesn't count. */ ! 3415: ; ! 3416: else if (TYPE_MODE (type) != BLKmode) ! 3417: { ! 3418: register int size; ! 3419: ! 3420: size = GET_MODE_SIZE (TYPE_MODE (type)); ! 3421: /* Compute how much space the push instruction will push. ! 3422: On many machines, pushing a byte will advance the stack ! 3423: pointer by a halfword. */ ! 3424: #ifdef PUSH_ROUNDING ! 3425: size = PUSH_ROUNDING (size); 1.1 root 3426: #endif 1.1.1.2 ! root 3427: /* Compute how much space the argument should get: ! 3428: round up to a multiple of the alignment for arguments. */ ! 3429: arg_size[i].constant ! 3430: = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1) ! 3431: / (PARM_BOUNDARY / BITS_PER_UNIT)) ! 3432: * (PARM_BOUNDARY / BITS_PER_UNIT)); ! 3433: } ! 3434: else ! 3435: { ! 3436: register tree size = size_in_bytes (type); ! 3437: ! 3438: /* A nonscalar. Round its size up to a multiple ! 3439: of the allocation unit for arguments. */ ! 3440: ! 3441: /* Now round up to multiple of PARM_BOUNDARY bits, ! 3442: then express as number of bytes. */ ! 3443: ADD_PARM_SIZE (arg_size[i], ! 3444: convert_units (convert_units (size, BITS_PER_UNIT, PARM_BOUNDARY), ! 3445: PARM_BOUNDARY, BITS_PER_UNIT)); ! 3446: ! 3447: } ! 3448: /* If a part of the arg was put into registers, ! 3449: don't include that part in the amount pushed. */ ! 3450: arg_size[i].constant ! 3451: -= ((partial[i] * UNITS_PER_WORD) ! 3452: / (PARM_BOUNDARY / BITS_PER_UNIT) ! 3453: * (PARM_BOUNDARY / BITS_PER_UNIT)); ! 3454: ! 3455: args_size.constant += arg_size[i].constant; ! 3456: ! 3457: if (arg_size[i].var) ! 3458: { ! 3459: ADD_PARM_SIZE (args_size, arg_size[i].var); ! 3460: } ! 3461: } ! 3462: ! 3463: /* If we have no actual push instructions, or we need a variable ! 3464: amount of space, make space for all the args right now. ! 3465: In any case, round the needed size up to multiple of STACK_BOUNDARY. */ ! 3466: ! 3467: if (args_size.var != 0) ! 3468: { ! 3469: old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx); ! 3470: old_pending_adj = pending_stack_adjust; ! 3471: argblock = push_block (round_push (ARGS_SIZE_RTX (args_size))); ! 3472: } ! 3473: else if (args_size.constant != 0) ! 3474: { ! 3475: int needed = args_size.constant; ! 3476: ! 3477: #ifdef STACK_BOUNDARY ! 3478: needed = (needed + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES; ! 3479: args_size.constant = needed; ! 3480: #endif ! 3481: ! 3482: #ifndef PUSH_ROUNDING ! 3483: /* Try to reuse some or all of the pending_stack_adjust ! 3484: to get this space. Maybe we can avoid any pushing. */ ! 3485: if (needed > pending_stack_adjust) ! 3486: { ! 3487: needed -= pending_stack_adjust; ! 3488: pending_stack_adjust = 0; ! 3489: } ! 3490: else ! 3491: { ! 3492: pending_stack_adjust -= needed; ! 3493: needed = 0; ! 3494: } ! 3495: if (needed > 0) ! 3496: argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed)); ! 3497: #endif /* no PUSH_ROUNDING */ ! 3498: } ! 3499: ! 3500: /* Get the function to call, in the form of RTL. */ ! 3501: if (fndecl) ! 3502: /* Get a SYMBOL_REF rtx for the function address. */ ! 3503: funexp = XEXP (DECL_RTL (fndecl), 0); ! 3504: else ! 3505: /* Generate an rtx (probably a pseudo-register) for the address. */ ! 3506: funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 3507: ! 3508: /* Now actually compute the args, and push those that need pushing. */ ! 3509: 1.1 root 3510: for (i = 0; i < num_actuals; i++) 3511: { 3512: register tree p = argvec[i]; 3513: register tree pval = TREE_VALUE (p); 1.1.1.2 ! root 3514: int used = 0; 1.1 root 3515: 3516: /* Push the next argument. Note that it has already been converted 3517: if necessary to the type that the called function expects. */ 3518: 3519: if (TREE_CODE (pval) == ERROR_MARK) 3520: ; 1.1.1.2 ! root 3521: else if (regvec[i] != 0 && partial[i] == 0) ! 3522: { ! 3523: /* Being passed entirely in a register. */ ! 3524: if (valvec[i] != 0) ! 3525: { ! 3526: if (GET_MODE (valvec[i]) == BLKmode) ! 3527: move_block_to_reg (REGNO (regvec[i]), valvec[i], ! 3528: (int_size_in_bytes (TREE_TYPE (pval)) ! 3529: / UNITS_PER_WORD)); ! 3530: else ! 3531: emit_move_insn (regvec[i], valvec[i]); ! 3532: } ! 3533: else ! 3534: store_expr (pval, regvec[i], 0); ! 3535: ! 3536: /* Don't allow anything left on stack from computation ! 3537: of argument to alloca. */ ! 3538: if (may_be_alloca) ! 3539: do_pending_stack_adjust (); ! 3540: } 1.1 root 3541: else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode) 3542: { 1.1.1.2 ! root 3543: register int size; ! 3544: rtx tem; ! 3545: ! 3546: /* Argument is a scalar, not entirely passed in registers. ! 3547: (If part is passed in registers, partial[I] says how much ! 3548: and emit_push_insn will take care of putting it there.) 1.1 root 3549: 3550: Push it, and if its size is less than the 3551: amount of space allocated to it, 3552: also bump stack pointer by the additional space. 3553: Note that in C the default argument promotions 3554: will prevent such mismatches. */ 3555: 3556: used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval))); 3557: /* Compute how much space the push instruction will push. 3558: On many machines, pushing a byte will advance the stack 3559: pointer by a halfword. */ 1.1.1.2 ! root 3560: #ifdef PUSH_ROUNDING 1.1 root 3561: size = PUSH_ROUNDING (size); 1.1.1.2 ! root 3562: #endif 1.1 root 3563: /* Compute how much space the argument should get: 3564: round up to a multiple of the alignment for arguments. */ 3565: used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1) 3566: / (PARM_BOUNDARY / BITS_PER_UNIT)) 3567: * (PARM_BOUNDARY / BITS_PER_UNIT)); 3568: 1.1.1.2 ! root 3569: tem = valvec[i]; ! 3570: if (tem == 0) ! 3571: tem = expand_expr (pval, 0, VOIDmode, 0); ! 3572: ! 3573: /* Don't allow anything left on stack from computation ! 3574: of argument to alloca. */ ! 3575: if (may_be_alloca) ! 3576: do_pending_stack_adjust (); ! 3577: ! 3578: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), 0, 0, ! 3579: partial[i], regvec[i], used - size, ! 3580: argblock, ARGS_SIZE_RTX (arg_offset[i])); 1.1 root 3581: } 3582: else 3583: { 1.1.1.2 ! root 3584: register rtx tem ! 3585: = valvec[i] ? valvec[i] : expand_expr (pval, 0, VOIDmode, 0); 1.1 root 3586: register int excess; 1.1.1.2 ! root 3587: rtx size_rtx; 1.1 root 3588: 1.1.1.2 ! root 3589: /* Pushing a nonscalar. ! 3590: If part is passed in registers, partial[I] says how much ! 3591: and emit_push_insn will take care of putting it there. */ 1.1 root 3592: 1.1.1.2 ! root 3593: /* Round its size up to a multiple ! 3594: of the allocation unit for arguments. */ 1.1 root 3595: 1.1.1.2 ! root 3596: if (arg_size[i].var != 0) ! 3597: { ! 3598: excess = 0; ! 3599: size_rtx = ARGS_SIZE_RTX (arg_size[i]); ! 3600: } ! 3601: else ! 3602: { ! 3603: register tree size = size_in_bytes (TREE_TYPE (pval)); ! 3604: /* PUSH_ROUNDING has no effect on us, because ! 3605: emit_push_insn for BLKmode is careful to avoid it. */ ! 3606: excess = arg_size[i].constant - TREE_INT_CST_LOW (size); ! 3607: size_rtx = expand_expr (size, 0, VOIDmode, 0); ! 3608: } 1.1 root 3609: 1.1.1.2 ! root 3610: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), size_rtx, ! 3611: TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT, ! 3612: partial[i], regvec[i], excess, argblock, ! 3613: ARGS_SIZE_RTX (arg_offset[i])); ! 3614: } 1.1 root 3615: 1.1.1.2 ! root 3616: /* Account for the stack space thus used. */ 1.1 root 3617: 3618: 1.1.1.2 ! root 3619: current_args_size += arg_size[i].constant; ! 3620: if (arg_size[i].var) ! 3621: current_args_size += 1; 1.1 root 3622: } 3623: 3624: /* Perform postincrements before actually calling the function. */ 3625: emit_queue (); 3626: 3627: /* Pass the function the address in which to return a structure value. */ 3628: if (structure_value_addr) 1.1.1.2 ! root 3629: emit_move_insn (struct_value_rtx, structure_value_addr); ! 3630: ! 3631: /* All arguments and registers used for the call must be set up by now! */ 1.1 root 3632: 1.1.1.2 ! root 3633: /* ??? Other languages need a nontrivial second argument (static chain). */ ! 3634: funexp = prepare_call_address (funexp, 0); ! 3635: ! 3636: /* Mark all register-parms as living through the call. ! 3637: ??? This is not quite correct, since it doesn't indicate ! 3638: that they are in use immediately before the call insn. ! 3639: Currently that doesn't matter since explicitly-used regs ! 3640: won't be used for reloading. But if the reloader becomes smarter, ! 3641: this will have to change somehow. */ ! 3642: for (i = 0; i < num_actuals; i++) ! 3643: if (regvec[i] != 0) ! 3644: { ! 3645: if (partial[i] > 0) ! 3646: use_regs (REGNO (regvec[i]), partial[i]); ! 3647: else if (GET_MODE (regvec[i]) == BLKmode) ! 3648: use_regs (REGNO (regvec[i]), ! 3649: (int_size_in_bytes (TREE_TYPE (TREE_VALUE (argvec[i]))) ! 3650: / UNITS_PER_WORD)); ! 3651: else ! 3652: emit_insn (gen_rtx (USE, VOIDmode, regvec[i])); ! 3653: } ! 3654: ! 3655: if (structure_value_addr) ! 3656: emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx)); ! 3657: ! 3658: /* Figure out the register where the value, if any, will come back. */ ! 3659: valreg = 0; ! 3660: if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode ! 3661: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode) ! 3662: valreg = hard_function_value (TREE_TYPE (exp), fndecl); ! 3663: ! 3664: /* Generate the actual call instruction. */ ! 3665: emit_call_1 (funexp, funtype, args_size.constant, ! 3666: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), ! 3667: valreg, old_current_args_size); 1.1 root 3668: 3669: /* ??? Nothing has been done here to record control flow 3670: when contained functions can do nonlocal gotos. */ 3671: 1.1.1.2 ! root 3672: /* For calls to `setjmp', etc., inform flow.c it should complain ! 3673: if nonvolatile values are live. */ ! 3674: ! 3675: if (is_setjmp) ! 3676: emit_note (IDENTIFIER_POINTER (DECL_NAME (fndecl)), NOTE_INSN_SETJMP); ! 3677: ! 3678: /* If size of args is variable, restore saved stack-pointer value. */ ! 3679: ! 3680: if (args_size.var != 0) ! 3681: { ! 3682: emit_move_insn (stack_pointer_rtx, old_stack_level); ! 3683: pending_stack_adjust = old_pending_adj; ! 3684: } ! 3685: 1.1 root 3686: /* If value type not void, return an rtx for the value. */ 3687: 1.1.1.2 ! root 3688: if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode ! 3689: || ignore) 1.1 root 3690: return 0; 3691: 3692: if (structure_value_addr) 3693: { 3694: if (target) 3695: return target; 1.1.1.2 ! root 3696: return gen_rtx (MEM, BLKmode, ! 3697: memory_address (BLKmode, structure_value_addr)); 1.1 root 3698: } 1.1.1.2 ! root 3699: ! 3700: if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))) 1.1 root 3701: { 1.1.1.2 ! root 3702: if (!rtx_equal_p (target, valreg)) ! 3703: emit_move_insn (target, valreg); ! 3704: else ! 3705: /* This tells expand_inline_function to copy valreg to its target. */ ! 3706: emit_insn (gen_rtx (USE, VOIDmode, valreg)); 1.1 root 3707: return target; 3708: } 1.1.1.2 ! root 3709: return copy_to_reg (valreg); 1.1 root 3710: } 3711: 3712: /* Expand conditional expressions. */ 3713: 3714: /* Generate code to evaluate EXP and jump to LABEL if the value is zero. 3715: LABEL is an rtx of code CODE_LABEL, in this function and all the 3716: functions here. */ 3717: 1.1.1.2 ! root 3718: void 1.1 root 3719: jumpifnot (exp, label) 3720: tree exp; 3721: rtx label; 3722: { 3723: do_jump (exp, label, 0); 3724: } 3725: 3726: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */ 3727: 1.1.1.2 ! root 3728: void 1.1 root 3729: jumpif (exp, label) 3730: tree exp; 3731: rtx label; 3732: { 3733: do_jump (exp, 0, label); 3734: } 3735: 3736: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if 3737: the result is zero, or IF_TRUE_LABEL if the result is one. 3738: Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero, 3739: meaning fall through in that case. 3740: 3741: This function is responsible for optimizing cases such as 3742: &&, || and comparison operators in EXP. */ 3743: 1.1.1.2 ! root 3744: void 1.1 root 3745: do_jump (exp, if_false_label, if_true_label) 3746: tree exp; 3747: rtx if_false_label, if_true_label; 3748: { 3749: register enum tree_code code = TREE_CODE (exp); 3750: /* Some cases need to create a label to jump to 3751: in order to properly fall through. 3752: These cases set DROP_THROUGH_LABEL nonzero. */ 3753: rtx drop_through_label = 0; 3754: rtx temp; 3755: rtx comparison = 0; 3756: 3757: emit_queue (); 3758: 3759: switch (code) 3760: { 3761: case ERROR_MARK: 3762: break; 3763: 3764: case INTEGER_CST: 3765: temp = integer_zerop (exp) ? if_false_label : if_true_label; 3766: if (temp) 3767: emit_jump (temp); 3768: break; 3769: 3770: case ADDR_EXPR: 3771: /* The address of something can never be zero. */ 3772: if (if_true_label) 3773: emit_jump (if_true_label); 3774: break; 1.1.1.2 ! root 3775: 1.1 root 3776: case NOP_EXPR: 3777: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); 3778: break; 3779: 3780: case TRUTH_NOT_EXPR: 3781: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); 3782: break; 3783: 3784: case TRUTH_ANDIF_EXPR: 3785: if (if_false_label == 0) 3786: if_false_label = drop_through_label = gen_label_rtx (); 3787: do_jump (TREE_OPERAND (exp, 0), if_false_label, 0); 3788: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 3789: break; 3790: 3791: case TRUTH_ORIF_EXPR: 3792: if (if_true_label == 0) 3793: if_true_label = drop_through_label = gen_label_rtx (); 3794: do_jump (TREE_OPERAND (exp, 0), 0, if_true_label); 3795: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 3796: break; 3797: 3798: case COMPOUND_EXPR: 1.1.1.2 ! root 3799: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); 1.1 root 3800: emit_queue (); 3801: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); 3802: break; 3803: 3804: case COND_EXPR: 3805: { 3806: register rtx label1 = gen_label_rtx (); 3807: drop_through_label = gen_label_rtx (); 3808: do_jump (TREE_OPERAND (exp, 0), label1, 0); 3809: /* Now the THEN-expression. */ 3810: do_jump (TREE_OPERAND (exp, 1), 3811: if_false_label ? if_false_label : drop_through_label, 3812: if_true_label ? if_true_label : drop_through_label); 3813: emit_label (label1); 3814: /* Now the ELSE-expression. */ 3815: do_jump (TREE_OPERAND (exp, 2), 3816: if_false_label ? if_false_label : drop_through_label, 3817: if_true_label ? if_true_label : drop_through_label); 3818: } 3819: break; 3820: 3821: case EQ_EXPR: 3822: comparison = compare (exp, EQ, EQ, EQ, EQ); 3823: break; 3824: 3825: case NE_EXPR: 3826: comparison = compare (exp, NE, NE, NE, NE); 3827: break; 3828: 3829: case LT_EXPR: 3830: comparison = compare (exp, LT, LTU, GT, GTU); 3831: break; 3832: 3833: case LE_EXPR: 3834: comparison = compare (exp, LE, LEU, GE, GEU); 3835: break; 3836: 3837: case GT_EXPR: 3838: comparison = compare (exp, GT, GTU, LT, LTU); 3839: break; 3840: 3841: case GE_EXPR: 3842: comparison = compare (exp, GE, GEU, LE, LEU); 3843: break; 3844: 3845: default: 3846: temp = expand_expr (exp, 0, VOIDmode, 0); 1.1.1.2 ! root 3847: /* Copy to register to avoid generating bad insns by cse ! 3848: from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */ ! 3849: if (!cse_not_expected && GET_CODE (temp) == MEM) ! 3850: temp = copy_to_reg (temp); 1.1 root 3851: do_pending_stack_adjust (); 1.1.1.2 ! root 3852: { ! 3853: rtx zero; ! 3854: if (GET_MODE (temp) == SFmode) ! 3855: zero = fconst0_rtx; ! 3856: else if (GET_MODE (temp) == DFmode) ! 3857: zero = dconst0_rtx; ! 3858: else ! 3859: zero = const0_rtx; 1.1 root 3860: 1.1.1.2 ! root 3861: if (GET_CODE (temp) == CONST_INT) ! 3862: comparison = compare_constants (NE, 0, ! 3863: INTVAL (temp), 0, BITS_PER_WORD); ! 3864: else if (GET_MODE (temp) != VOIDmode) ! 3865: comparison = compare1 (temp, zero, NE, NE, 0, GET_MODE (temp)); ! 3866: else ! 3867: abort (); ! 3868: } 1.1 root 3869: } 3870: 1.1.1.2 ! root 3871: /* Do any postincrements in the expression that was tested. */ ! 3872: emit_queue (); ! 3873: 1.1 root 3874: /* If COMPARISON is nonzero here, it is an rtx that can be substituted 3875: straight into a conditional jump instruction as the jump condition. 3876: Otherwise, all the work has been done already. */ 3877: 1.1.1.2 ! root 3878: if (comparison == const1_rtx) ! 3879: { ! 3880: if (if_true_label) ! 3881: emit_jump (if_true_label); ! 3882: } ! 3883: else if (comparison == const0_rtx) ! 3884: { ! 3885: if (if_false_label) ! 3886: emit_jump (if_false_label); ! 3887: } ! 3888: else if (comparison) ! 3889: { ! 3890: if (if_true_label) ! 3891: { ! 3892: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, ! 3893: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison, ! 3894: gen_rtx (LABEL_REF, VOIDmode, ! 3895: if_true_label), ! 3896: pc_rtx))); ! 3897: if (if_false_label) ! 3898: emit_jump (if_false_label); ! 3899: } ! 3900: else if (if_false_label) ! 3901: { ! 3902: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, ! 3903: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison, ! 3904: pc_rtx, ! 3905: gen_rtx (LABEL_REF, VOIDmode, ! 3906: if_false_label)))); ! 3907: } ! 3908: } 1.1 root 3909: 3910: if (drop_through_label) 3911: emit_label (drop_through_label); 3912: } 3913: 1.1.1.2 ! root 3914: /* Compare two integer constant rtx's, OP0 and OP1. ! 3915: The comparison operation is OPERATION. ! 3916: Return an rtx representing the value 1 or 0. ! 3917: WIDTH is the width in bits that is significant. */ ! 3918: ! 3919: static rtx ! 3920: compare_constants (operation, unsignedp, op0, op1, width) ! 3921: enum rtx_code operation; ! 3922: int unsignedp; ! 3923: int op0, op1; ! 3924: int width; ! 3925: { ! 3926: int val; ! 3927: ! 3928: /* Sign-extend or zero-extend the operands to a full word ! 3929: from an initial width of WIDTH bits. */ ! 3930: if (width < HOST_BITS_PER_INT) ! 3931: { ! 3932: op0 &= (1 << width) - 1; ! 3933: op1 &= (1 << width) - 1; ! 3934: ! 3935: if (! unsignedp) ! 3936: { ! 3937: if (op0 & (1 << (width - 1))) ! 3938: op0 |= ((-1) << width); ! 3939: if (op1 & (1 << (width - 1))) ! 3940: op1 |= ((-1) << width); ! 3941: } ! 3942: } ! 3943: ! 3944: switch (operation) ! 3945: { ! 3946: case EQ: ! 3947: val = op0 == op1; ! 3948: break; ! 3949: ! 3950: case NE: ! 3951: val = op0 != op1; ! 3952: break; ! 3953: ! 3954: case GT: ! 3955: case GTU: ! 3956: val = op0 > op1; ! 3957: break; ! 3958: ! 3959: case LT: ! 3960: case LTU: ! 3961: val = op0 < op1; ! 3962: break; ! 3963: ! 3964: case GE: ! 3965: case GEU: ! 3966: val = op0 >= op1; ! 3967: break; ! 3968: ! 3969: case LE: ! 3970: case LEU: ! 3971: val = op0 <= op1; ! 3972: } ! 3973: ! 3974: return val ? const1_rtx : const0_rtx; ! 3975: } ! 3976: 1.1 root 3977: /* Generate code for a comparison expression EXP 3978: (including code to compute the values to be compared) 3979: and set (CC0) according to the result. 3980: SIGNED_FORWARD should be the rtx operation for this comparison for 3981: signed data; UNSIGNED_FORWARD, likewise for use if data is unsigned. 3982: SIGNED_REVERSE and UNSIGNED_REVERSE are used if it is desirable 3983: to interchange the operands for the compare instruction. 3984: 3985: We force a stack adjustment unless there are currently 3986: things pushed on the stack that aren't yet used. */ 3987: 3988: static rtx 3989: compare (exp, signed_forward, unsigned_forward, 3990: signed_reverse, unsigned_reverse) 3991: register tree exp; 3992: enum rtx_code signed_forward, unsigned_forward; 3993: enum rtx_code signed_reverse, unsigned_reverse; 3994: { 1.1.1.2 ! root 3995: 1.1 root 3996: register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); 3997: register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); 3998: register enum machine_mode mode = GET_MODE (op0); 3999: int unsignedp; 4000: 4001: /* If one operand is 0, make it the second one. */ 4002: 4003: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx) 4004: { 4005: rtx tem = op0; 4006: op0 = op1; 4007: op1 = tem; 4008: signed_forward = signed_reverse; 4009: unsigned_forward = unsigned_reverse; 4010: } 4011: 1.1.1.2 ! root 4012: if (flag_force_mem) 1.1 root 4013: { 4014: op0 = force_not_mem (op0); 4015: op1 = force_not_mem (op1); 4016: } 4017: 4018: do_pending_stack_adjust (); 4019: 1.1.1.2 ! root 4020: unsignedp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) ! 4021: || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))); ! 4022: ! 4023: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! 4024: return compare_constants (signed_forward, unsignedp, ! 4025: INTVAL (op0), INTVAL (op1), ! 4026: GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))); 1.1 root 4027: 4028: emit_cmp_insn (op0, op1, 4029: (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0, 4030: unsignedp); 4031: 4032: return gen_rtx ((unsignedp ? unsigned_forward : signed_forward), 4033: VOIDmode, cc0_rtx, const0_rtx); 4034: } 4035: 4036: /* Like compare but expects the values to compare as two rtx's. 4037: The decision as to signed or unsigned comparison must be made by the caller. 4038: BLKmode is not allowed. */ 4039: 4040: static rtx 1.1.1.2 ! root 4041: compare1 (op0, op1, forward_op, reverse_op, unsignedp, mode) 1.1 root 4042: register rtx op0, op1; 4043: enum rtx_code forward_op, reverse_op; 4044: int unsignedp; 1.1.1.2 ! root 4045: enum machine_mode mode; 1.1 root 4046: { 4047: /* If one operand is 0, make it the second one. */ 4048: 4049: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx) 4050: { 4051: rtx tem = op0; 4052: op0 = op1; 4053: op1 = tem; 4054: forward_op = reverse_op; 4055: } 4056: 1.1.1.2 ! root 4057: if (flag_force_mem) 1.1 root 4058: { 4059: op0 = force_not_mem (op0); 4060: op1 = force_not_mem (op1); 4061: } 4062: 4063: do_pending_stack_adjust (); 4064: 1.1.1.2 ! root 4065: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! 4066: return compare_constants (forward_op, unsignedp, ! 4067: INTVAL (op0), INTVAL (op1), ! 4068: GET_MODE_BITSIZE (mode)); ! 4069: 1.1 root 4070: emit_cmp_insn (op0, op1, 0, unsignedp); 4071: 4072: return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx); 4073: } 4074: 4075: /* Generate code to calculate EXP using a store-flag instruction 4076: and return an rtx for the result. 4077: If TARGET is nonzero, store the result there if convenient. 4078: 4079: Return zero if there is no suitable set-flag instruction 4080: available on this machine. */ 4081: 4082: static rtx 1.1.1.2 ! root 4083: do_store_flag (exp, target, mode) 1.1 root 4084: tree exp; 4085: rtx target; 1.1.1.2 ! root 4086: enum machine_mode mode; 1.1 root 4087: { 4088: register enum tree_code code = TREE_CODE (exp); 4089: register rtx comparison = 0; 1.1.1.2 ! root 4090: enum machine_mode compare_mode; 1.1 root 4091: 4092: switch (code) 4093: { 1.1.1.2 ! root 4094: #ifdef HAVE_seq 1.1 root 4095: case EQ_EXPR: 1.1.1.2 ! root 4096: if (HAVE_seq) ! 4097: { ! 4098: comparison = compare (exp, EQ, EQ, EQ, EQ); ! 4099: compare_mode = insn_operand_mode[(int) CODE_FOR_seq][0]; ! 4100: } 1.1 root 4101: break; 4102: #endif 4103: 1.1.1.2 ! root 4104: #ifdef HAVE_sne 1.1 root 4105: case NE_EXPR: 1.1.1.2 ! root 4106: if (HAVE_sne) ! 4107: { ! 4108: comparison = compare (exp, NE, NE, NE, NE); ! 4109: compare_mode = insn_operand_mode[(int) CODE_FOR_sne][0]; ! 4110: } 1.1 root 4111: break; 4112: #endif 4113: 1.1.1.2 ! root 4114: #if defined (HAVE_slt) && defined (HAVE_sltu) && defined (HAVE_sgt) && defined (HAVE_sgtu) 1.1 root 4115: case LT_EXPR: 1.1.1.2 ! root 4116: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu) ! 4117: { ! 4118: comparison = compare (exp, LT, LTU, GT, GTU); ! 4119: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0]; ! 4120: } 1.1 root 4121: break; 4122: 4123: case GT_EXPR: 1.1.1.2 ! root 4124: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu) ! 4125: { ! 4126: comparison = compare (exp, GT, GTU, LT, LTU); ! 4127: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0]; ! 4128: } 1.1 root 4129: break; 4130: #endif 4131: 1.1.1.2 ! root 4132: #if defined (HAVE_sle) && defined (HAVE_sleu) && defined (HAVE_sge) && defined (HAVE_sgeu) 1.1 root 4133: case LE_EXPR: 1.1.1.2 ! root 4134: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu) ! 4135: { ! 4136: comparison = compare (exp, LE, LEU, GE, GEU); ! 4137: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0]; ! 4138: } 1.1 root 4139: break; 4140: 4141: case GE_EXPR: 1.1.1.2 ! root 4142: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu) ! 4143: { ! 4144: comparison = compare (exp, GE, GEU, LE, LEU); ! 4145: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0]; ! 4146: } 1.1 root 4147: break; 4148: #endif 4149: } 4150: if (comparison == 0) 4151: return 0; 4152: 1.1.1.2 ! root 4153: if (target == 0 || GET_MODE (target) != mode ! 4154: || (mode != compare_mode && GET_CODE (target) != REG)) ! 4155: target = gen_reg_rtx (mode); ! 4156: ! 4157: /* Store the comparison in its proper mode. */ ! 4158: if (GET_MODE (target) != compare_mode) ! 4159: emit_insn (gen_rtx (SET, VOIDmode, ! 4160: gen_rtx (SUBREG, compare_mode, target, 0), ! 4161: comparison)); ! 4162: else ! 4163: emit_insn (gen_rtx (SET, VOIDmode, target, comparison)); ! 4164: ! 4165: #if STORE_FLAG_VALUE != 1 ! 4166: expand_bit_and (mode, target, const1_rtx, target); ! 4167: #endif 1.1 root 4168: return target; 4169: } 4170: 4171: /* Generate a tablejump instruction (used for switch statements). */ 4172: 4173: #ifdef HAVE_tablejump 4174: 4175: /* INDEX is the value being switched on, with the lowest value 4176: in the table already subtracted. 4177: RANGE is the length of the jump table. 4178: TABLE_LABEL is a CODE_LABEL rtx for the table itself. 1.1.1.2 ! root 4179: 1.1 root 4180: DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the 4181: index value is out of range. */ 4182: 4183: void 4184: do_tablejump (index, range, table_label, default_label) 4185: rtx index, range, table_label, default_label; 4186: { 4187: register rtx temp; 4188: 4189: emit_cmp_insn (range, index, 0); 1.1.1.2 ! root 4190: emit_jump_insn (gen_bltu (default_label)); 1.1 root 4191: index = memory_address (CASE_VECTOR_MODE, 4192: gen_rtx (PLUS, Pmode, 4193: gen_rtx (MULT, Pmode, index, 4194: gen_rtx (CONST_INT, VOIDmode, 1.1.1.2 ! root 4195: GET_MODE_SIZE (CASE_VECTOR_MODE))), ! 4196: gen_rtx (LABEL_REF, VOIDmode, table_label))); 1.1 root 4197: temp = gen_reg_rtx (CASE_VECTOR_MODE); 4198: convert_move (temp, gen_rtx (MEM, CASE_VECTOR_MODE, index), 0); 4199: 1.1.1.2 ! root 4200: emit_jump_insn (gen_tablejump (temp, table_label)); 1.1 root 4201: } 4202: 1.1.1.2 ! root 4203: #endif /* HAVE_tablejump */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.