|
|
1.1 ! root 1: /* Convert tree expression to rtl instructions, for GNU compiler. ! 2: Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "machmode.h" ! 23: #include "rtl.h" ! 24: #include "tree.h" ! 25: #include "obstack.h" ! 26: #include "flags.h" ! 27: #include "function.h" ! 28: #include "insn-flags.h" ! 29: #include "insn-codes.h" ! 30: #include "expr.h" ! 31: #include "insn-config.h" ! 32: #include "recog.h" ! 33: #include "output.h" ! 34: #include "typeclass.h" ! 35: ! 36: #include "bytecode.h" ! 37: #include "bc-opcode.h" ! 38: #include "bc-typecd.h" ! 39: #include "bc-optab.h" ! 40: #include "bc-emit.h" ! 41: ! 42: ! 43: #define CEIL(x,y) (((x) + (y) - 1) / (y)) ! 44: ! 45: /* Decide whether a function's arguments should be processed ! 46: from first to last or from last to first. ! 47: ! 48: They should if the stack and args grow in opposite directions, but ! 49: only if we have push insns. */ ! 50: ! 51: #ifdef PUSH_ROUNDING ! 52: ! 53: #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD) ! 54: #define PUSH_ARGS_REVERSED /* If it's last to first */ ! 55: #endif ! 56: ! 57: #endif ! 58: ! 59: #ifndef STACK_PUSH_CODE ! 60: #ifdef STACK_GROWS_DOWNWARD ! 61: #define STACK_PUSH_CODE PRE_DEC ! 62: #else ! 63: #define STACK_PUSH_CODE PRE_INC ! 64: #endif ! 65: #endif ! 66: ! 67: /* Like STACK_BOUNDARY but in units of bytes, not bits. */ ! 68: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT) ! 69: ! 70: /* If this is nonzero, we do not bother generating VOLATILE ! 71: around volatile memory references, and we are willing to ! 72: output indirect addresses. If cse is to follow, we reject ! 73: indirect addresses so a useful potential cse is generated; ! 74: if it is used only once, instruction combination will produce ! 75: the same indirect address eventually. */ ! 76: int cse_not_expected; ! 77: ! 78: /* Nonzero to generate code for all the subroutines within an ! 79: expression before generating the upper levels of the expression. ! 80: Nowadays this is never zero. */ ! 81: int do_preexpand_calls = 1; ! 82: ! 83: /* Number of units that we should eventually pop off the stack. ! 84: These are the arguments to function calls that have already returned. */ ! 85: int pending_stack_adjust; ! 86: ! 87: /* Nonzero means stack pops must not be deferred, and deferred stack ! 88: pops must not be output. It is nonzero inside a function call, ! 89: inside a conditional expression, inside a statement expression, ! 90: and in other cases as well. */ ! 91: int inhibit_defer_pop; ! 92: ! 93: /* A list of all cleanups which belong to the arguments of ! 94: function calls being expanded by expand_call. */ ! 95: tree cleanups_this_call; ! 96: ! 97: /* Nonzero means __builtin_saveregs has already been done in this function. ! 98: The value is the pseudoreg containing the value __builtin_saveregs ! 99: returned. */ ! 100: static rtx saveregs_value; ! 101: ! 102: /* Similarly for __builtin_apply_args. */ ! 103: static rtx apply_args_value; ! 104: ! 105: /* This structure is used by move_by_pieces to describe the move to ! 106: be performed. */ ! 107: ! 108: struct move_by_pieces ! 109: { ! 110: rtx to; ! 111: rtx to_addr; ! 112: int autinc_to; ! 113: int explicit_inc_to; ! 114: rtx from; ! 115: rtx from_addr; ! 116: int autinc_from; ! 117: int explicit_inc_from; ! 118: int len; ! 119: int offset; ! 120: int reverse; ! 121: }; ! 122: ! 123: /* Used to generate bytecodes: keep track of size of local variables, ! 124: as well as depth of arithmetic stack. (Notice that variables are ! 125: stored on the machine's stack, not the arithmetic stack.) */ ! 126: ! 127: int local_vars_size; ! 128: extern int stack_depth; ! 129: extern int max_stack_depth; ! 130: extern struct obstack permanent_obstack; ! 131: ! 132: ! 133: static rtx enqueue_insn PROTO((rtx, rtx)); ! 134: static int queued_subexp_p PROTO((rtx)); ! 135: static void init_queue PROTO((void)); ! 136: static void move_by_pieces PROTO((rtx, rtx, int, int)); ! 137: static int move_by_pieces_ninsns PROTO((unsigned int, int)); ! 138: static void move_by_pieces_1 PROTO((rtx (*) (), enum machine_mode, ! 139: struct move_by_pieces *)); ! 140: static void group_insns PROTO((rtx)); ! 141: static void store_constructor PROTO((tree, rtx)); ! 142: static rtx store_field PROTO((rtx, int, int, enum machine_mode, tree, ! 143: enum machine_mode, int, int, int)); ! 144: static tree save_noncopied_parts PROTO((tree, tree)); ! 145: static tree init_noncopied_parts PROTO((tree, tree)); ! 146: static int safe_from_p PROTO((rtx, tree)); ! 147: static int fixed_type_p PROTO((tree)); ! 148: static int get_pointer_alignment PROTO((tree, unsigned)); ! 149: static tree string_constant PROTO((tree, tree *)); ! 150: static tree c_strlen PROTO((tree)); ! 151: static rtx expand_builtin PROTO((tree, rtx, rtx, enum machine_mode, int)); ! 152: static int apply_args_size PROTO((void)); ! 153: static int apply_result_size PROTO((void)); ! 154: static rtx result_vector PROTO((int, rtx)); ! 155: static rtx expand_builtin_apply_args PROTO((void)); ! 156: static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); ! 157: static void expand_builtin_return PROTO((rtx)); ! 158: static rtx expand_increment PROTO((tree, int)); ! 159: rtx bc_expand_increment PROTO((struct increment_operator *, tree)); ! 160: tree bc_runtime_type_code PROTO((tree)); ! 161: rtx bc_allocate_local PROTO((int, int)); ! 162: void bc_store_memory PROTO((tree, tree)); ! 163: tree bc_expand_component_address PROTO((tree)); ! 164: tree bc_expand_address PROTO((tree)); ! 165: void bc_expand_constructor PROTO((tree)); ! 166: void bc_adjust_stack PROTO((int)); ! 167: tree bc_canonicalize_array_ref PROTO((tree)); ! 168: void bc_load_memory PROTO((tree, tree)); ! 169: void bc_load_externaddr PROTO((rtx)); ! 170: void bc_load_externaddr_id PROTO((tree, int)); ! 171: void bc_load_localaddr PROTO((rtx)); ! 172: void bc_load_parmaddr PROTO((rtx)); ! 173: static void preexpand_calls PROTO((tree)); ! 174: static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx)); ! 175: static void do_jump_by_parts_greater_rtx PROTO((enum machine_mode, int, rtx, rtx, rtx, rtx)); ! 176: static void do_jump_by_parts_equality PROTO((tree, rtx, rtx)); ! 177: static void do_jump_by_parts_equality_rtx PROTO((rtx, rtx, rtx)); ! 178: static void do_jump_for_compare PROTO((rtx, rtx, rtx)); ! 179: static rtx compare PROTO((tree, enum rtx_code, enum rtx_code)); ! 180: static rtx do_store_flag PROTO((tree, rtx, enum machine_mode, int)); ! 181: ! 182: /* Record for each mode whether we can move a register directly to or ! 183: from an object of that mode in memory. If we can't, we won't try ! 184: to use that mode directly when accessing a field of that mode. */ ! 185: ! 186: static char direct_load[NUM_MACHINE_MODES]; ! 187: static char direct_store[NUM_MACHINE_MODES]; ! 188: ! 189: /* MOVE_RATIO is the number of move instructions that is better than ! 190: a block move. */ ! 191: ! 192: #ifndef MOVE_RATIO ! 193: #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti) ! 194: #define MOVE_RATIO 2 ! 195: #else ! 196: /* A value of around 6 would minimize code size; infinity would minimize ! 197: execution time. */ ! 198: #define MOVE_RATIO 15 ! 199: #endif ! 200: #endif ! 201: ! 202: /* This array records the insn_code of insns to perform block moves. */ ! 203: enum insn_code movstr_optab[NUM_MACHINE_MODES]; ! 204: ! 205: /* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */ ! 206: ! 207: #ifndef SLOW_UNALIGNED_ACCESS ! 208: #define SLOW_UNALIGNED_ACCESS 0 ! 209: #endif ! 210: ! 211: /* Register mappings for target machines without register windows. */ ! 212: #ifndef INCOMING_REGNO ! 213: #define INCOMING_REGNO(OUT) (OUT) ! 214: #endif ! 215: #ifndef OUTGOING_REGNO ! 216: #define OUTGOING_REGNO(IN) (IN) ! 217: #endif ! 218: ! 219: /* Maps used to convert modes to const, load, and store bytecodes. */ ! 220: enum bytecode_opcode mode_to_const_map[MAX_MACHINE_MODE]; ! 221: enum bytecode_opcode mode_to_load_map[MAX_MACHINE_MODE]; ! 222: enum bytecode_opcode mode_to_store_map[MAX_MACHINE_MODE]; ! 223: ! 224: /* Initialize maps used to convert modes to const, load, and store ! 225: bytecodes. */ ! 226: void ! 227: bc_init_mode_to_opcode_maps () ! 228: { ! 229: int mode; ! 230: ! 231: for (mode = 0; mode < (int) MAX_MACHINE_MODE; mode++) ! 232: mode_to_const_map[mode] = ! 233: mode_to_load_map[mode] = ! 234: mode_to_store_map[mode] = neverneverland; ! 235: ! 236: #define DEF_MODEMAP(SYM, CODE, UCODE, CONST, LOAD, STORE) \ ! 237: mode_to_const_map[(int) SYM] = CONST; \ ! 238: mode_to_load_map[(int) SYM] = LOAD; \ ! 239: mode_to_store_map[(int) SYM] = STORE; ! 240: ! 241: #include "modemap.def" ! 242: #undef DEF_MODEMAP ! 243: } ! 244: ! 245: /* This is run once per compilation to set up which modes can be used ! 246: directly in memory and to initialize the block move optab. */ ! 247: ! 248: void ! 249: init_expr_once () ! 250: { ! 251: rtx insn, pat; ! 252: enum machine_mode mode; ! 253: /* Try indexing by frame ptr and try by stack ptr. ! 254: It is known that on the Convex the stack ptr isn't a valid index. ! 255: With luck, one or the other is valid on any machine. */ ! 256: rtx mem = gen_rtx (MEM, VOIDmode, stack_pointer_rtx); ! 257: rtx mem1 = gen_rtx (MEM, VOIDmode, frame_pointer_rtx); ! 258: ! 259: start_sequence (); ! 260: insn = emit_insn (gen_rtx (SET, 0, 0)); ! 261: pat = PATTERN (insn); ! 262: ! 263: for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES; ! 264: mode = (enum machine_mode) ((int) mode + 1)) ! 265: { ! 266: int regno; ! 267: rtx reg; ! 268: int num_clobbers; ! 269: ! 270: direct_load[(int) mode] = direct_store[(int) mode] = 0; ! 271: PUT_MODE (mem, mode); ! 272: PUT_MODE (mem1, mode); ! 273: ! 274: /* See if there is some register that can be used in this mode and ! 275: directly loaded or stored from memory. */ ! 276: ! 277: if (mode != VOIDmode && mode != BLKmode) ! 278: for (regno = 0; regno < FIRST_PSEUDO_REGISTER ! 279: && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0); ! 280: regno++) ! 281: { ! 282: if (! HARD_REGNO_MODE_OK (regno, mode)) ! 283: continue; ! 284: ! 285: reg = gen_rtx (REG, mode, regno); ! 286: ! 287: SET_SRC (pat) = mem; ! 288: SET_DEST (pat) = reg; ! 289: if (recog (pat, insn, &num_clobbers) >= 0) ! 290: direct_load[(int) mode] = 1; ! 291: ! 292: SET_SRC (pat) = mem1; ! 293: SET_DEST (pat) = reg; ! 294: if (recog (pat, insn, &num_clobbers) >= 0) ! 295: direct_load[(int) mode] = 1; ! 296: ! 297: SET_SRC (pat) = reg; ! 298: SET_DEST (pat) = mem; ! 299: if (recog (pat, insn, &num_clobbers) >= 0) ! 300: direct_store[(int) mode] = 1; ! 301: ! 302: SET_SRC (pat) = reg; ! 303: SET_DEST (pat) = mem1; ! 304: if (recog (pat, insn, &num_clobbers) >= 0) ! 305: direct_store[(int) mode] = 1; ! 306: } ! 307: } ! 308: ! 309: end_sequence (); ! 310: } ! 311: ! 312: /* This is run at the start of compiling a function. */ ! 313: ! 314: void ! 315: init_expr () ! 316: { ! 317: init_queue (); ! 318: ! 319: pending_stack_adjust = 0; ! 320: inhibit_defer_pop = 0; ! 321: cleanups_this_call = 0; ! 322: saveregs_value = 0; ! 323: apply_args_value = 0; ! 324: forced_labels = 0; ! 325: } ! 326: ! 327: /* Save all variables describing the current status into the structure *P. ! 328: This is used before starting a nested function. */ ! 329: ! 330: void ! 331: save_expr_status (p) ! 332: struct function *p; ! 333: { ! 334: /* Instead of saving the postincrement queue, empty it. */ ! 335: emit_queue (); ! 336: ! 337: p->pending_stack_adjust = pending_stack_adjust; ! 338: p->inhibit_defer_pop = inhibit_defer_pop; ! 339: p->cleanups_this_call = cleanups_this_call; ! 340: p->saveregs_value = saveregs_value; ! 341: p->apply_args_value = apply_args_value; ! 342: p->forced_labels = forced_labels; ! 343: ! 344: pending_stack_adjust = 0; ! 345: inhibit_defer_pop = 0; ! 346: cleanups_this_call = 0; ! 347: saveregs_value = 0; ! 348: apply_args_value = 0; ! 349: forced_labels = 0; ! 350: } ! 351: ! 352: /* Restore all variables describing the current status from the structure *P. ! 353: This is used after a nested function. */ ! 354: ! 355: void ! 356: restore_expr_status (p) ! 357: struct function *p; ! 358: { ! 359: pending_stack_adjust = p->pending_stack_adjust; ! 360: inhibit_defer_pop = p->inhibit_defer_pop; ! 361: cleanups_this_call = p->cleanups_this_call; ! 362: saveregs_value = p->saveregs_value; ! 363: apply_args_value = p->apply_args_value; ! 364: forced_labels = p->forced_labels; ! 365: } ! 366: ! 367: /* Manage the queue of increment instructions to be output ! 368: for POSTINCREMENT_EXPR expressions, etc. */ ! 369: ! 370: static rtx pending_chain; ! 371: ! 372: /* Queue up to increment (or change) VAR later. BODY says how: ! 373: BODY should be the same thing you would pass to emit_insn ! 374: to increment right away. It will go to emit_insn later on. ! 375: ! 376: The value is a QUEUED expression to be used in place of VAR ! 377: where you want to guarantee the pre-incrementation value of VAR. */ ! 378: ! 379: static rtx ! 380: enqueue_insn (var, body) ! 381: rtx var, body; ! 382: { ! 383: pending_chain = gen_rtx (QUEUED, GET_MODE (var), ! 384: var, NULL_RTX, NULL_RTX, body, pending_chain); ! 385: return pending_chain; ! 386: } ! 387: ! 388: /* Use protect_from_queue to convert a QUEUED expression ! 389: into something that you can put immediately into an instruction. ! 390: If the queued incrementation has not happened yet, ! 391: protect_from_queue returns the variable itself. ! 392: If the incrementation has happened, protect_from_queue returns a temp ! 393: that contains a copy of the old value of the variable. ! 394: ! 395: Any time an rtx which might possibly be a QUEUED is to be put ! 396: into an instruction, it must be passed through protect_from_queue first. ! 397: QUEUED expressions are not meaningful in instructions. ! 398: ! 399: Do not pass a value through protect_from_queue and then hold ! 400: on to it for a while before putting it in an instruction! ! 401: If the queue is flushed in between, incorrect code will result. */ ! 402: ! 403: rtx ! 404: protect_from_queue (x, modify) ! 405: register rtx x; ! 406: int modify; ! 407: { ! 408: register RTX_CODE code = GET_CODE (x); ! 409: ! 410: #if 0 /* A QUEUED can hang around after the queue is forced out. */ ! 411: /* Shortcut for most common case. */ ! 412: if (pending_chain == 0) ! 413: return x; ! 414: #endif ! 415: ! 416: if (code != QUEUED) ! 417: { ! 418: /* A special hack for read access to (MEM (QUEUED ...)) ! 419: to facilitate use of autoincrement. ! 420: Make a copy of the contents of the memory location ! 421: rather than a copy of the address, but not ! 422: if the value is of mode BLKmode. */ ! 423: if (code == MEM && GET_MODE (x) != BLKmode ! 424: && GET_CODE (XEXP (x, 0)) == QUEUED && !modify) ! 425: { ! 426: register rtx y = XEXP (x, 0); ! 427: XEXP (x, 0) = QUEUED_VAR (y); ! 428: if (QUEUED_INSN (y)) ! 429: { ! 430: register rtx temp = gen_reg_rtx (GET_MODE (x)); ! 431: emit_insn_before (gen_move_insn (temp, x), ! 432: QUEUED_INSN (y)); ! 433: return temp; ! 434: } ! 435: return x; ! 436: } ! 437: /* Otherwise, recursively protect the subexpressions of all ! 438: the kinds of rtx's that can contain a QUEUED. */ ! 439: if (code == MEM) ! 440: { ! 441: rtx tem = protect_from_queue (XEXP (x, 0), 0); ! 442: if (tem != XEXP (x, 0)) ! 443: { ! 444: x = copy_rtx (x); ! 445: XEXP (x, 0) = tem; ! 446: } ! 447: } ! 448: else if (code == PLUS || code == MULT) ! 449: { ! 450: rtx new0 = protect_from_queue (XEXP (x, 0), 0); ! 451: rtx new1 = protect_from_queue (XEXP (x, 1), 0); ! 452: if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) ! 453: { ! 454: x = copy_rtx (x); ! 455: XEXP (x, 0) = new0; ! 456: XEXP (x, 1) = new1; ! 457: } ! 458: } ! 459: return x; ! 460: } ! 461: /* If the increment has not happened, use the variable itself. */ ! 462: if (QUEUED_INSN (x) == 0) ! 463: return QUEUED_VAR (x); ! 464: /* If the increment has happened and a pre-increment copy exists, ! 465: use that copy. */ ! 466: if (QUEUED_COPY (x) != 0) ! 467: return QUEUED_COPY (x); ! 468: /* The increment has happened but we haven't set up a pre-increment copy. ! 469: Set one up now, and use it. */ ! 470: QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x))); ! 471: emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)), ! 472: QUEUED_INSN (x)); ! 473: return QUEUED_COPY (x); ! 474: } ! 475: ! 476: /* Return nonzero if X contains a QUEUED expression: ! 477: if it contains anything that will be altered by a queued increment. ! 478: We handle only combinations of MEM, PLUS, MINUS and MULT operators ! 479: since memory addresses generally contain only those. */ ! 480: ! 481: static int ! 482: queued_subexp_p (x) ! 483: rtx x; ! 484: { ! 485: register enum rtx_code code = GET_CODE (x); ! 486: switch (code) ! 487: { ! 488: case QUEUED: ! 489: return 1; ! 490: case MEM: ! 491: return queued_subexp_p (XEXP (x, 0)); ! 492: case MULT: ! 493: case PLUS: ! 494: case MINUS: ! 495: return queued_subexp_p (XEXP (x, 0)) ! 496: || queued_subexp_p (XEXP (x, 1)); ! 497: } ! 498: return 0; ! 499: } ! 500: ! 501: /* Perform all the pending incrementations. */ ! 502: ! 503: void ! 504: emit_queue () ! 505: { ! 506: register rtx p; ! 507: while (p = pending_chain) ! 508: { ! 509: QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p)); ! 510: pending_chain = QUEUED_NEXT (p); ! 511: } ! 512: } ! 513: ! 514: static void ! 515: init_queue () ! 516: { ! 517: if (pending_chain) ! 518: abort (); ! 519: } ! 520: ! 521: /* Copy data from FROM to TO, where the machine modes are not the same. ! 522: Both modes may be integer, or both may be floating. ! 523: UNSIGNEDP should be nonzero if FROM is an unsigned type. ! 524: This causes zero-extension instead of sign-extension. */ ! 525: ! 526: void ! 527: convert_move (to, from, unsignedp) ! 528: register rtx to, from; ! 529: int unsignedp; ! 530: { ! 531: enum machine_mode to_mode = GET_MODE (to); ! 532: enum machine_mode from_mode = GET_MODE (from); ! 533: int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT; ! 534: int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT; ! 535: enum insn_code code; ! 536: rtx libcall; ! 537: ! 538: /* rtx code for making an equivalent value. */ ! 539: enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND); ! 540: ! 541: to = protect_from_queue (to, 1); ! 542: from = protect_from_queue (from, 0); ! 543: ! 544: if (to_real != from_real) ! 545: abort (); ! 546: ! 547: /* If FROM is a SUBREG that indicates that we have already done at least ! 548: the required extension, strip it. We don't handle such SUBREGs as ! 549: TO here. */ ! 550: ! 551: if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) ! 552: && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from))) ! 553: >= GET_MODE_SIZE (to_mode)) ! 554: && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp) ! 555: from = gen_lowpart (to_mode, from), from_mode = to_mode; ! 556: ! 557: if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to)) ! 558: abort (); ! 559: ! 560: if (to_mode == from_mode ! 561: || (from_mode == VOIDmode && CONSTANT_P (from))) ! 562: { ! 563: emit_move_insn (to, from); ! 564: return; ! 565: } ! 566: ! 567: if (to_real) ! 568: { ! 569: rtx value; ! 570: ! 571: #ifdef HAVE_extendqfhf2 ! 572: if (HAVE_extendqfsf2 && from_mode == QFmode && to_mode == HFmode) ! 573: { ! 574: emit_unop_insn (CODE_FOR_extendqfsf2, to, from, UNKNOWN); ! 575: return; ! 576: } ! 577: #endif ! 578: #ifdef HAVE_extendqfsf2 ! 579: if (HAVE_extendqfsf2 && from_mode == QFmode && to_mode == SFmode) ! 580: { ! 581: emit_unop_insn (CODE_FOR_extendqfsf2, to, from, UNKNOWN); ! 582: return; ! 583: } ! 584: #endif ! 585: #ifdef HAVE_extendqfdf2 ! 586: if (HAVE_extendqfdf2 && from_mode == QFmode && to_mode == DFmode) ! 587: { ! 588: emit_unop_insn (CODE_FOR_extendqfdf2, to, from, UNKNOWN); ! 589: return; ! 590: } ! 591: #endif ! 592: #ifdef HAVE_extendqfxf2 ! 593: if (HAVE_extendqfxf2 && from_mode == QFmode && to_mode == XFmode) ! 594: { ! 595: emit_unop_insn (CODE_FOR_extendqfxf2, to, from, UNKNOWN); ! 596: return; ! 597: } ! 598: #endif ! 599: #ifdef HAVE_extendqftf2 ! 600: if (HAVE_extendqftf2 && from_mode == QFmode && to_mode == TFmode) ! 601: { ! 602: emit_unop_insn (CODE_FOR_extendqftf2, to, from, UNKNOWN); ! 603: return; ! 604: } ! 605: #endif ! 606: ! 607: #ifdef HAVE_extendhfsf2 ! 608: if (HAVE_extendhfsf2 && from_mode == HFmode && to_mode == SFmode) ! 609: { ! 610: emit_unop_insn (CODE_FOR_extendhfsf2, to, from, UNKNOWN); ! 611: return; ! 612: } ! 613: #endif ! 614: #ifdef HAVE_extendhfdf2 ! 615: if (HAVE_extendhfdf2 && from_mode == HFmode && to_mode == DFmode) ! 616: { ! 617: emit_unop_insn (CODE_FOR_extendhfdf2, to, from, UNKNOWN); ! 618: return; ! 619: } ! 620: #endif ! 621: #ifdef HAVE_extendhfxf2 ! 622: if (HAVE_extendhfxf2 && from_mode == HFmode && to_mode == XFmode) ! 623: { ! 624: emit_unop_insn (CODE_FOR_extendhfxf2, to, from, UNKNOWN); ! 625: return; ! 626: } ! 627: #endif ! 628: #ifdef HAVE_extendhftf2 ! 629: if (HAVE_extendhftf2 && from_mode == HFmode && to_mode == TFmode) ! 630: { ! 631: emit_unop_insn (CODE_FOR_extendhftf2, to, from, UNKNOWN); ! 632: return; ! 633: } ! 634: #endif ! 635: ! 636: #ifdef HAVE_extendsfdf2 ! 637: if (HAVE_extendsfdf2 && from_mode == SFmode && to_mode == DFmode) ! 638: { ! 639: emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN); ! 640: return; ! 641: } ! 642: #endif ! 643: #ifdef HAVE_extendsfxf2 ! 644: if (HAVE_extendsfxf2 && from_mode == SFmode && to_mode == XFmode) ! 645: { ! 646: emit_unop_insn (CODE_FOR_extendsfxf2, to, from, UNKNOWN); ! 647: return; ! 648: } ! 649: #endif ! 650: #ifdef HAVE_extendsftf2 ! 651: if (HAVE_extendsftf2 && from_mode == SFmode && to_mode == TFmode) ! 652: { ! 653: emit_unop_insn (CODE_FOR_extendsftf2, to, from, UNKNOWN); ! 654: return; ! 655: } ! 656: #endif ! 657: #ifdef HAVE_extenddfxf2 ! 658: if (HAVE_extenddfxf2 && from_mode == DFmode && to_mode == XFmode) ! 659: { ! 660: emit_unop_insn (CODE_FOR_extenddfxf2, to, from, UNKNOWN); ! 661: return; ! 662: } ! 663: #endif ! 664: #ifdef HAVE_extenddftf2 ! 665: if (HAVE_extenddftf2 && from_mode == DFmode && to_mode == TFmode) ! 666: { ! 667: emit_unop_insn (CODE_FOR_extenddftf2, to, from, UNKNOWN); ! 668: return; ! 669: } ! 670: #endif ! 671: ! 672: #ifdef HAVE_trunchfqf2 ! 673: if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode) ! 674: { ! 675: emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN); ! 676: return; ! 677: } ! 678: #endif ! 679: #ifdef HAVE_truncsfqf2 ! 680: if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode) ! 681: { ! 682: emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN); ! 683: return; ! 684: } ! 685: #endif ! 686: #ifdef HAVE_truncdfqf2 ! 687: if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode) ! 688: { ! 689: emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN); ! 690: return; ! 691: } ! 692: #endif ! 693: #ifdef HAVE_truncxfqf2 ! 694: if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode) ! 695: { ! 696: emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN); ! 697: return; ! 698: } ! 699: #endif ! 700: #ifdef HAVE_trunctfqf2 ! 701: if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode) ! 702: { ! 703: emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN); ! 704: return; ! 705: } ! 706: #endif ! 707: #ifdef HAVE_truncsfhf2 ! 708: if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode) ! 709: { ! 710: emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN); ! 711: return; ! 712: } ! 713: #endif ! 714: #ifdef HAVE_truncdfhf2 ! 715: if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode) ! 716: { ! 717: emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN); ! 718: return; ! 719: } ! 720: #endif ! 721: #ifdef HAVE_truncxfhf2 ! 722: if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode) ! 723: { ! 724: emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN); ! 725: return; ! 726: } ! 727: #endif ! 728: #ifdef HAVE_trunctfhf2 ! 729: if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode) ! 730: { ! 731: emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN); ! 732: return; ! 733: } ! 734: #endif ! 735: #ifdef HAVE_truncdfsf2 ! 736: if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode) ! 737: { ! 738: emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN); ! 739: return; ! 740: } ! 741: #endif ! 742: #ifdef HAVE_truncxfsf2 ! 743: if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode) ! 744: { ! 745: emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN); ! 746: return; ! 747: } ! 748: #endif ! 749: #ifdef HAVE_trunctfsf2 ! 750: if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode) ! 751: { ! 752: emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN); ! 753: return; ! 754: } ! 755: #endif ! 756: #ifdef HAVE_truncxfdf2 ! 757: if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode) ! 758: { ! 759: emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN); ! 760: return; ! 761: } ! 762: #endif ! 763: #ifdef HAVE_trunctfdf2 ! 764: if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode) ! 765: { ! 766: emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN); ! 767: return; ! 768: } ! 769: #endif ! 770: ! 771: libcall = (rtx) 0; ! 772: switch (from_mode) ! 773: { ! 774: case SFmode: ! 775: switch (to_mode) ! 776: { ! 777: case DFmode: ! 778: libcall = extendsfdf2_libfunc; ! 779: break; ! 780: ! 781: case XFmode: ! 782: libcall = extendsfxf2_libfunc; ! 783: break; ! 784: ! 785: case TFmode: ! 786: libcall = extendsftf2_libfunc; ! 787: break; ! 788: } ! 789: break; ! 790: ! 791: case DFmode: ! 792: switch (to_mode) ! 793: { ! 794: case SFmode: ! 795: libcall = truncdfsf2_libfunc; ! 796: break; ! 797: ! 798: case XFmode: ! 799: libcall = extenddfxf2_libfunc; ! 800: break; ! 801: ! 802: case TFmode: ! 803: libcall = extenddftf2_libfunc; ! 804: break; ! 805: } ! 806: break; ! 807: ! 808: case XFmode: ! 809: switch (to_mode) ! 810: { ! 811: case SFmode: ! 812: libcall = truncxfsf2_libfunc; ! 813: break; ! 814: ! 815: case DFmode: ! 816: libcall = truncxfdf2_libfunc; ! 817: break; ! 818: } ! 819: break; ! 820: ! 821: case TFmode: ! 822: switch (to_mode) ! 823: { ! 824: case SFmode: ! 825: libcall = trunctfsf2_libfunc; ! 826: break; ! 827: ! 828: case DFmode: ! 829: libcall = trunctfdf2_libfunc; ! 830: break; ! 831: } ! 832: break; ! 833: } ! 834: ! 835: if (libcall == (rtx) 0) ! 836: /* This conversion is not implemented yet. */ ! 837: abort (); ! 838: ! 839: value = emit_library_call_value (libcall, NULL_RTX, 1, to_mode, ! 840: 1, from, from_mode); ! 841: emit_move_insn (to, value); ! 842: return; ! 843: } ! 844: ! 845: /* Now both modes are integers. */ ! 846: ! 847: /* Handle expanding beyond a word. */ ! 848: if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode) ! 849: && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD) ! 850: { ! 851: rtx insns; ! 852: rtx lowpart; ! 853: rtx fill_value; ! 854: rtx lowfrom; ! 855: int i; ! 856: enum machine_mode lowpart_mode; ! 857: int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD); ! 858: ! 859: /* Try converting directly if the insn is supported. */ ! 860: if ((code = can_extend_p (to_mode, from_mode, unsignedp)) ! 861: != CODE_FOR_nothing) ! 862: { ! 863: /* If FROM is a SUBREG, put it into a register. Do this ! 864: so that we always generate the same set of insns for ! 865: better cse'ing; if an intermediate assignment occurred, ! 866: we won't be doing the operation directly on the SUBREG. */ ! 867: if (optimize > 0 && GET_CODE (from) == SUBREG) ! 868: from = force_reg (from_mode, from); ! 869: emit_unop_insn (code, to, from, equiv_code); ! 870: return; ! 871: } ! 872: /* Next, try converting via full word. */ ! 873: else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD ! 874: && ((code = can_extend_p (to_mode, word_mode, unsignedp)) ! 875: != CODE_FOR_nothing)) ! 876: { ! 877: if (GET_CODE (to) == REG) ! 878: emit_insn (gen_rtx (CLOBBER, VOIDmode, to)); ! 879: convert_move (gen_lowpart (word_mode, to), from, unsignedp); ! 880: emit_unop_insn (code, to, ! 881: gen_lowpart (word_mode, to), equiv_code); ! 882: return; ! 883: } ! 884: ! 885: /* No special multiword conversion insn; do it by hand. */ ! 886: start_sequence (); ! 887: ! 888: /* Get a copy of FROM widened to a word, if necessary. */ ! 889: if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD) ! 890: lowpart_mode = word_mode; ! 891: else ! 892: lowpart_mode = from_mode; ! 893: ! 894: lowfrom = convert_to_mode (lowpart_mode, from, unsignedp); ! 895: ! 896: lowpart = gen_lowpart (lowpart_mode, to); ! 897: emit_move_insn (lowpart, lowfrom); ! 898: ! 899: /* Compute the value to put in each remaining word. */ ! 900: if (unsignedp) ! 901: fill_value = const0_rtx; ! 902: else ! 903: { ! 904: #ifdef HAVE_slt ! 905: if (HAVE_slt ! 906: && insn_operand_mode[(int) CODE_FOR_slt][0] == word_mode ! 907: && STORE_FLAG_VALUE == -1) ! 908: { ! 909: emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX, ! 910: lowpart_mode, 0, 0); ! 911: fill_value = gen_reg_rtx (word_mode); ! 912: emit_insn (gen_slt (fill_value)); ! 913: } ! 914: else ! 915: #endif ! 916: { ! 917: fill_value ! 918: = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom, ! 919: size_int (GET_MODE_BITSIZE (lowpart_mode) - 1), ! 920: NULL_RTX, 0); ! 921: fill_value = convert_to_mode (word_mode, fill_value, 1); ! 922: } ! 923: } ! 924: ! 925: /* Fill the remaining words. */ ! 926: for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++) ! 927: { ! 928: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); ! 929: rtx subword = operand_subword (to, index, 1, to_mode); ! 930: ! 931: if (subword == 0) ! 932: abort (); ! 933: ! 934: if (fill_value != subword) ! 935: emit_move_insn (subword, fill_value); ! 936: } ! 937: ! 938: insns = get_insns (); ! 939: end_sequence (); ! 940: ! 941: emit_no_conflict_block (insns, to, from, NULL_RTX, ! 942: gen_rtx (equiv_code, to_mode, copy_rtx (from))); ! 943: return; ! 944: } ! 945: ! 946: /* Truncating multi-word to a word or less. */ ! 947: if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD ! 948: && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD) ! 949: { ! 950: if (!((GET_CODE (from) == MEM ! 951: && ! MEM_VOLATILE_P (from) ! 952: && direct_load[(int) to_mode] ! 953: && ! mode_dependent_address_p (XEXP (from, 0))) ! 954: || GET_CODE (from) == REG ! 955: || GET_CODE (from) == SUBREG)) ! 956: from = force_reg (from_mode, from); ! 957: convert_move (to, gen_lowpart (word_mode, from), 0); ! 958: return; ! 959: } ! 960: ! 961: /* Handle pointer conversion */ /* SPEE 900220 */ ! 962: if (to_mode == PSImode) ! 963: { ! 964: if (from_mode != SImode) ! 965: from = convert_to_mode (SImode, from, unsignedp); ! 966: ! 967: #ifdef HAVE_truncsipsi ! 968: if (HAVE_truncsipsi) ! 969: { ! 970: emit_unop_insn (CODE_FOR_truncsipsi, to, from, UNKNOWN); ! 971: return; ! 972: } ! 973: #endif /* HAVE_truncsipsi */ ! 974: abort (); ! 975: } ! 976: ! 977: if (from_mode == PSImode) ! 978: { ! 979: if (to_mode != SImode) ! 980: { ! 981: from = convert_to_mode (SImode, from, unsignedp); ! 982: from_mode = SImode; ! 983: } ! 984: else ! 985: { ! 986: #ifdef HAVE_extendpsisi ! 987: if (HAVE_extendpsisi) ! 988: { ! 989: emit_unop_insn (CODE_FOR_extendpsisi, to, from, UNKNOWN); ! 990: return; ! 991: } ! 992: #endif /* HAVE_extendpsisi */ ! 993: abort (); ! 994: } ! 995: } ! 996: ! 997: /* Now follow all the conversions between integers ! 998: no more than a word long. */ ! 999: ! 1000: /* For truncation, usually we can just refer to FROM in a narrower mode. */ ! 1001: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode) ! 1002: && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode), ! 1003: GET_MODE_BITSIZE (from_mode))) ! 1004: { ! 1005: if (!((GET_CODE (from) == MEM ! 1006: && ! MEM_VOLATILE_P (from) ! 1007: && direct_load[(int) to_mode] ! 1008: && ! mode_dependent_address_p (XEXP (from, 0))) ! 1009: || GET_CODE (from) == REG ! 1010: || GET_CODE (from) == SUBREG)) ! 1011: from = force_reg (from_mode, from); ! 1012: emit_move_insn (to, gen_lowpart (to_mode, from)); ! 1013: return; ! 1014: } ! 1015: ! 1016: /* Handle extension. */ ! 1017: if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode)) ! 1018: { ! 1019: /* Convert directly if that works. */ ! 1020: if ((code = can_extend_p (to_mode, from_mode, unsignedp)) ! 1021: != CODE_FOR_nothing) ! 1022: { ! 1023: /* If FROM is a SUBREG, put it into a register. Do this ! 1024: so that we always generate the same set of insns for ! 1025: better cse'ing; if an intermediate assignment occurred, ! 1026: we won't be doing the operation directly on the SUBREG. */ ! 1027: if (optimize > 0 && GET_CODE (from) == SUBREG) ! 1028: from = force_reg (from_mode, from); ! 1029: emit_unop_insn (code, to, from, equiv_code); ! 1030: return; ! 1031: } ! 1032: else ! 1033: { ! 1034: enum machine_mode intermediate; ! 1035: ! 1036: /* Search for a mode to convert via. */ ! 1037: for (intermediate = from_mode; intermediate != VOIDmode; ! 1038: intermediate = GET_MODE_WIDER_MODE (intermediate)) ! 1039: if ((can_extend_p (to_mode, intermediate, unsignedp) ! 1040: != CODE_FOR_nothing) ! 1041: && (can_extend_p (intermediate, from_mode, unsignedp) ! 1042: != CODE_FOR_nothing)) ! 1043: { ! 1044: convert_move (to, convert_to_mode (intermediate, from, ! 1045: unsignedp), unsignedp); ! 1046: return; ! 1047: } ! 1048: ! 1049: /* No suitable intermediate mode. */ ! 1050: abort (); ! 1051: } ! 1052: } ! 1053: ! 1054: /* Support special truncate insns for certain modes. */ ! 1055: ! 1056: if (from_mode == DImode && to_mode == SImode) ! 1057: { ! 1058: #ifdef HAVE_truncdisi2 ! 1059: if (HAVE_truncdisi2) ! 1060: { ! 1061: emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN); ! 1062: return; ! 1063: } ! 1064: #endif ! 1065: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1066: return; ! 1067: } ! 1068: ! 1069: if (from_mode == DImode && to_mode == HImode) ! 1070: { ! 1071: #ifdef HAVE_truncdihi2 ! 1072: if (HAVE_truncdihi2) ! 1073: { ! 1074: emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN); ! 1075: return; ! 1076: } ! 1077: #endif ! 1078: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1079: return; ! 1080: } ! 1081: ! 1082: if (from_mode == DImode && to_mode == QImode) ! 1083: { ! 1084: #ifdef HAVE_truncdiqi2 ! 1085: if (HAVE_truncdiqi2) ! 1086: { ! 1087: emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN); ! 1088: return; ! 1089: } ! 1090: #endif ! 1091: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1092: return; ! 1093: } ! 1094: ! 1095: if (from_mode == SImode && to_mode == HImode) ! 1096: { ! 1097: #ifdef HAVE_truncsihi2 ! 1098: if (HAVE_truncsihi2) ! 1099: { ! 1100: emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN); ! 1101: return; ! 1102: } ! 1103: #endif ! 1104: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1105: return; ! 1106: } ! 1107: ! 1108: if (from_mode == SImode && to_mode == QImode) ! 1109: { ! 1110: #ifdef HAVE_truncsiqi2 ! 1111: if (HAVE_truncsiqi2) ! 1112: { ! 1113: emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN); ! 1114: return; ! 1115: } ! 1116: #endif ! 1117: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1118: return; ! 1119: } ! 1120: ! 1121: if (from_mode == HImode && to_mode == QImode) ! 1122: { ! 1123: #ifdef HAVE_trunchiqi2 ! 1124: if (HAVE_trunchiqi2) ! 1125: { ! 1126: emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN); ! 1127: return; ! 1128: } ! 1129: #endif ! 1130: convert_move (to, force_reg (from_mode, from), unsignedp); ! 1131: return; ! 1132: } ! 1133: ! 1134: /* Handle truncation of volatile memrefs, and so on; ! 1135: the things that couldn't be truncated directly, ! 1136: and for which there was no special instruction. */ ! 1137: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)) ! 1138: { ! 1139: rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from)); ! 1140: emit_move_insn (to, temp); ! 1141: return; ! 1142: } ! 1143: ! 1144: /* Mode combination is not recognized. */ ! 1145: abort (); ! 1146: } ! 1147: ! 1148: /* Return an rtx for a value that would result ! 1149: from converting X to mode MODE. ! 1150: Both X and MODE may be floating, or both integer. ! 1151: UNSIGNEDP is nonzero if X is an unsigned value. ! 1152: This can be done by referring to a part of X in place ! 1153: or by copying to a new temporary with conversion. ! 1154: ! 1155: This function *must not* call protect_from_queue ! 1156: except when putting X into an insn (in which case convert_move does it). */ ! 1157: ! 1158: rtx ! 1159: convert_to_mode (mode, x, unsignedp) ! 1160: enum machine_mode mode; ! 1161: rtx x; ! 1162: int unsignedp; ! 1163: { ! 1164: return convert_modes (mode, VOIDmode, x, unsignedp); ! 1165: } ! 1166: ! 1167: /* Return an rtx for a value that would result ! 1168: from converting X from mode OLDMODE to mode MODE. ! 1169: Both modes may be floating, or both integer. ! 1170: UNSIGNEDP is nonzero if X is an unsigned value. ! 1171: ! 1172: This can be done by referring to a part of X in place ! 1173: or by copying to a new temporary with conversion. ! 1174: ! 1175: You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode. ! 1176: ! 1177: This function *must not* call protect_from_queue ! 1178: except when putting X into an insn (in which case convert_move does it). */ ! 1179: ! 1180: rtx ! 1181: convert_modes (mode, oldmode, x, unsignedp) ! 1182: enum machine_mode mode, oldmode; ! 1183: rtx x; ! 1184: int unsignedp; ! 1185: { ! 1186: register rtx temp; ! 1187: ! 1188: /* If FROM is a SUBREG that indicates that we have already done at least ! 1189: the required extension, strip it. */ ! 1190: ! 1191: if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x) ! 1192: && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode) ! 1193: && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp) ! 1194: x = gen_lowpart (mode, x); ! 1195: ! 1196: if (GET_MODE (x) != VOIDmode) ! 1197: oldmode = GET_MODE (x); ! 1198: ! 1199: if (mode == oldmode) ! 1200: return x; ! 1201: ! 1202: /* There is one case that we must handle specially: If we are converting ! 1203: a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and ! 1204: we are to interpret the constant as unsigned, gen_lowpart will do ! 1205: the wrong if the constant appears negative. What we want to do is ! 1206: make the high-order word of the constant zero, not all ones. */ ! 1207: ! 1208: if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT ! 1209: && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT ! 1210: && GET_CODE (x) == CONST_INT && INTVAL (x) < 0) ! 1211: return immed_double_const (INTVAL (x), (HOST_WIDE_INT) 0, mode); ! 1212: ! 1213: /* We can do this with a gen_lowpart if both desired and current modes ! 1214: are integer, and this is either a constant integer, a register, or a ! 1215: non-volatile MEM. Except for the constant case where MODE is no ! 1216: wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand. */ ! 1217: ! 1218: if ((GET_CODE (x) == CONST_INT ! 1219: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) ! 1220: || (GET_MODE_CLASS (mode) == MODE_INT ! 1221: && GET_MODE_CLASS (oldmode) == MODE_INT ! 1222: && (GET_CODE (x) == CONST_DOUBLE ! 1223: || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode) ! 1224: && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x) ! 1225: && direct_load[(int) mode]) ! 1226: || GET_CODE (x) == REG))))) ! 1227: { ! 1228: /* ?? If we don't know OLDMODE, we have to assume here that ! 1229: X does not need sign- or zero-extension. This may not be ! 1230: the case, but it's the best we can do. */ ! 1231: if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode ! 1232: && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode)) ! 1233: { ! 1234: HOST_WIDE_INT val = INTVAL (x); ! 1235: int width = GET_MODE_BITSIZE (oldmode); ! 1236: ! 1237: /* We must sign or zero-extend in this case. Start by ! 1238: zero-extending, then sign extend if we need to. */ ! 1239: val &= ((HOST_WIDE_INT) 1 << width) - 1; ! 1240: if (! unsignedp ! 1241: && (val & ((HOST_WIDE_INT) 1 << (width - 1)))) ! 1242: val |= (HOST_WIDE_INT) (-1) << width; ! 1243: ! 1244: return GEN_INT (val); ! 1245: } ! 1246: ! 1247: return gen_lowpart (mode, x); ! 1248: } ! 1249: ! 1250: temp = gen_reg_rtx (mode); ! 1251: convert_move (temp, x, unsignedp); ! 1252: return temp; ! 1253: } ! 1254: ! 1255: /* Generate several move instructions to copy LEN bytes ! 1256: from block FROM to block TO. (These are MEM rtx's with BLKmode). ! 1257: The caller must pass FROM and TO ! 1258: through protect_from_queue before calling. ! 1259: ALIGN (in bytes) is maximum alignment we can assume. */ ! 1260: ! 1261: static void ! 1262: move_by_pieces (to, from, len, align) ! 1263: rtx to, from; ! 1264: int len, align; ! 1265: { ! 1266: struct move_by_pieces data; ! 1267: rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0); ! 1268: int max_size = MOVE_MAX + 1; ! 1269: ! 1270: data.offset = 0; ! 1271: data.to_addr = to_addr; ! 1272: data.from_addr = from_addr; ! 1273: data.to = to; ! 1274: data.from = from; ! 1275: data.autinc_to ! 1276: = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC ! 1277: || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC); ! 1278: data.autinc_from ! 1279: = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC ! 1280: || GET_CODE (from_addr) == POST_INC ! 1281: || GET_CODE (from_addr) == POST_DEC); ! 1282: ! 1283: data.explicit_inc_from = 0; ! 1284: data.explicit_inc_to = 0; ! 1285: data.reverse ! 1286: = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC); ! 1287: if (data.reverse) data.offset = len; ! 1288: data.len = len; ! 1289: ! 1290: /* If copying requires more than two move insns, ! 1291: copy addresses to registers (to make displacements shorter) ! 1292: and use post-increment if available. */ ! 1293: if (!(data.autinc_from && data.autinc_to) ! 1294: && move_by_pieces_ninsns (len, align) > 2) ! 1295: { ! 1296: #ifdef HAVE_PRE_DECREMENT ! 1297: if (data.reverse && ! data.autinc_from) ! 1298: { ! 1299: data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len)); ! 1300: data.autinc_from = 1; ! 1301: data.explicit_inc_from = -1; ! 1302: } ! 1303: #endif ! 1304: #ifdef HAVE_POST_INCREMENT ! 1305: if (! data.autinc_from) ! 1306: { ! 1307: data.from_addr = copy_addr_to_reg (from_addr); ! 1308: data.autinc_from = 1; ! 1309: data.explicit_inc_from = 1; ! 1310: } ! 1311: #endif ! 1312: if (!data.autinc_from && CONSTANT_P (from_addr)) ! 1313: data.from_addr = copy_addr_to_reg (from_addr); ! 1314: #ifdef HAVE_PRE_DECREMENT ! 1315: if (data.reverse && ! data.autinc_to) ! 1316: { ! 1317: data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len)); ! 1318: data.autinc_to = 1; ! 1319: data.explicit_inc_to = -1; ! 1320: } ! 1321: #endif ! 1322: #ifdef HAVE_POST_INCREMENT ! 1323: if (! data.reverse && ! data.autinc_to) ! 1324: { ! 1325: data.to_addr = copy_addr_to_reg (to_addr); ! 1326: data.autinc_to = 1; ! 1327: data.explicit_inc_to = 1; ! 1328: } ! 1329: #endif ! 1330: if (!data.autinc_to && CONSTANT_P (to_addr)) ! 1331: data.to_addr = copy_addr_to_reg (to_addr); ! 1332: } ! 1333: ! 1334: if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS) ! 1335: || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 1336: align = MOVE_MAX; ! 1337: ! 1338: /* First move what we can in the largest integer mode, then go to ! 1339: successively smaller modes. */ ! 1340: ! 1341: while (max_size > 1) ! 1342: { ! 1343: enum machine_mode mode = VOIDmode, tmode; ! 1344: enum insn_code icode; ! 1345: ! 1346: for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); ! 1347: tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) ! 1348: if (GET_MODE_SIZE (tmode) < max_size) ! 1349: mode = tmode; ! 1350: ! 1351: if (mode == VOIDmode) ! 1352: break; ! 1353: ! 1354: icode = mov_optab->handlers[(int) mode].insn_code; ! 1355: if (icode != CODE_FOR_nothing ! 1356: && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT, ! 1357: GET_MODE_SIZE (mode))) ! 1358: move_by_pieces_1 (GEN_FCN (icode), mode, &data); ! 1359: ! 1360: max_size = GET_MODE_SIZE (mode); ! 1361: } ! 1362: ! 1363: /* The code above should have handled everything. */ ! 1364: if (data.len != 0) ! 1365: abort (); ! 1366: } ! 1367: ! 1368: /* Return number of insns required to move L bytes by pieces. ! 1369: ALIGN (in bytes) is maximum alignment we can assume. */ ! 1370: ! 1371: static int ! 1372: move_by_pieces_ninsns (l, align) ! 1373: unsigned int l; ! 1374: int align; ! 1375: { ! 1376: register int n_insns = 0; ! 1377: int max_size = MOVE_MAX + 1; ! 1378: ! 1379: if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS) ! 1380: || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 1381: align = MOVE_MAX; ! 1382: ! 1383: while (max_size > 1) ! 1384: { ! 1385: enum machine_mode mode = VOIDmode, tmode; ! 1386: enum insn_code icode; ! 1387: ! 1388: for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); ! 1389: tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) ! 1390: if (GET_MODE_SIZE (tmode) < max_size) ! 1391: mode = tmode; ! 1392: ! 1393: if (mode == VOIDmode) ! 1394: break; ! 1395: ! 1396: icode = mov_optab->handlers[(int) mode].insn_code; ! 1397: if (icode != CODE_FOR_nothing ! 1398: && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT, ! 1399: GET_MODE_SIZE (mode))) ! 1400: n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode); ! 1401: ! 1402: max_size = GET_MODE_SIZE (mode); ! 1403: } ! 1404: ! 1405: return n_insns; ! 1406: } ! 1407: ! 1408: /* Subroutine of move_by_pieces. Move as many bytes as appropriate ! 1409: with move instructions for mode MODE. GENFUN is the gen_... function ! 1410: to make a move insn for that mode. DATA has all the other info. */ ! 1411: ! 1412: static void ! 1413: move_by_pieces_1 (genfun, mode, data) ! 1414: rtx (*genfun) (); ! 1415: enum machine_mode mode; ! 1416: struct move_by_pieces *data; ! 1417: { ! 1418: register int size = GET_MODE_SIZE (mode); ! 1419: register rtx to1, from1; ! 1420: ! 1421: while (data->len >= size) ! 1422: { ! 1423: if (data->reverse) data->offset -= size; ! 1424: ! 1425: to1 = (data->autinc_to ! 1426: ? gen_rtx (MEM, mode, data->to_addr) ! 1427: : change_address (data->to, mode, ! 1428: plus_constant (data->to_addr, data->offset))); ! 1429: from1 = ! 1430: (data->autinc_from ! 1431: ? gen_rtx (MEM, mode, data->from_addr) ! 1432: : change_address (data->from, mode, ! 1433: plus_constant (data->from_addr, data->offset))); ! 1434: ! 1435: #ifdef HAVE_PRE_DECREMENT ! 1436: if (data->explicit_inc_to < 0) ! 1437: emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); ! 1438: if (data->explicit_inc_from < 0) ! 1439: emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); ! 1440: #endif ! 1441: ! 1442: emit_insn ((*genfun) (to1, from1)); ! 1443: #ifdef HAVE_POST_INCREMENT ! 1444: if (data->explicit_inc_to > 0) ! 1445: emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size))); ! 1446: if (data->explicit_inc_from > 0) ! 1447: emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size))); ! 1448: #endif ! 1449: ! 1450: if (! data->reverse) data->offset += size; ! 1451: ! 1452: data->len -= size; ! 1453: } ! 1454: } ! 1455: ! 1456: /* Emit code to move a block Y to a block X. ! 1457: This may be done with string-move instructions, ! 1458: with multiple scalar move instructions, or with a library call. ! 1459: ! 1460: Both X and Y must be MEM rtx's (perhaps inside VOLATILE) ! 1461: with mode BLKmode. ! 1462: SIZE is an rtx that says how long they are. ! 1463: ALIGN is the maximum alignment we can assume they have, ! 1464: measured in bytes. */ ! 1465: ! 1466: void ! 1467: emit_block_move (x, y, size, align) ! 1468: rtx x, y; ! 1469: rtx size; ! 1470: int align; ! 1471: { ! 1472: if (GET_MODE (x) != BLKmode) ! 1473: abort (); ! 1474: ! 1475: if (GET_MODE (y) != BLKmode) ! 1476: abort (); ! 1477: ! 1478: x = protect_from_queue (x, 1); ! 1479: y = protect_from_queue (y, 0); ! 1480: size = protect_from_queue (size, 0); ! 1481: ! 1482: if (GET_CODE (x) != MEM) ! 1483: abort (); ! 1484: if (GET_CODE (y) != MEM) ! 1485: abort (); ! 1486: if (size == 0) ! 1487: abort (); ! 1488: ! 1489: if (GET_CODE (size) == CONST_INT ! 1490: && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO)) ! 1491: move_by_pieces (x, y, INTVAL (size), align); ! 1492: else ! 1493: { ! 1494: /* Try the most limited insn first, because there's no point ! 1495: including more than one in the machine description unless ! 1496: the more limited one has some advantage. */ ! 1497: ! 1498: rtx opalign = GEN_INT (align); ! 1499: enum machine_mode mode; ! 1500: ! 1501: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; ! 1502: mode = GET_MODE_WIDER_MODE (mode)) ! 1503: { ! 1504: enum insn_code code = movstr_optab[(int) mode]; ! 1505: ! 1506: if (code != CODE_FOR_nothing ! 1507: /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT ! 1508: here because if SIZE is less than the mode mask, as it is ! 1509: returned by the macro, it will definitely be less than the ! 1510: actual mode mask. */ ! 1511: && (unsigned HOST_WIDE_INT) INTVAL (size) <= GET_MODE_MASK (mode) ! 1512: && (insn_operand_predicate[(int) code][0] == 0 ! 1513: || (*insn_operand_predicate[(int) code][0]) (x, BLKmode)) ! 1514: && (insn_operand_predicate[(int) code][1] == 0 ! 1515: || (*insn_operand_predicate[(int) code][1]) (y, BLKmode)) ! 1516: && (insn_operand_predicate[(int) code][3] == 0 ! 1517: || (*insn_operand_predicate[(int) code][3]) (opalign, ! 1518: VOIDmode))) ! 1519: { ! 1520: rtx op2; ! 1521: rtx last = get_last_insn (); ! 1522: rtx pat; ! 1523: ! 1524: op2 = convert_to_mode (mode, size, 1); ! 1525: if (insn_operand_predicate[(int) code][2] != 0 ! 1526: && ! (*insn_operand_predicate[(int) code][2]) (op2, mode)) ! 1527: op2 = copy_to_mode_reg (mode, op2); ! 1528: ! 1529: pat = GEN_FCN ((int) code) (x, y, op2, opalign); ! 1530: if (pat) ! 1531: { ! 1532: emit_insn (pat); ! 1533: return; ! 1534: } ! 1535: else ! 1536: delete_insns_since (last); ! 1537: } ! 1538: } ! 1539: ! 1540: #ifdef TARGET_MEM_FUNCTIONS ! 1541: emit_library_call (memcpy_libfunc, 0, ! 1542: VOIDmode, 3, XEXP (x, 0), Pmode, ! 1543: XEXP (y, 0), Pmode, ! 1544: convert_to_mode (TYPE_MODE (sizetype), size, ! 1545: TREE_UNSIGNED (sizetype)), ! 1546: TYPE_MODE (sizetype)); ! 1547: #else ! 1548: emit_library_call (bcopy_libfunc, 0, ! 1549: VOIDmode, 3, XEXP (y, 0), Pmode, ! 1550: XEXP (x, 0), Pmode, ! 1551: convert_to_mode (TYPE_MODE (sizetype), size, ! 1552: TREE_UNSIGNED (sizetype)), ! 1553: TYPE_MODE (sizetype)); ! 1554: #endif ! 1555: } ! 1556: } ! 1557: ! 1558: /* Copy all or part of a value X into registers starting at REGNO. ! 1559: The number of registers to be filled is NREGS. */ ! 1560: ! 1561: void ! 1562: move_block_to_reg (regno, x, nregs, mode) ! 1563: int regno; ! 1564: rtx x; ! 1565: int nregs; ! 1566: enum machine_mode mode; ! 1567: { ! 1568: int i; ! 1569: rtx pat, last; ! 1570: ! 1571: if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x)) ! 1572: x = validize_mem (force_const_mem (mode, x)); ! 1573: ! 1574: /* See if the machine can do this with a load multiple insn. */ ! 1575: #ifdef HAVE_load_multiple ! 1576: if (HAVE_load_multiple) ! 1577: { ! 1578: last = get_last_insn (); ! 1579: pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x, ! 1580: GEN_INT (nregs)); ! 1581: if (pat) ! 1582: { ! 1583: emit_insn (pat); ! 1584: return; ! 1585: } ! 1586: else ! 1587: delete_insns_since (last); ! 1588: } ! 1589: #endif ! 1590: ! 1591: for (i = 0; i < nregs; i++) ! 1592: emit_move_insn (gen_rtx (REG, word_mode, regno + i), ! 1593: operand_subword_force (x, i, mode)); ! 1594: } ! 1595: ! 1596: /* Copy all or part of a BLKmode value X out of registers starting at REGNO. ! 1597: The number of registers to be filled is NREGS. SIZE indicates the number ! 1598: of bytes in the object X. */ ! 1599: ! 1600: ! 1601: void ! 1602: move_block_from_reg (regno, x, nregs, size) ! 1603: int regno; ! 1604: rtx x; ! 1605: int nregs; ! 1606: int size; ! 1607: { ! 1608: int i; ! 1609: rtx pat, last; ! 1610: ! 1611: /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned ! 1612: to the left before storing to memory. */ ! 1613: if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN) ! 1614: { ! 1615: rtx tem = operand_subword (x, 0, 1, BLKmode); ! 1616: rtx shift; ! 1617: ! 1618: if (tem == 0) ! 1619: abort (); ! 1620: ! 1621: shift = expand_shift (LSHIFT_EXPR, word_mode, ! 1622: gen_rtx (REG, word_mode, regno), ! 1623: build_int_2 ((UNITS_PER_WORD - size) ! 1624: * BITS_PER_UNIT, 0), NULL_RTX, 0); ! 1625: emit_move_insn (tem, shift); ! 1626: return; ! 1627: } ! 1628: ! 1629: /* See if the machine can do this with a store multiple insn. */ ! 1630: #ifdef HAVE_store_multiple ! 1631: if (HAVE_store_multiple) ! 1632: { ! 1633: last = get_last_insn (); ! 1634: pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno), ! 1635: GEN_INT (nregs)); ! 1636: if (pat) ! 1637: { ! 1638: emit_insn (pat); ! 1639: return; ! 1640: } ! 1641: else ! 1642: delete_insns_since (last); ! 1643: } ! 1644: #endif ! 1645: ! 1646: for (i = 0; i < nregs; i++) ! 1647: { ! 1648: rtx tem = operand_subword (x, i, 1, BLKmode); ! 1649: ! 1650: if (tem == 0) ! 1651: abort (); ! 1652: ! 1653: emit_move_insn (tem, gen_rtx (REG, word_mode, regno + i)); ! 1654: } ! 1655: } ! 1656: ! 1657: /* Mark NREGS consecutive regs, starting at REGNO, as being live now. */ ! 1658: ! 1659: void ! 1660: use_regs (regno, nregs) ! 1661: int regno; ! 1662: int nregs; ! 1663: { ! 1664: int i; ! 1665: ! 1666: for (i = 0; i < nregs; i++) ! 1667: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, word_mode, regno + i))); ! 1668: } ! 1669: ! 1670: /* Mark the instructions since PREV as a libcall block. ! 1671: Add REG_LIBCALL to PREV and add a REG_RETVAL to the most recent insn. */ ! 1672: ! 1673: static void ! 1674: group_insns (prev) ! 1675: rtx prev; ! 1676: { ! 1677: rtx insn_first; ! 1678: rtx insn_last; ! 1679: ! 1680: /* Find the instructions to mark */ ! 1681: if (prev) ! 1682: insn_first = NEXT_INSN (prev); ! 1683: else ! 1684: insn_first = get_insns (); ! 1685: ! 1686: insn_last = get_last_insn (); ! 1687: ! 1688: REG_NOTES (insn_last) = gen_rtx (INSN_LIST, REG_RETVAL, insn_first, ! 1689: REG_NOTES (insn_last)); ! 1690: ! 1691: REG_NOTES (insn_first) = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last, ! 1692: REG_NOTES (insn_first)); ! 1693: } ! 1694: ! 1695: /* Write zeros through the storage of OBJECT. ! 1696: If OBJECT has BLKmode, SIZE is its length in bytes. */ ! 1697: ! 1698: void ! 1699: clear_storage (object, size) ! 1700: rtx object; ! 1701: int size; ! 1702: { ! 1703: if (GET_MODE (object) == BLKmode) ! 1704: { ! 1705: #ifdef TARGET_MEM_FUNCTIONS ! 1706: emit_library_call (memset_libfunc, 0, ! 1707: VOIDmode, 3, ! 1708: XEXP (object, 0), Pmode, const0_rtx, Pmode, ! 1709: GEN_INT (size), Pmode); ! 1710: #else ! 1711: emit_library_call (bzero_libfunc, 0, ! 1712: VOIDmode, 2, ! 1713: XEXP (object, 0), Pmode, ! 1714: GEN_INT (size), Pmode); ! 1715: #endif ! 1716: } ! 1717: else ! 1718: emit_move_insn (object, const0_rtx); ! 1719: } ! 1720: ! 1721: /* Generate code to copy Y into X. ! 1722: Both Y and X must have the same mode, except that ! 1723: Y can be a constant with VOIDmode. ! 1724: This mode cannot be BLKmode; use emit_block_move for that. ! 1725: ! 1726: Return the last instruction emitted. */ ! 1727: ! 1728: rtx ! 1729: emit_move_insn (x, y) ! 1730: rtx x, y; ! 1731: { ! 1732: enum machine_mode mode = GET_MODE (x); ! 1733: enum machine_mode submode; ! 1734: enum mode_class class = GET_MODE_CLASS (mode); ! 1735: int i; ! 1736: ! 1737: x = protect_from_queue (x, 1); ! 1738: y = protect_from_queue (y, 0); ! 1739: ! 1740: if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode)) ! 1741: abort (); ! 1742: ! 1743: if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y)) ! 1744: y = force_const_mem (mode, y); ! 1745: ! 1746: /* If X or Y are memory references, verify that their addresses are valid ! 1747: for the machine. */ ! 1748: if (GET_CODE (x) == MEM ! 1749: && ((! memory_address_p (GET_MODE (x), XEXP (x, 0)) ! 1750: && ! push_operand (x, GET_MODE (x))) ! 1751: || (flag_force_addr ! 1752: && CONSTANT_ADDRESS_P (XEXP (x, 0))))) ! 1753: x = change_address (x, VOIDmode, XEXP (x, 0)); ! 1754: ! 1755: if (GET_CODE (y) == MEM ! 1756: && (! memory_address_p (GET_MODE (y), XEXP (y, 0)) ! 1757: || (flag_force_addr ! 1758: && CONSTANT_ADDRESS_P (XEXP (y, 0))))) ! 1759: y = change_address (y, VOIDmode, XEXP (y, 0)); ! 1760: ! 1761: if (mode == BLKmode) ! 1762: abort (); ! 1763: ! 1764: return emit_move_insn_1 (x, y); ! 1765: } ! 1766: ! 1767: /* Low level part of emit_move_insn. ! 1768: Called just like emit_move_insn, but assumes X and Y ! 1769: are basically valid. */ ! 1770: ! 1771: rtx ! 1772: emit_move_insn_1 (x, y) ! 1773: rtx x, y; ! 1774: { ! 1775: enum machine_mode mode = GET_MODE (x); ! 1776: enum machine_mode submode; ! 1777: enum mode_class class = GET_MODE_CLASS (mode); ! 1778: int i; ! 1779: ! 1780: if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) ! 1781: submode = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, ! 1782: (class == MODE_COMPLEX_INT ! 1783: ? MODE_INT : MODE_FLOAT), ! 1784: 0); ! 1785: ! 1786: if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 1787: return ! 1788: emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); ! 1789: ! 1790: /* Expand complex moves by moving real part and imag part, if possible. */ ! 1791: else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) ! 1792: && submode != BLKmode ! 1793: && (mov_optab->handlers[(int) submode].insn_code ! 1794: != CODE_FOR_nothing)) ! 1795: { ! 1796: /* Don't split destination if it is a stack push. */ ! 1797: int stack = push_operand (x, GET_MODE (x)); ! 1798: rtx prev = get_last_insn (); ! 1799: ! 1800: /* Tell flow that the whole of the destination is being set. */ ! 1801: if (GET_CODE (x) == REG) ! 1802: emit_insn (gen_rtx (CLOBBER, VOIDmode, x)); ! 1803: ! 1804: /* If this is a stack, push the highpart first, so it ! 1805: will be in the argument order. ! 1806: ! 1807: In that case, change_address is used only to convert ! 1808: the mode, not to change the address. */ ! 1809: if (stack) ! 1810: { ! 1811: /* Note that the real part always precedes the imag part in memory ! 1812: regardless of machine's endianness. */ ! 1813: #ifdef STACK_GROWS_DOWNWARD ! 1814: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1815: (gen_rtx (MEM, submode, (XEXP (x, 0))), ! 1816: gen_imagpart (submode, y))); ! 1817: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1818: (gen_rtx (MEM, submode, (XEXP (x, 0))), ! 1819: gen_realpart (submode, y))); ! 1820: #else ! 1821: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1822: (gen_rtx (MEM, submode, (XEXP (x, 0))), ! 1823: gen_realpart (submode, y))); ! 1824: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1825: (gen_rtx (MEM, submode, (XEXP (x, 0))), ! 1826: gen_imagpart (submode, y))); ! 1827: #endif ! 1828: } ! 1829: else ! 1830: { ! 1831: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1832: (gen_highpart (submode, x), gen_highpart (submode, y))); ! 1833: emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) ! 1834: (gen_lowpart (submode, x), gen_lowpart (submode, y))); ! 1835: } ! 1836: ! 1837: if (GET_CODE (x) != CONCAT) ! 1838: /* If X is a CONCAT, we got insns like RD = RS, ID = IS, ! 1839: each with a separate pseudo as destination. ! 1840: It's not correct for flow to treat them as a unit. */ ! 1841: group_insns (prev); ! 1842: ! 1843: return get_last_insn (); ! 1844: } ! 1845: ! 1846: /* This will handle any multi-word mode that lacks a move_insn pattern. ! 1847: However, you will get better code if you define such patterns, ! 1848: even if they must turn into multiple assembler instructions. */ ! 1849: else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ! 1850: { ! 1851: rtx last_insn = 0; ! 1852: rtx prev_insn = get_last_insn (); ! 1853: ! 1854: for (i = 0; ! 1855: i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; ! 1856: i++) ! 1857: { ! 1858: rtx xpart = operand_subword (x, i, 1, mode); ! 1859: rtx ypart = operand_subword (y, i, 1, mode); ! 1860: ! 1861: /* If we can't get a part of Y, put Y into memory if it is a ! 1862: constant. Otherwise, force it into a register. If we still ! 1863: can't get a part of Y, abort. */ ! 1864: if (ypart == 0 && CONSTANT_P (y)) ! 1865: { ! 1866: y = force_const_mem (mode, y); ! 1867: ypart = operand_subword (y, i, 1, mode); ! 1868: } ! 1869: else if (ypart == 0) ! 1870: ypart = operand_subword_force (y, i, mode); ! 1871: ! 1872: if (xpart == 0 || ypart == 0) ! 1873: abort (); ! 1874: ! 1875: last_insn = emit_move_insn (xpart, ypart); ! 1876: } ! 1877: /* Mark these insns as a libcall block. */ ! 1878: group_insns (prev_insn); ! 1879: ! 1880: return last_insn; ! 1881: } ! 1882: else ! 1883: abort (); ! 1884: } ! 1885: ! 1886: /* Pushing data onto the stack. */ ! 1887: ! 1888: /* Push a block of length SIZE (perhaps variable) ! 1889: and return an rtx to address the beginning of the block. ! 1890: Note that it is not possible for the value returned to be a QUEUED. ! 1891: The value may be virtual_outgoing_args_rtx. ! 1892: ! 1893: EXTRA is the number of bytes of padding to push in addition to SIZE. ! 1894: BELOW nonzero means this padding comes at low addresses; ! 1895: otherwise, the padding comes at high addresses. */ ! 1896: ! 1897: rtx ! 1898: push_block (size, extra, below) ! 1899: rtx size; ! 1900: int extra, below; ! 1901: { ! 1902: register rtx temp; ! 1903: if (CONSTANT_P (size)) ! 1904: anti_adjust_stack (plus_constant (size, extra)); ! 1905: else if (GET_CODE (size) == REG && extra == 0) ! 1906: anti_adjust_stack (size); ! 1907: else ! 1908: { ! 1909: rtx temp = copy_to_mode_reg (Pmode, size); ! 1910: if (extra != 0) ! 1911: temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra), ! 1912: temp, 0, OPTAB_LIB_WIDEN); ! 1913: anti_adjust_stack (temp); ! 1914: } ! 1915: ! 1916: #ifdef STACK_GROWS_DOWNWARD ! 1917: temp = virtual_outgoing_args_rtx; ! 1918: if (extra != 0 && below) ! 1919: temp = plus_constant (temp, extra); ! 1920: #else ! 1921: if (GET_CODE (size) == CONST_INT) ! 1922: temp = plus_constant (virtual_outgoing_args_rtx, ! 1923: - INTVAL (size) - (below ? 0 : extra)); ! 1924: else if (extra != 0 && !below) ! 1925: temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx, ! 1926: negate_rtx (Pmode, plus_constant (size, extra))); ! 1927: else ! 1928: temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx, ! 1929: negate_rtx (Pmode, size)); ! 1930: #endif ! 1931: ! 1932: return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp); ! 1933: } ! 1934: ! 1935: rtx ! 1936: gen_push_operand () ! 1937: { ! 1938: return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx); ! 1939: } ! 1940: ! 1941: /* Generate code to push X onto the stack, assuming it has mode MODE and ! 1942: type TYPE. ! 1943: MODE is redundant except when X is a CONST_INT (since they don't ! 1944: carry mode info). ! 1945: SIZE is an rtx for the size of data to be copied (in bytes), ! 1946: needed only if X is BLKmode. ! 1947: ! 1948: ALIGN (in bytes) is maximum alignment we can assume. ! 1949: ! 1950: If PARTIAL and REG are both nonzero, then copy that many of the first ! 1951: words of X into registers starting with REG, and push the rest of X. ! 1952: The amount of space pushed is decreased by PARTIAL words, ! 1953: rounded *down* to a multiple of PARM_BOUNDARY. ! 1954: REG must be a hard register in this case. ! 1955: If REG is zero but PARTIAL is not, take any all others actions for an ! 1956: argument partially in registers, but do not actually load any ! 1957: registers. ! 1958: ! 1959: EXTRA is the amount in bytes of extra space to leave next to this arg. ! 1960: This is ignored if an argument block has already been allocated. ! 1961: ! 1962: On a machine that lacks real push insns, ARGS_ADDR is the address of ! 1963: the bottom of the argument block for this call. We use indexing off there ! 1964: to store the arg. On machines with push insns, ARGS_ADDR is 0 when a ! 1965: argument block has not been preallocated. ! 1966: ! 1967: ARGS_SO_FAR is the size of args previously pushed for this call. */ ! 1968: ! 1969: void ! 1970: emit_push_insn (x, mode, type, size, align, partial, reg, extra, ! 1971: args_addr, args_so_far) ! 1972: register rtx x; ! 1973: enum machine_mode mode; ! 1974: tree type; ! 1975: rtx size; ! 1976: int align; ! 1977: int partial; ! 1978: rtx reg; ! 1979: int extra; ! 1980: rtx args_addr; ! 1981: rtx args_so_far; ! 1982: { ! 1983: rtx xinner; ! 1984: enum direction stack_direction ! 1985: #ifdef STACK_GROWS_DOWNWARD ! 1986: = downward; ! 1987: #else ! 1988: = upward; ! 1989: #endif ! 1990: ! 1991: /* Decide where to pad the argument: `downward' for below, ! 1992: `upward' for above, or `none' for don't pad it. ! 1993: Default is below for small data on big-endian machines; else above. */ ! 1994: enum direction where_pad = FUNCTION_ARG_PADDING (mode, type); ! 1995: ! 1996: /* Invert direction if stack is post-update. */ ! 1997: if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC) ! 1998: if (where_pad != none) ! 1999: where_pad = (where_pad == downward ? upward : downward); ! 2000: ! 2001: xinner = x = protect_from_queue (x, 0); ! 2002: ! 2003: if (mode == BLKmode) ! 2004: { ! 2005: /* Copy a block into the stack, entirely or partially. */ ! 2006: ! 2007: register rtx temp; ! 2008: int used = partial * UNITS_PER_WORD; ! 2009: int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); ! 2010: int skip; ! 2011: ! 2012: if (size == 0) ! 2013: abort (); ! 2014: ! 2015: used -= offset; ! 2016: ! 2017: /* USED is now the # of bytes we need not copy to the stack ! 2018: because registers will take care of them. */ ! 2019: ! 2020: if (partial != 0) ! 2021: xinner = change_address (xinner, BLKmode, ! 2022: plus_constant (XEXP (xinner, 0), used)); ! 2023: ! 2024: /* If the partial register-part of the arg counts in its stack size, ! 2025: skip the part of stack space corresponding to the registers. ! 2026: Otherwise, start copying to the beginning of the stack space, ! 2027: by setting SKIP to 0. */ ! 2028: #ifndef REG_PARM_STACK_SPACE ! 2029: skip = 0; ! 2030: #else ! 2031: skip = used; ! 2032: #endif ! 2033: ! 2034: #ifdef PUSH_ROUNDING ! 2035: /* Do it with several push insns if that doesn't take lots of insns ! 2036: and if there is no difficulty with push insns that skip bytes ! 2037: on the stack for alignment purposes. */ ! 2038: if (args_addr == 0 ! 2039: && GET_CODE (size) == CONST_INT ! 2040: && skip == 0 ! 2041: && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align) ! 2042: < MOVE_RATIO) ! 2043: /* Here we avoid the case of a structure whose weak alignment ! 2044: forces many pushes of a small amount of data, ! 2045: and such small pushes do rounding that causes trouble. */ ! 2046: && ((! STRICT_ALIGNMENT && ! SLOW_UNALIGNED_ACCESS) ! 2047: || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT ! 2048: || PUSH_ROUNDING (align) == align) ! 2049: && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size)) ! 2050: { ! 2051: /* Push padding now if padding above and stack grows down, ! 2052: or if padding below and stack grows up. ! 2053: But if space already allocated, this has already been done. */ ! 2054: if (extra && args_addr == 0 ! 2055: && where_pad != none && where_pad != stack_direction) ! 2056: anti_adjust_stack (GEN_INT (extra)); ! 2057: ! 2058: move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, ! 2059: INTVAL (size) - used, align); ! 2060: } ! 2061: else ! 2062: #endif /* PUSH_ROUNDING */ ! 2063: { ! 2064: /* Otherwise make space on the stack and copy the data ! 2065: to the address of that space. */ ! 2066: ! 2067: /* Deduct words put into registers from the size we must copy. */ ! 2068: if (partial != 0) ! 2069: { ! 2070: if (GET_CODE (size) == CONST_INT) ! 2071: size = GEN_INT (INTVAL (size) - used); ! 2072: else ! 2073: size = expand_binop (GET_MODE (size), sub_optab, size, ! 2074: GEN_INT (used), NULL_RTX, 0, ! 2075: OPTAB_LIB_WIDEN); ! 2076: } ! 2077: ! 2078: /* Get the address of the stack space. ! 2079: In this case, we do not deal with EXTRA separately. ! 2080: A single stack adjust will do. */ ! 2081: if (! args_addr) ! 2082: { ! 2083: temp = push_block (size, extra, where_pad == downward); ! 2084: extra = 0; ! 2085: } ! 2086: else if (GET_CODE (args_so_far) == CONST_INT) ! 2087: temp = memory_address (BLKmode, ! 2088: plus_constant (args_addr, ! 2089: skip + INTVAL (args_so_far))); ! 2090: else ! 2091: temp = memory_address (BLKmode, ! 2092: plus_constant (gen_rtx (PLUS, Pmode, ! 2093: args_addr, args_so_far), ! 2094: skip)); ! 2095: ! 2096: /* TEMP is the address of the block. Copy the data there. */ ! 2097: if (GET_CODE (size) == CONST_INT ! 2098: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) ! 2099: < MOVE_RATIO)) ! 2100: { ! 2101: move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner, ! 2102: INTVAL (size), align); ! 2103: goto ret; ! 2104: } ! 2105: /* Try the most limited insn first, because there's no point ! 2106: including more than one in the machine description unless ! 2107: the more limited one has some advantage. */ ! 2108: #ifdef HAVE_movstrqi ! 2109: if (HAVE_movstrqi ! 2110: && GET_CODE (size) == CONST_INT ! 2111: && ((unsigned) INTVAL (size) ! 2112: < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) ! 2113: { ! 2114: rtx pat = gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! 2115: xinner, size, GEN_INT (align)); ! 2116: if (pat != 0) ! 2117: { ! 2118: emit_insn (pat); ! 2119: goto ret; ! 2120: } ! 2121: } ! 2122: #endif ! 2123: #ifdef HAVE_movstrhi ! 2124: if (HAVE_movstrhi ! 2125: && GET_CODE (size) == CONST_INT ! 2126: && ((unsigned) INTVAL (size) ! 2127: < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) ! 2128: { ! 2129: rtx pat = gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! 2130: xinner, size, GEN_INT (align)); ! 2131: if (pat != 0) ! 2132: { ! 2133: emit_insn (pat); ! 2134: goto ret; ! 2135: } ! 2136: } ! 2137: #endif ! 2138: #ifdef HAVE_movstrsi ! 2139: if (HAVE_movstrsi) ! 2140: { ! 2141: rtx pat = gen_movstrsi (gen_rtx (MEM, BLKmode, temp), ! 2142: xinner, size, GEN_INT (align)); ! 2143: if (pat != 0) ! 2144: { ! 2145: emit_insn (pat); ! 2146: goto ret; ! 2147: } ! 2148: } ! 2149: #endif ! 2150: #ifdef HAVE_movstrdi ! 2151: if (HAVE_movstrdi) ! 2152: { ! 2153: rtx pat = gen_movstrdi (gen_rtx (MEM, BLKmode, temp), ! 2154: xinner, size, GEN_INT (align)); ! 2155: if (pat != 0) ! 2156: { ! 2157: emit_insn (pat); ! 2158: goto ret; ! 2159: } ! 2160: } ! 2161: #endif ! 2162: ! 2163: #ifndef ACCUMULATE_OUTGOING_ARGS ! 2164: /* If the source is referenced relative to the stack pointer, ! 2165: copy it to another register to stabilize it. We do not need ! 2166: to do this if we know that we won't be changing sp. */ ! 2167: ! 2168: if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp) ! 2169: || reg_mentioned_p (virtual_outgoing_args_rtx, temp)) ! 2170: temp = copy_to_reg (temp); ! 2171: #endif ! 2172: ! 2173: /* Make inhibit_defer_pop nonzero around the library call ! 2174: to force it to pop the bcopy-arguments right away. */ ! 2175: NO_DEFER_POP; ! 2176: #ifdef TARGET_MEM_FUNCTIONS ! 2177: emit_library_call (memcpy_libfunc, 0, ! 2178: VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode, ! 2179: convert_to_mode (TYPE_MODE (sizetype), ! 2180: size, TREE_UNSIGNED (sizetype)), ! 2181: TYPE_MODE (sizetype)); ! 2182: #else ! 2183: emit_library_call (bcopy_libfunc, 0, ! 2184: VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode, ! 2185: convert_to_mode (TYPE_MODE (sizetype), ! 2186: size, TREE_UNSIGNED (sizetype)), ! 2187: TYPE_MODE (sizetype)); ! 2188: #endif ! 2189: OK_DEFER_POP; ! 2190: } ! 2191: } ! 2192: else if (partial > 0) ! 2193: { ! 2194: /* Scalar partly in registers. */ ! 2195: ! 2196: int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD; ! 2197: int i; ! 2198: int not_stack; ! 2199: /* # words of start of argument ! 2200: that we must make space for but need not store. */ ! 2201: int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD); ! 2202: int args_offset = INTVAL (args_so_far); ! 2203: int skip; ! 2204: ! 2205: /* Push padding now if padding above and stack grows down, ! 2206: or if padding below and stack grows up. ! 2207: But if space already allocated, this has already been done. */ ! 2208: if (extra && args_addr == 0 ! 2209: && where_pad != none && where_pad != stack_direction) ! 2210: anti_adjust_stack (GEN_INT (extra)); ! 2211: ! 2212: /* If we make space by pushing it, we might as well push ! 2213: the real data. Otherwise, we can leave OFFSET nonzero ! 2214: and leave the space uninitialized. */ ! 2215: if (args_addr == 0) ! 2216: offset = 0; ! 2217: ! 2218: /* Now NOT_STACK gets the number of words that we don't need to ! 2219: allocate on the stack. */ ! 2220: not_stack = partial - offset; ! 2221: ! 2222: /* If the partial register-part of the arg counts in its stack size, ! 2223: skip the part of stack space corresponding to the registers. ! 2224: Otherwise, start copying to the beginning of the stack space, ! 2225: by setting SKIP to 0. */ ! 2226: #ifndef REG_PARM_STACK_SPACE ! 2227: skip = 0; ! 2228: #else ! 2229: skip = not_stack; ! 2230: #endif ! 2231: ! 2232: if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x)) ! 2233: x = validize_mem (force_const_mem (mode, x)); ! 2234: ! 2235: /* If X is a hard register in a non-integer mode, copy it into a pseudo; ! 2236: SUBREGs of such registers are not allowed. */ ! 2237: if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER ! 2238: && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT)) ! 2239: x = copy_to_reg (x); ! 2240: ! 2241: /* Loop over all the words allocated on the stack for this arg. */ ! 2242: /* We can do it by words, because any scalar bigger than a word ! 2243: has a size a multiple of a word. */ ! 2244: #ifndef PUSH_ARGS_REVERSED ! 2245: for (i = not_stack; i < size; i++) ! 2246: #else ! 2247: for (i = size - 1; i >= not_stack; i--) ! 2248: #endif ! 2249: if (i >= not_stack + offset) ! 2250: emit_push_insn (operand_subword_force (x, i, mode), ! 2251: word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX, ! 2252: 0, args_addr, ! 2253: GEN_INT (args_offset + ((i - not_stack + skip) ! 2254: * UNITS_PER_WORD))); ! 2255: } ! 2256: else ! 2257: { ! 2258: rtx addr; ! 2259: ! 2260: /* Push padding now if padding above and stack grows down, ! 2261: or if padding below and stack grows up. ! 2262: But if space already allocated, this has already been done. */ ! 2263: if (extra && args_addr == 0 ! 2264: && where_pad != none && where_pad != stack_direction) ! 2265: anti_adjust_stack (GEN_INT (extra)); ! 2266: ! 2267: #ifdef PUSH_ROUNDING ! 2268: if (args_addr == 0) ! 2269: addr = gen_push_operand (); ! 2270: else ! 2271: #endif ! 2272: if (GET_CODE (args_so_far) == CONST_INT) ! 2273: addr ! 2274: = memory_address (mode, ! 2275: plus_constant (args_addr, INTVAL (args_so_far))); ! 2276: else ! 2277: addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr, ! 2278: args_so_far)); ! 2279: ! 2280: emit_move_insn (gen_rtx (MEM, mode, addr), x); ! 2281: } ! 2282: ! 2283: ret: ! 2284: /* If part should go in registers, copy that part ! 2285: into the appropriate registers. Do this now, at the end, ! 2286: since mem-to-mem copies above may do function calls. */ ! 2287: if (partial > 0 && reg != 0) ! 2288: move_block_to_reg (REGNO (reg), x, partial, mode); ! 2289: ! 2290: if (extra && args_addr == 0 && where_pad == stack_direction) ! 2291: anti_adjust_stack (GEN_INT (extra)); ! 2292: } ! 2293: ! 2294: /* Expand an assignment that stores the value of FROM into TO. ! 2295: If WANT_VALUE is nonzero, return an rtx for the value of TO. ! 2296: (This may contain a QUEUED rtx; ! 2297: if the value is constant, this rtx is a constant.) ! 2298: Otherwise, the returned value is NULL_RTX. ! 2299: ! 2300: SUGGEST_REG is no longer actually used. ! 2301: It used to mean, copy the value through a register ! 2302: and return that register, if that is possible. ! 2303: We now use WANT_VALUE to decide whether to do this. */ ! 2304: ! 2305: rtx ! 2306: expand_assignment (to, from, want_value, suggest_reg) ! 2307: tree to, from; ! 2308: int want_value; ! 2309: int suggest_reg; ! 2310: { ! 2311: register rtx to_rtx = 0; ! 2312: rtx result; ! 2313: ! 2314: /* Don't crash if the lhs of the assignment was erroneous. */ ! 2315: ! 2316: if (TREE_CODE (to) == ERROR_MARK) ! 2317: { ! 2318: result = expand_expr (from, NULL_RTX, VOIDmode, 0); ! 2319: return want_value ? result : NULL_RTX; ! 2320: } ! 2321: ! 2322: if (output_bytecode) ! 2323: { ! 2324: tree dest_innermost; ! 2325: ! 2326: bc_expand_expr (from); ! 2327: bc_emit_instruction (duplicate); ! 2328: ! 2329: dest_innermost = bc_expand_address (to); ! 2330: ! 2331: /* Can't deduce from TYPE that we're dealing with a bitfield, so ! 2332: take care of it here. */ ! 2333: ! 2334: bc_store_memory (TREE_TYPE (to), dest_innermost); ! 2335: return NULL; ! 2336: } ! 2337: ! 2338: /* Assignment of a structure component needs special treatment ! 2339: if the structure component's rtx is not simply a MEM. ! 2340: Assignment of an array element at a constant index ! 2341: has the same problem. */ ! 2342: ! 2343: if (TREE_CODE (to) == COMPONENT_REF ! 2344: || TREE_CODE (to) == BIT_FIELD_REF ! 2345: || (TREE_CODE (to) == ARRAY_REF ! 2346: && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST ! 2347: && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST)) ! 2348: { ! 2349: enum machine_mode mode1; ! 2350: int bitsize; ! 2351: int bitpos; ! 2352: tree offset; ! 2353: int unsignedp; ! 2354: int volatilep = 0; ! 2355: tree tem; ! 2356: int alignment; ! 2357: ! 2358: push_temp_slots (); ! 2359: tem = get_inner_reference (to, &bitsize, &bitpos, &offset, ! 2360: &mode1, &unsignedp, &volatilep); ! 2361: ! 2362: /* If we are going to use store_bit_field and extract_bit_field, ! 2363: make sure to_rtx will be safe for multiple use. */ ! 2364: ! 2365: if (mode1 == VOIDmode && want_value) ! 2366: tem = stabilize_reference (tem); ! 2367: ! 2368: alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT; ! 2369: to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0); ! 2370: if (offset != 0) ! 2371: { ! 2372: rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); ! 2373: ! 2374: if (GET_CODE (to_rtx) != MEM) ! 2375: abort (); ! 2376: to_rtx = change_address (to_rtx, VOIDmode, ! 2377: gen_rtx (PLUS, Pmode, XEXP (to_rtx, 0), ! 2378: force_reg (Pmode, offset_rtx))); ! 2379: /* If we have a variable offset, the known alignment ! 2380: is only that of the innermost structure containing the field. ! 2381: (Actually, we could sometimes do better by using the ! 2382: align of an element of the innermost array, but no need.) */ ! 2383: if (TREE_CODE (to) == COMPONENT_REF ! 2384: || TREE_CODE (to) == BIT_FIELD_REF) ! 2385: alignment ! 2386: = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (to, 0))) / BITS_PER_UNIT; ! 2387: } ! 2388: if (volatilep) ! 2389: { ! 2390: if (GET_CODE (to_rtx) == MEM) ! 2391: MEM_VOLATILE_P (to_rtx) = 1; ! 2392: #if 0 /* This was turned off because, when a field is volatile ! 2393: in an object which is not volatile, the object may be in a register, ! 2394: and then we would abort over here. */ ! 2395: else ! 2396: abort (); ! 2397: #endif ! 2398: } ! 2399: ! 2400: ! 2401: /* ! 2402: if (TREE_SELF_OFFSET (TREE_OPERAND (to, 1))) ! 2403: { ! 2404: from = build_binary_op (MINUS_EXPR, from, ! 2405: build1 (ADDR_EXPR, TREE_TYPE (to), to)); ! 2406: } ! 2407: */ ! 2408: ! 2409: result = store_field (to_rtx, bitsize, bitpos, mode1, from, ! 2410: (want_value ! 2411: /* Spurious cast makes HPUX compiler happy. */ ! 2412: ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to)) ! 2413: : VOIDmode), ! 2414: unsignedp, ! 2415: /* Required alignment of containing datum. */ ! 2416: alignment, ! 2417: int_size_in_bytes (TREE_TYPE (tem))); ! 2418: preserve_temp_slots (result); ! 2419: free_temp_slots (); ! 2420: pop_temp_slots (); ! 2421: ! 2422: /* If the value is meaningful, convert RESULT to the proper mode. ! 2423: Otherwise, return nothing. */ ! 2424: return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)), ! 2425: TYPE_MODE (TREE_TYPE (from)), ! 2426: result, ! 2427: TREE_UNSIGNED (TREE_TYPE (to))) ! 2428: : NULL_RTX); ! 2429: } ! 2430: ! 2431: /* If the rhs is a function call and its value is not an aggregate, ! 2432: call the function before we start to compute the lhs. ! 2433: This is needed for correct code for cases such as ! 2434: val = setjmp (buf) on machines where reference to val ! 2435: requires loading up part of an address in a separate insn. ! 2436: ! 2437: Don't do this if TO is a VAR_DECL whose DECL_RTL is REG since it might be ! 2438: a promoted variable where the zero- or sign- extension needs to be done. ! 2439: Handling this in the normal way is safe because no computation is done ! 2440: before the call. */ ! 2441: if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from) ! 2442: && ! (TREE_CODE (to) == VAR_DECL && GET_CODE (DECL_RTL (to)) == REG)) ! 2443: { ! 2444: rtx value; ! 2445: ! 2446: push_temp_slots (); ! 2447: value = expand_expr (from, NULL_RTX, VOIDmode, 0); ! 2448: if (to_rtx == 0) ! 2449: to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_CONST_ADDRESS); ! 2450: ! 2451: emit_move_insn (to_rtx, value); ! 2452: preserve_temp_slots (to_rtx); ! 2453: free_temp_slots (); ! 2454: pop_temp_slots (); ! 2455: return want_value ? to_rtx : NULL_RTX; ! 2456: } ! 2457: ! 2458: /* Ordinary treatment. Expand TO to get a REG or MEM rtx. ! 2459: Don't re-expand if it was expanded already (in COMPONENT_REF case). */ ! 2460: ! 2461: if (to_rtx == 0) ! 2462: to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_CONST_ADDRESS); ! 2463: ! 2464: /* ! 2465: if (TREE_SELF_OFFSET (to)) ! 2466: { ! 2467: from = build_binary_op (MINUS_EXPR, from, ! 2468: build1 (ADDR_EXPR, TREE_TYPE (to), to)); ! 2469: } ! 2470: */ ! 2471: ! 2472: /* Don't move directly into a return register. */ ! 2473: if (TREE_CODE (to) == RESULT_DECL && GET_CODE (to_rtx) == REG) ! 2474: { ! 2475: rtx temp; ! 2476: ! 2477: push_temp_slots (); ! 2478: temp = expand_expr (from, 0, GET_MODE (to_rtx), 0); ! 2479: emit_move_insn (to_rtx, temp); ! 2480: preserve_temp_slots (to_rtx); ! 2481: free_temp_slots (); ! 2482: pop_temp_slots (); ! 2483: return want_value ? to_rtx : NULL_RTX; ! 2484: } ! 2485: ! 2486: /* In case we are returning the contents of an object which overlaps ! 2487: the place the value is being stored, use a safe function when copying ! 2488: a value through a pointer into a structure value return block. */ ! 2489: if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF ! 2490: && current_function_returns_struct ! 2491: && !current_function_returns_pcc_struct) ! 2492: { ! 2493: rtx from_rtx, size; ! 2494: ! 2495: push_temp_slots (); ! 2496: size = expr_size (from); ! 2497: from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0); ! 2498: ! 2499: #ifdef TARGET_MEM_FUNCTIONS ! 2500: emit_library_call (memcpy_libfunc, 0, ! 2501: VOIDmode, 3, XEXP (to_rtx, 0), Pmode, ! 2502: XEXP (from_rtx, 0), Pmode, ! 2503: convert_to_mode (TYPE_MODE (sizetype), ! 2504: size, TREE_UNSIGNED (sizetype)), ! 2505: TYPE_MODE (sizetype)); ! 2506: #else ! 2507: emit_library_call (bcopy_libfunc, 0, ! 2508: VOIDmode, 3, XEXP (from_rtx, 0), Pmode, ! 2509: XEXP (to_rtx, 0), Pmode, ! 2510: convert_to_mode (TYPE_MODE (sizetype), ! 2511: size, TREE_UNSIGNED (sizetype)), ! 2512: TYPE_MODE (sizetype)); ! 2513: #endif ! 2514: ! 2515: preserve_temp_slots (to_rtx); ! 2516: free_temp_slots (); ! 2517: pop_temp_slots (); ! 2518: return want_value ? to_rtx : NULL_RTX; ! 2519: } ! 2520: ! 2521: /* Compute FROM and store the value in the rtx we got. */ ! 2522: ! 2523: push_temp_slots (); ! 2524: result = store_expr (from, to_rtx, want_value); ! 2525: preserve_temp_slots (result); ! 2526: free_temp_slots (); ! 2527: pop_temp_slots (); ! 2528: return want_value ? result : NULL_RTX; ! 2529: } ! 2530: ! 2531: /* Generate code for computing expression EXP, ! 2532: and storing the value into TARGET. ! 2533: TARGET may contain a QUEUED rtx. ! 2534: ! 2535: If WANT_VALUE is nonzero, return a copy of the value ! 2536: not in TARGET, so that we can be sure to use the proper ! 2537: value in a containing expression even if TARGET has something ! 2538: else stored in it. If possible, we copy the value through a pseudo ! 2539: and return that pseudo. Or, if the value is constant, we try to ! 2540: return the constant. In some cases, we return a pseudo ! 2541: copied *from* TARGET. ! 2542: ! 2543: If the mode is BLKmode then we may return TARGET itself. ! 2544: It turns out that in BLKmode it doesn't cause a problem. ! 2545: because C has no operators that could combine two different ! 2546: assignments into the same BLKmode object with different values ! 2547: with no sequence point. Will other languages need this to ! 2548: be more thorough? ! 2549: ! 2550: If WANT_VALUE is 0, we return NULL, to make sure ! 2551: to catch quickly any cases where the caller uses the value ! 2552: and fails to set WANT_VALUE. */ ! 2553: ! 2554: rtx ! 2555: store_expr (exp, target, want_value) ! 2556: register tree exp; ! 2557: register rtx target; ! 2558: int want_value; ! 2559: { ! 2560: register rtx temp; ! 2561: int dont_return_target = 0; ! 2562: ! 2563: if (TREE_CODE (exp) == COMPOUND_EXPR) ! 2564: { ! 2565: /* Perform first part of compound expression, then assign from second ! 2566: part. */ ! 2567: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 2568: emit_queue (); ! 2569: return store_expr (TREE_OPERAND (exp, 1), target, want_value); ! 2570: } ! 2571: else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode) ! 2572: { ! 2573: /* For conditional expression, get safe form of the target. Then ! 2574: test the condition, doing the appropriate assignment on either ! 2575: side. This avoids the creation of unnecessary temporaries. ! 2576: For non-BLKmode, it is more efficient not to do this. */ ! 2577: ! 2578: rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx (); ! 2579: ! 2580: emit_queue (); ! 2581: target = protect_from_queue (target, 1); ! 2582: ! 2583: NO_DEFER_POP; ! 2584: jumpifnot (TREE_OPERAND (exp, 0), lab1); ! 2585: store_expr (TREE_OPERAND (exp, 1), target, 0); ! 2586: emit_queue (); ! 2587: emit_jump_insn (gen_jump (lab2)); ! 2588: emit_barrier (); ! 2589: emit_label (lab1); ! 2590: store_expr (TREE_OPERAND (exp, 2), target, 0); ! 2591: emit_queue (); ! 2592: emit_label (lab2); ! 2593: OK_DEFER_POP; ! 2594: return want_value ? target : NULL_RTX; ! 2595: } ! 2596: else if (want_value && GET_CODE (target) == MEM && ! MEM_VOLATILE_P (target) ! 2597: && GET_MODE (target) != BLKmode) ! 2598: /* If target is in memory and caller wants value in a register instead, ! 2599: arrange that. Pass TARGET as target for expand_expr so that, ! 2600: if EXP is another assignment, WANT_VALUE will be nonzero for it. ! 2601: We know expand_expr will not use the target in that case. ! 2602: Don't do this if TARGET is volatile because we are supposed ! 2603: to write it and then read it. */ ! 2604: { ! 2605: temp = expand_expr (exp, cse_not_expected ? NULL_RTX : target, ! 2606: GET_MODE (target), 0); ! 2607: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) ! 2608: temp = copy_to_reg (temp); ! 2609: dont_return_target = 1; ! 2610: } ! 2611: else if (queued_subexp_p (target)) ! 2612: /* If target contains a postincrement, let's not risk ! 2613: using it as the place to generate the rhs. */ ! 2614: { ! 2615: if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode) ! 2616: { ! 2617: /* Expand EXP into a new pseudo. */ ! 2618: temp = gen_reg_rtx (GET_MODE (target)); ! 2619: temp = expand_expr (exp, temp, GET_MODE (target), 0); ! 2620: } ! 2621: else ! 2622: temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0); ! 2623: ! 2624: /* If target is volatile, ANSI requires accessing the value ! 2625: *from* the target, if it is accessed. So make that happen. ! 2626: In no case return the target itself. */ ! 2627: if (! MEM_VOLATILE_P (target) && want_value) ! 2628: dont_return_target = 1; ! 2629: } ! 2630: else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target)) ! 2631: /* If this is an scalar in a register that is stored in a wider mode ! 2632: than the declared mode, compute the result into its declared mode ! 2633: and then convert to the wider mode. Our value is the computed ! 2634: expression. */ ! 2635: { ! 2636: temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); ! 2637: ! 2638: /* If TEMP is a VOIDmode constant, use convert_modes to make ! 2639: sure that we properly convert it. */ ! 2640: if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode) ! 2641: temp = convert_modes (GET_MODE (SUBREG_REG (target)), ! 2642: TYPE_MODE (TREE_TYPE (exp)), temp, ! 2643: SUBREG_PROMOTED_UNSIGNED_P (target)); ! 2644: ! 2645: convert_move (SUBREG_REG (target), temp, ! 2646: SUBREG_PROMOTED_UNSIGNED_P (target)); ! 2647: return want_value ? temp : NULL_RTX; ! 2648: } ! 2649: else ! 2650: { ! 2651: temp = expand_expr (exp, target, GET_MODE (target), 0); ! 2652: /* DO return TARGET if it's a specified hardware register. ! 2653: expand_return relies on this. ! 2654: If TARGET is a volatile mem ref, either return TARGET ! 2655: or return a reg copied *from* TARGET; ANSI requires this. ! 2656: ! 2657: Otherwise, if TEMP is not TARGET, return TEMP ! 2658: if it is constant (for efficiency), ! 2659: or if we really want the correct value. */ ! 2660: if (!(target && GET_CODE (target) == REG ! 2661: && REGNO (target) < FIRST_PSEUDO_REGISTER) ! 2662: && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) ! 2663: && temp != target ! 2664: && (CONSTANT_P (temp) || want_value)) ! 2665: dont_return_target = 1; ! 2666: } ! 2667: ! 2668: /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not ! 2669: the same as that of TARGET, adjust the constant. This is needed, for ! 2670: example, in case it is a CONST_DOUBLE and we want only a word-sized ! 2671: value. */ ! 2672: if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode ! 2673: && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) ! 2674: temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)), ! 2675: temp, TREE_UNSIGNED (TREE_TYPE (exp))); ! 2676: ! 2677: /* If value was not generated in the target, store it there. ! 2678: Convert the value to TARGET's type first if nec. */ ! 2679: ! 2680: if (temp != target && TREE_CODE (exp) != ERROR_MARK) ! 2681: { ! 2682: target = protect_from_queue (target, 1); ! 2683: if (GET_MODE (temp) != GET_MODE (target) ! 2684: && GET_MODE (temp) != VOIDmode) ! 2685: { ! 2686: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 2687: if (dont_return_target) ! 2688: { ! 2689: /* In this case, we will return TEMP, ! 2690: so make sure it has the proper mode. ! 2691: But don't forget to store the value into TARGET. */ ! 2692: temp = convert_to_mode (GET_MODE (target), temp, unsignedp); ! 2693: emit_move_insn (target, temp); ! 2694: } ! 2695: else ! 2696: convert_move (target, temp, unsignedp); ! 2697: } ! 2698: ! 2699: else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST) ! 2700: { ! 2701: /* Handle copying a string constant into an array. ! 2702: The string constant may be shorter than the array. ! 2703: So copy just the string's actual length, and clear the rest. */ ! 2704: rtx size; ! 2705: ! 2706: /* Get the size of the data type of the string, ! 2707: which is actually the size of the target. */ ! 2708: size = expr_size (exp); ! 2709: if (GET_CODE (size) == CONST_INT ! 2710: && INTVAL (size) < TREE_STRING_LENGTH (exp)) ! 2711: emit_block_move (target, temp, size, ! 2712: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 2713: else ! 2714: { ! 2715: /* Compute the size of the data to copy from the string. */ ! 2716: tree copy_size ! 2717: = size_binop (MIN_EXPR, ! 2718: make_tree (sizetype, size), ! 2719: convert (sizetype, ! 2720: build_int_2 (TREE_STRING_LENGTH (exp), 0))); ! 2721: rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX, ! 2722: VOIDmode, 0); ! 2723: rtx label = 0; ! 2724: ! 2725: /* Copy that much. */ ! 2726: emit_block_move (target, temp, copy_size_rtx, ! 2727: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 2728: ! 2729: /* Figure out how much is left in TARGET ! 2730: that we have to clear. */ ! 2731: if (GET_CODE (copy_size_rtx) == CONST_INT) ! 2732: { ! 2733: temp = plus_constant (XEXP (target, 0), ! 2734: TREE_STRING_LENGTH (exp)); ! 2735: size = plus_constant (size, ! 2736: - TREE_STRING_LENGTH (exp)); ! 2737: } ! 2738: else ! 2739: { ! 2740: enum machine_mode size_mode = Pmode; ! 2741: ! 2742: temp = force_reg (Pmode, XEXP (target, 0)); ! 2743: temp = expand_binop (size_mode, add_optab, temp, ! 2744: copy_size_rtx, NULL_RTX, 0, ! 2745: OPTAB_LIB_WIDEN); ! 2746: ! 2747: size = expand_binop (size_mode, sub_optab, size, ! 2748: copy_size_rtx, NULL_RTX, 0, ! 2749: OPTAB_LIB_WIDEN); ! 2750: ! 2751: emit_cmp_insn (size, const0_rtx, LT, NULL_RTX, ! 2752: GET_MODE (size), 0, 0); ! 2753: label = gen_label_rtx (); ! 2754: emit_jump_insn (gen_blt (label)); ! 2755: } ! 2756: ! 2757: if (size != const0_rtx) ! 2758: { ! 2759: #ifdef TARGET_MEM_FUNCTIONS ! 2760: emit_library_call (memset_libfunc, 0, VOIDmode, 3, ! 2761: temp, Pmode, const0_rtx, Pmode, size, Pmode); ! 2762: #else ! 2763: emit_library_call (bzero_libfunc, 0, VOIDmode, 2, ! 2764: temp, Pmode, size, Pmode); ! 2765: #endif ! 2766: } ! 2767: if (label) ! 2768: emit_label (label); ! 2769: } ! 2770: } ! 2771: else if (GET_MODE (temp) == BLKmode) ! 2772: emit_block_move (target, temp, expr_size (exp), ! 2773: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 2774: else ! 2775: emit_move_insn (target, temp); ! 2776: } ! 2777: ! 2778: if (dont_return_target && GET_CODE (temp) != MEM) ! 2779: return temp; ! 2780: if (want_value && GET_MODE (target) != BLKmode) ! 2781: return copy_to_reg (target); ! 2782: if (want_value) ! 2783: return target; ! 2784: return NULL_RTX; ! 2785: } ! 2786: ! 2787: /* Store the value of constructor EXP into the rtx TARGET. ! 2788: TARGET is either a REG or a MEM. */ ! 2789: ! 2790: static void ! 2791: store_constructor (exp, target) ! 2792: tree exp; ! 2793: rtx target; ! 2794: { ! 2795: tree type = TREE_TYPE (exp); ! 2796: ! 2797: /* We know our target cannot conflict, since safe_from_p has been called. */ ! 2798: #if 0 ! 2799: /* Don't try copying piece by piece into a hard register ! 2800: since that is vulnerable to being clobbered by EXP. ! 2801: Instead, construct in a pseudo register and then copy it all. */ ! 2802: if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER) ! 2803: { ! 2804: rtx temp = gen_reg_rtx (GET_MODE (target)); ! 2805: store_constructor (exp, temp); ! 2806: emit_move_insn (target, temp); ! 2807: return; ! 2808: } ! 2809: #endif ! 2810: ! 2811: if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE ! 2812: || TREE_CODE (type) == QUAL_UNION_TYPE) ! 2813: { ! 2814: register tree elt; ! 2815: ! 2816: /* Inform later passes that the whole union value is dead. */ ! 2817: if (TREE_CODE (type) == UNION_TYPE ! 2818: || TREE_CODE (type) == QUAL_UNION_TYPE) ! 2819: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2820: ! 2821: /* If we are building a static constructor into a register, ! 2822: set the initial value as zero so we can fold the value into ! 2823: a constant. */ ! 2824: else if (GET_CODE (target) == REG && TREE_STATIC (exp)) ! 2825: emit_move_insn (target, const0_rtx); ! 2826: ! 2827: /* If the constructor has fewer fields than the structure, ! 2828: clear the whole structure first. */ ! 2829: else if (list_length (CONSTRUCTOR_ELTS (exp)) ! 2830: != list_length (TYPE_FIELDS (type))) ! 2831: clear_storage (target, int_size_in_bytes (type)); ! 2832: else ! 2833: /* Inform later passes that the old value is dead. */ ! 2834: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2835: ! 2836: /* Store each element of the constructor into ! 2837: the corresponding field of TARGET. */ ! 2838: ! 2839: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 2840: { ! 2841: register tree field = TREE_PURPOSE (elt); ! 2842: register enum machine_mode mode; ! 2843: int bitsize; ! 2844: int bitpos = 0; ! 2845: int unsignedp; ! 2846: tree pos, constant = 0, offset = 0; ! 2847: rtx to_rtx = target; ! 2848: ! 2849: /* Just ignore missing fields. ! 2850: We cleared the whole structure, above, ! 2851: if any fields are missing. */ ! 2852: if (field == 0) ! 2853: continue; ! 2854: ! 2855: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); ! 2856: unsignedp = TREE_UNSIGNED (field); ! 2857: mode = DECL_MODE (field); ! 2858: if (DECL_BIT_FIELD (field)) ! 2859: mode = VOIDmode; ! 2860: ! 2861: pos = DECL_FIELD_BITPOS (field); ! 2862: if (TREE_CODE (pos) == INTEGER_CST) ! 2863: constant = pos; ! 2864: else if (TREE_CODE (pos) == PLUS_EXPR ! 2865: && TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST) ! 2866: constant = TREE_OPERAND (pos, 1), offset = TREE_OPERAND (pos, 0); ! 2867: else ! 2868: offset = pos; ! 2869: ! 2870: if (constant) ! 2871: bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); ! 2872: ! 2873: if (offset) ! 2874: { ! 2875: rtx offset_rtx; ! 2876: ! 2877: if (contains_placeholder_p (offset)) ! 2878: offset = build (WITH_RECORD_EXPR, sizetype, ! 2879: offset, exp); ! 2880: ! 2881: offset = size_binop (FLOOR_DIV_EXPR, offset, ! 2882: size_int (BITS_PER_UNIT)); ! 2883: ! 2884: offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); ! 2885: if (GET_CODE (to_rtx) != MEM) ! 2886: abort (); ! 2887: ! 2888: to_rtx ! 2889: = change_address (to_rtx, VOIDmode, ! 2890: gen_rtx (PLUS, Pmode, XEXP (to_rtx, 0), ! 2891: force_reg (Pmode, offset_rtx))); ! 2892: } ! 2893: ! 2894: store_field (to_rtx, bitsize, bitpos, mode, TREE_VALUE (elt), ! 2895: /* The alignment of TARGET is ! 2896: at least what its type requires. */ ! 2897: VOIDmode, 0, ! 2898: TYPE_ALIGN (type) / BITS_PER_UNIT, ! 2899: int_size_in_bytes (type)); ! 2900: } ! 2901: } ! 2902: else if (TREE_CODE (type) == ARRAY_TYPE) ! 2903: { ! 2904: register tree elt; ! 2905: register int i; ! 2906: tree domain = TYPE_DOMAIN (type); ! 2907: HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! 2908: HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); ! 2909: tree elttype = TREE_TYPE (type); ! 2910: ! 2911: /* If the constructor has fewer fields than the structure, ! 2912: clear the whole structure first. Similarly if this this is ! 2913: static constructor of a non-BLKmode object. */ ! 2914: ! 2915: if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1 ! 2916: || (GET_CODE (target) == REG && TREE_STATIC (exp))) ! 2917: clear_storage (target, int_size_in_bytes (type)); ! 2918: else ! 2919: /* Inform later passes that the old value is dead. */ ! 2920: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 2921: ! 2922: /* Store each element of the constructor into ! 2923: the corresponding element of TARGET, determined ! 2924: by counting the elements. */ ! 2925: for (elt = CONSTRUCTOR_ELTS (exp), i = 0; ! 2926: elt; ! 2927: elt = TREE_CHAIN (elt), i++) ! 2928: { ! 2929: register enum machine_mode mode; ! 2930: int bitsize; ! 2931: int bitpos; ! 2932: int unsignedp; ! 2933: tree index = TREE_PURPOSE (elt); ! 2934: rtx xtarget = target; ! 2935: ! 2936: mode = TYPE_MODE (elttype); ! 2937: bitsize = GET_MODE_BITSIZE (mode); ! 2938: unsignedp = TREE_UNSIGNED (elttype); ! 2939: ! 2940: if (index != 0 && TREE_CODE (index) != INTEGER_CST) ! 2941: { ! 2942: /* We don't currently allow variable indices in a ! 2943: C initializer, but let's try here to support them. */ ! 2944: rtx pos_rtx, addr, xtarget; ! 2945: tree position; ! 2946: ! 2947: position = size_binop (MULT_EXPR, index, TYPE_SIZE (elttype)); ! 2948: pos_rtx = expand_expr (position, 0, VOIDmode, 0); ! 2949: addr = gen_rtx (PLUS, Pmode, XEXP (target, 0), pos_rtx); ! 2950: xtarget = change_address (target, mode, addr); ! 2951: store_expr (TREE_VALUE (elt), xtarget, 0); ! 2952: } ! 2953: else ! 2954: { ! 2955: if (index != 0) ! 2956: bitpos = ((TREE_INT_CST_LOW (index) - minelt) ! 2957: * TREE_INT_CST_LOW (TYPE_SIZE (elttype))); ! 2958: else ! 2959: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))); ! 2960: ! 2961: store_field (xtarget, bitsize, bitpos, mode, TREE_VALUE (elt), ! 2962: /* The alignment of TARGET is ! 2963: at least what its type requires. */ ! 2964: VOIDmode, 0, ! 2965: TYPE_ALIGN (type) / BITS_PER_UNIT, ! 2966: int_size_in_bytes (type)); ! 2967: } ! 2968: } ! 2969: } ! 2970: ! 2971: else ! 2972: abort (); ! 2973: } ! 2974: ! 2975: /* Store the value of EXP (an expression tree) ! 2976: into a subfield of TARGET which has mode MODE and occupies ! 2977: BITSIZE bits, starting BITPOS bits from the start of TARGET. ! 2978: If MODE is VOIDmode, it means that we are storing into a bit-field. ! 2979: ! 2980: If VALUE_MODE is VOIDmode, return nothing in particular. ! 2981: UNSIGNEDP is not used in this case. ! 2982: ! 2983: Otherwise, return an rtx for the value stored. This rtx ! 2984: has mode VALUE_MODE if that is convenient to do. ! 2985: In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. ! 2986: ! 2987: ALIGN is the alignment that TARGET is known to have, measured in bytes. ! 2988: TOTAL_SIZE is the size in bytes of the structure, or -1 if varying. */ ! 2989: ! 2990: static rtx ! 2991: store_field (target, bitsize, bitpos, mode, exp, value_mode, ! 2992: unsignedp, align, total_size) ! 2993: rtx target; ! 2994: int bitsize, bitpos; ! 2995: enum machine_mode mode; ! 2996: tree exp; ! 2997: enum machine_mode value_mode; ! 2998: int unsignedp; ! 2999: int align; ! 3000: int total_size; ! 3001: { ! 3002: HOST_WIDE_INT width_mask = 0; ! 3003: ! 3004: if (bitsize < HOST_BITS_PER_WIDE_INT) ! 3005: width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1; ! 3006: ! 3007: /* If we are storing into an unaligned field of an aligned union that is ! 3008: in a register, we may have the mode of TARGET being an integer mode but ! 3009: MODE == BLKmode. In that case, get an aligned object whose size and ! 3010: alignment are the same as TARGET and store TARGET into it (we can avoid ! 3011: the store if the field being stored is the entire width of TARGET). Then ! 3012: call ourselves recursively to store the field into a BLKmode version of ! 3013: that object. Finally, load from the object into TARGET. This is not ! 3014: very efficient in general, but should only be slightly more expensive ! 3015: than the otherwise-required unaligned accesses. Perhaps this can be ! 3016: cleaned up later. */ ! 3017: ! 3018: if (mode == BLKmode ! 3019: && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG)) ! 3020: { ! 3021: rtx object = assign_stack_temp (GET_MODE (target), ! 3022: GET_MODE_SIZE (GET_MODE (target)), 0); ! 3023: rtx blk_object = copy_rtx (object); ! 3024: ! 3025: PUT_MODE (blk_object, BLKmode); ! 3026: ! 3027: if (bitsize != GET_MODE_BITSIZE (GET_MODE (target))) ! 3028: emit_move_insn (object, target); ! 3029: ! 3030: store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, ! 3031: align, total_size); ! 3032: ! 3033: /* Even though we aren't returning target, we need to ! 3034: give it the updated value. */ ! 3035: emit_move_insn (target, object); ! 3036: ! 3037: return blk_object; ! 3038: } ! 3039: ! 3040: /* If the structure is in a register or if the component ! 3041: is a bit field, we cannot use addressing to access it. ! 3042: Use bit-field techniques or SUBREG to store in it. */ ! 3043: ! 3044: if (mode == VOIDmode ! 3045: || (mode != BLKmode && ! direct_store[(int) mode]) ! 3046: || GET_CODE (target) == REG ! 3047: || GET_CODE (target) == SUBREG ! 3048: /* If the field isn't aligned enough to store as an ordinary memref, ! 3049: store it as a bit field. */ ! 3050: || (STRICT_ALIGNMENT ! 3051: && align * BITS_PER_UNIT < GET_MODE_ALIGNMENT (mode)) ! 3052: || (STRICT_ALIGNMENT && bitpos % GET_MODE_ALIGNMENT (mode) != 0)) ! 3053: { ! 3054: rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); ! 3055: ! 3056: /* Unless MODE is VOIDmode or BLKmode, convert TEMP to ! 3057: MODE. */ ! 3058: if (mode != VOIDmode && mode != BLKmode ! 3059: && mode != TYPE_MODE (TREE_TYPE (exp))) ! 3060: temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1); ! 3061: ! 3062: /* Store the value in the bitfield. */ ! 3063: store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size); ! 3064: if (value_mode != VOIDmode) ! 3065: { ! 3066: /* The caller wants an rtx for the value. */ ! 3067: /* If possible, avoid refetching from the bitfield itself. */ ! 3068: if (width_mask != 0 ! 3069: && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))) ! 3070: { ! 3071: tree count; ! 3072: enum machine_mode tmode; ! 3073: ! 3074: if (unsignedp) ! 3075: return expand_and (temp, GEN_INT (width_mask), NULL_RTX); ! 3076: tmode = GET_MODE (temp); ! 3077: if (tmode == VOIDmode) ! 3078: tmode = value_mode; ! 3079: count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0); ! 3080: temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0); ! 3081: return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0); ! 3082: } ! 3083: return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 3084: NULL_RTX, value_mode, 0, align, ! 3085: total_size); ! 3086: } ! 3087: return const0_rtx; ! 3088: } ! 3089: else ! 3090: { ! 3091: rtx addr = XEXP (target, 0); ! 3092: rtx to_rtx; ! 3093: ! 3094: /* If a value is wanted, it must be the lhs; ! 3095: so make the address stable for multiple use. */ ! 3096: ! 3097: if (value_mode != VOIDmode && GET_CODE (addr) != REG ! 3098: && ! CONSTANT_ADDRESS_P (addr) ! 3099: /* A frame-pointer reference is already stable. */ ! 3100: && ! (GET_CODE (addr) == PLUS ! 3101: && GET_CODE (XEXP (addr, 1)) == CONST_INT ! 3102: && (XEXP (addr, 0) == virtual_incoming_args_rtx ! 3103: || XEXP (addr, 0) == virtual_stack_vars_rtx))) ! 3104: addr = copy_to_reg (addr); ! 3105: ! 3106: /* Now build a reference to just the desired component. */ ! 3107: ! 3108: to_rtx = change_address (target, mode, ! 3109: plus_constant (addr, (bitpos / BITS_PER_UNIT))); ! 3110: MEM_IN_STRUCT_P (to_rtx) = 1; ! 3111: ! 3112: return store_expr (exp, to_rtx, value_mode != VOIDmode); ! 3113: } ! 3114: } ! 3115: ! 3116: /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF, ! 3117: or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or ! 3118: ARRAY_REFs and find the ultimate containing object, which we return. ! 3119: ! 3120: We set *PBITSIZE to the size in bits that we want, *PBITPOS to the ! 3121: bit position, and *PUNSIGNEDP to the signedness of the field. ! 3122: If the position of the field is variable, we store a tree ! 3123: giving the variable offset (in units) in *POFFSET. ! 3124: This offset is in addition to the bit position. ! 3125: If the position is not variable, we store 0 in *POFFSET. ! 3126: ! 3127: If any of the extraction expressions is volatile, ! 3128: we store 1 in *PVOLATILEP. Otherwise we don't change that. ! 3129: ! 3130: If the field is a bit-field, *PMODE is set to VOIDmode. Otherwise, it ! 3131: is a mode that can be used to access the field. In that case, *PBITSIZE ! 3132: is redundant. ! 3133: ! 3134: If the field describes a variable-sized object, *PMODE is set to ! 3135: VOIDmode and *PBITSIZE is set to -1. An access cannot be made in ! 3136: this case, but the address of the object can be found. */ ! 3137: ! 3138: tree ! 3139: get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, ! 3140: punsignedp, pvolatilep) ! 3141: tree exp; ! 3142: int *pbitsize; ! 3143: int *pbitpos; ! 3144: tree *poffset; ! 3145: enum machine_mode *pmode; ! 3146: int *punsignedp; ! 3147: int *pvolatilep; ! 3148: { ! 3149: tree orig_exp = exp; ! 3150: tree size_tree = 0; ! 3151: enum machine_mode mode = VOIDmode; ! 3152: tree offset = integer_zero_node; ! 3153: ! 3154: if (TREE_CODE (exp) == COMPONENT_REF) ! 3155: { ! 3156: size_tree = DECL_SIZE (TREE_OPERAND (exp, 1)); ! 3157: if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1))) ! 3158: mode = DECL_MODE (TREE_OPERAND (exp, 1)); ! 3159: *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1)); ! 3160: } ! 3161: else if (TREE_CODE (exp) == BIT_FIELD_REF) ! 3162: { ! 3163: size_tree = TREE_OPERAND (exp, 1); ! 3164: *punsignedp = TREE_UNSIGNED (exp); ! 3165: } ! 3166: else ! 3167: { ! 3168: mode = TYPE_MODE (TREE_TYPE (exp)); ! 3169: *pbitsize = GET_MODE_BITSIZE (mode); ! 3170: *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); ! 3171: } ! 3172: ! 3173: if (size_tree) ! 3174: { ! 3175: if (TREE_CODE (size_tree) != INTEGER_CST) ! 3176: mode = BLKmode, *pbitsize = -1; ! 3177: else ! 3178: *pbitsize = TREE_INT_CST_LOW (size_tree); ! 3179: } ! 3180: ! 3181: /* Compute cumulative bit-offset for nested component-refs and array-refs, ! 3182: and find the ultimate containing object. */ ! 3183: ! 3184: *pbitpos = 0; ! 3185: ! 3186: while (1) ! 3187: { ! 3188: if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF) ! 3189: { ! 3190: tree pos = (TREE_CODE (exp) == COMPONENT_REF ! 3191: ? DECL_FIELD_BITPOS (TREE_OPERAND (exp, 1)) ! 3192: : TREE_OPERAND (exp, 2)); ! 3193: ! 3194: /* If this field hasn't been filled in yet, don't go ! 3195: past it. This should only happen when folding expressions ! 3196: made during type construction. */ ! 3197: if (pos == 0) ! 3198: break; ! 3199: ! 3200: if (TREE_CODE (pos) == PLUS_EXPR) ! 3201: { ! 3202: tree constant, var; ! 3203: if (TREE_CODE (TREE_OPERAND (pos, 0)) == INTEGER_CST) ! 3204: { ! 3205: constant = TREE_OPERAND (pos, 0); ! 3206: var = TREE_OPERAND (pos, 1); ! 3207: } ! 3208: else if (TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST) ! 3209: { ! 3210: constant = TREE_OPERAND (pos, 1); ! 3211: var = TREE_OPERAND (pos, 0); ! 3212: } ! 3213: else ! 3214: abort (); ! 3215: ! 3216: *pbitpos += TREE_INT_CST_LOW (constant); ! 3217: offset = size_binop (PLUS_EXPR, offset, ! 3218: size_binop (FLOOR_DIV_EXPR, var, ! 3219: size_int (BITS_PER_UNIT))); ! 3220: } ! 3221: else if (TREE_CODE (pos) == INTEGER_CST) ! 3222: *pbitpos += TREE_INT_CST_LOW (pos); ! 3223: else ! 3224: { ! 3225: /* Assume here that the offset is a multiple of a unit. ! 3226: If not, there should be an explicitly added constant. */ ! 3227: offset = size_binop (PLUS_EXPR, offset, ! 3228: size_binop (FLOOR_DIV_EXPR, pos, ! 3229: size_int (BITS_PER_UNIT))); ! 3230: } ! 3231: } ! 3232: ! 3233: else if (TREE_CODE (exp) == ARRAY_REF) ! 3234: { ! 3235: /* This code is based on the code in case ARRAY_REF in expand_expr ! 3236: below. We assume here that the size of an array element is ! 3237: always an integral multiple of BITS_PER_UNIT. */ ! 3238: ! 3239: tree index = TREE_OPERAND (exp, 1); ! 3240: tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 3241: tree low_bound ! 3242: = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; ! 3243: tree index_type = TREE_TYPE (index); ! 3244: ! 3245: if (! integer_zerop (low_bound)) ! 3246: index = fold (build (MINUS_EXPR, index_type, index, low_bound)); ! 3247: ! 3248: if (TYPE_PRECISION (index_type) != POINTER_SIZE) ! 3249: { ! 3250: index = convert (type_for_size (POINTER_SIZE, 0), index); ! 3251: index_type = TREE_TYPE (index); ! 3252: } ! 3253: ! 3254: index = fold (build (MULT_EXPR, index_type, index, ! 3255: TYPE_SIZE (TREE_TYPE (exp)))); ! 3256: ! 3257: if (TREE_CODE (index) == INTEGER_CST ! 3258: && TREE_INT_CST_HIGH (index) == 0) ! 3259: *pbitpos += TREE_INT_CST_LOW (index); ! 3260: else ! 3261: offset = size_binop (PLUS_EXPR, offset, ! 3262: size_binop (FLOOR_DIV_EXPR, index, ! 3263: size_int (BITS_PER_UNIT))); ! 3264: } ! 3265: else if (TREE_CODE (exp) != NON_LVALUE_EXPR ! 3266: && ! ((TREE_CODE (exp) == NOP_EXPR ! 3267: || TREE_CODE (exp) == CONVERT_EXPR) ! 3268: && (TYPE_MODE (TREE_TYPE (exp)) ! 3269: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))) ! 3270: break; ! 3271: ! 3272: /* If any reference in the chain is volatile, the effect is volatile. */ ! 3273: if (TREE_THIS_VOLATILE (exp)) ! 3274: *pvolatilep = 1; ! 3275: exp = TREE_OPERAND (exp, 0); ! 3276: } ! 3277: ! 3278: /* If this was a bit-field, see if there is a mode that allows direct ! 3279: access in case EXP is in memory. */ ! 3280: if (mode == VOIDmode && *pbitsize != 0 && *pbitpos % *pbitsize == 0) ! 3281: { ! 3282: mode = mode_for_size (*pbitsize, MODE_INT, 0); ! 3283: if (mode == BLKmode) ! 3284: mode = VOIDmode; ! 3285: } ! 3286: ! 3287: if (integer_zerop (offset)) ! 3288: offset = 0; ! 3289: ! 3290: if (offset != 0 && contains_placeholder_p (offset)) ! 3291: offset = build (WITH_RECORD_EXPR, sizetype, offset, orig_exp); ! 3292: ! 3293: *pmode = mode; ! 3294: *poffset = offset; ! 3295: return exp; ! 3296: } ! 3297: ! 3298: /* Given an rtx VALUE that may contain additions and multiplications, ! 3299: return an equivalent value that just refers to a register or memory. ! 3300: This is done by generating instructions to perform the arithmetic ! 3301: and returning a pseudo-register containing the value. ! 3302: ! 3303: The returned value may be a REG, SUBREG, MEM or constant. */ ! 3304: ! 3305: rtx ! 3306: force_operand (value, target) ! 3307: rtx value, target; ! 3308: { ! 3309: register optab binoptab = 0; ! 3310: /* Use a temporary to force order of execution of calls to ! 3311: `force_operand'. */ ! 3312: rtx tmp; ! 3313: register rtx op2; ! 3314: /* Use subtarget as the target for operand 0 of a binary operation. */ ! 3315: register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); ! 3316: ! 3317: if (GET_CODE (value) == PLUS) ! 3318: binoptab = add_optab; ! 3319: else if (GET_CODE (value) == MINUS) ! 3320: binoptab = sub_optab; ! 3321: else if (GET_CODE (value) == MULT) ! 3322: { ! 3323: op2 = XEXP (value, 1); ! 3324: if (!CONSTANT_P (op2) ! 3325: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 3326: subtarget = 0; ! 3327: tmp = force_operand (XEXP (value, 0), subtarget); ! 3328: return expand_mult (GET_MODE (value), tmp, ! 3329: force_operand (op2, NULL_RTX), ! 3330: target, 0); ! 3331: } ! 3332: ! 3333: if (binoptab) ! 3334: { ! 3335: op2 = XEXP (value, 1); ! 3336: if (!CONSTANT_P (op2) ! 3337: && !(GET_CODE (op2) == REG && op2 != subtarget)) ! 3338: subtarget = 0; ! 3339: if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT) ! 3340: { ! 3341: binoptab = add_optab; ! 3342: op2 = negate_rtx (GET_MODE (value), op2); ! 3343: } ! 3344: ! 3345: /* Check for an addition with OP2 a constant integer and our first ! 3346: operand a PLUS of a virtual register and something else. In that ! 3347: case, we want to emit the sum of the virtual register and the ! 3348: constant first and then add the other value. This allows virtual ! 3349: register instantiation to simply modify the constant rather than ! 3350: creating another one around this addition. */ ! 3351: if (binoptab == add_optab && GET_CODE (op2) == CONST_INT ! 3352: && GET_CODE (XEXP (value, 0)) == PLUS ! 3353: && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG ! 3354: && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER ! 3355: && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER) ! 3356: { ! 3357: rtx temp = expand_binop (GET_MODE (value), binoptab, ! 3358: XEXP (XEXP (value, 0), 0), op2, ! 3359: subtarget, 0, OPTAB_LIB_WIDEN); ! 3360: return expand_binop (GET_MODE (value), binoptab, temp, ! 3361: force_operand (XEXP (XEXP (value, 0), 1), 0), ! 3362: target, 0, OPTAB_LIB_WIDEN); ! 3363: } ! 3364: ! 3365: tmp = force_operand (XEXP (value, 0), subtarget); ! 3366: return expand_binop (GET_MODE (value), binoptab, tmp, ! 3367: force_operand (op2, NULL_RTX), ! 3368: target, 0, OPTAB_LIB_WIDEN); ! 3369: /* We give UNSIGNEDP = 0 to expand_binop ! 3370: because the only operations we are expanding here are signed ones. */ ! 3371: } ! 3372: return value; ! 3373: } ! 3374: ! 3375: /* Subroutine of expand_expr: ! 3376: save the non-copied parts (LIST) of an expr (LHS), and return a list ! 3377: which can restore these values to their previous values, ! 3378: should something modify their storage. */ ! 3379: ! 3380: static tree ! 3381: save_noncopied_parts (lhs, list) ! 3382: tree lhs; ! 3383: tree list; ! 3384: { ! 3385: tree tail; ! 3386: tree parts = 0; ! 3387: ! 3388: for (tail = list; tail; tail = TREE_CHAIN (tail)) ! 3389: if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST) ! 3390: parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail))); ! 3391: else ! 3392: { ! 3393: tree part = TREE_VALUE (tail); ! 3394: tree part_type = TREE_TYPE (part); ! 3395: tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part); ! 3396: rtx target = assign_stack_temp (TYPE_MODE (part_type), ! 3397: int_size_in_bytes (part_type), 0); ! 3398: if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0))) ! 3399: target = change_address (target, TYPE_MODE (part_type), NULL_RTX); ! 3400: parts = tree_cons (to_be_saved, ! 3401: build (RTL_EXPR, part_type, NULL_TREE, ! 3402: (tree) target), ! 3403: parts); ! 3404: store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0); ! 3405: } ! 3406: return parts; ! 3407: } ! 3408: ! 3409: /* Subroutine of expand_expr: ! 3410: record the non-copied parts (LIST) of an expr (LHS), and return a list ! 3411: which specifies the initial values of these parts. */ ! 3412: ! 3413: static tree ! 3414: init_noncopied_parts (lhs, list) ! 3415: tree lhs; ! 3416: tree list; ! 3417: { ! 3418: tree tail; ! 3419: tree parts = 0; ! 3420: ! 3421: for (tail = list; tail; tail = TREE_CHAIN (tail)) ! 3422: if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST) ! 3423: parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail))); ! 3424: else ! 3425: { ! 3426: tree part = TREE_VALUE (tail); ! 3427: tree part_type = TREE_TYPE (part); ! 3428: tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part); ! 3429: parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts); ! 3430: } ! 3431: return parts; ! 3432: } ! 3433: ! 3434: /* Subroutine of expand_expr: return nonzero iff there is no way that ! 3435: EXP can reference X, which is being modified. */ ! 3436: ! 3437: static int ! 3438: safe_from_p (x, exp) ! 3439: rtx x; ! 3440: tree exp; ! 3441: { ! 3442: rtx exp_rtl = 0; ! 3443: int i, nops; ! 3444: ! 3445: if (x == 0) ! 3446: return 1; ! 3447: ! 3448: /* If this is a subreg of a hard register, declare it unsafe, otherwise, ! 3449: find the underlying pseudo. */ ! 3450: if (GET_CODE (x) == SUBREG) ! 3451: { ! 3452: x = SUBREG_REG (x); ! 3453: if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) ! 3454: return 0; ! 3455: } ! 3456: ! 3457: /* If X is a location in the outgoing argument area, it is always safe. */ ! 3458: if (GET_CODE (x) == MEM ! 3459: && (XEXP (x, 0) == virtual_outgoing_args_rtx ! 3460: || (GET_CODE (XEXP (x, 0)) == PLUS ! 3461: && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))) ! 3462: return 1; ! 3463: ! 3464: switch (TREE_CODE_CLASS (TREE_CODE (exp))) ! 3465: { ! 3466: case 'd': ! 3467: exp_rtl = DECL_RTL (exp); ! 3468: break; ! 3469: ! 3470: case 'c': ! 3471: return 1; ! 3472: ! 3473: case 'x': ! 3474: if (TREE_CODE (exp) == TREE_LIST) ! 3475: return ((TREE_VALUE (exp) == 0 ! 3476: || safe_from_p (x, TREE_VALUE (exp))) ! 3477: && (TREE_CHAIN (exp) == 0 ! 3478: || safe_from_p (x, TREE_CHAIN (exp)))); ! 3479: else ! 3480: return 0; ! 3481: ! 3482: case '1': ! 3483: return safe_from_p (x, TREE_OPERAND (exp, 0)); ! 3484: ! 3485: case '2': ! 3486: case '<': ! 3487: return (safe_from_p (x, TREE_OPERAND (exp, 0)) ! 3488: && safe_from_p (x, TREE_OPERAND (exp, 1))); ! 3489: ! 3490: case 'e': ! 3491: case 'r': ! 3492: /* Now do code-specific tests. EXP_RTL is set to any rtx we find in ! 3493: the expression. If it is set, we conflict iff we are that rtx or ! 3494: both are in memory. Otherwise, we check all operands of the ! 3495: expression recursively. */ ! 3496: ! 3497: switch (TREE_CODE (exp)) ! 3498: { ! 3499: case ADDR_EXPR: ! 3500: return (staticp (TREE_OPERAND (exp, 0)) ! 3501: || safe_from_p (x, TREE_OPERAND (exp, 0))); ! 3502: ! 3503: case INDIRECT_REF: ! 3504: if (GET_CODE (x) == MEM) ! 3505: return 0; ! 3506: break; ! 3507: ! 3508: case CALL_EXPR: ! 3509: exp_rtl = CALL_EXPR_RTL (exp); ! 3510: if (exp_rtl == 0) ! 3511: { ! 3512: /* Assume that the call will clobber all hard registers and ! 3513: all of memory. */ ! 3514: if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) ! 3515: || GET_CODE (x) == MEM) ! 3516: return 0; ! 3517: } ! 3518: ! 3519: break; ! 3520: ! 3521: case RTL_EXPR: ! 3522: exp_rtl = RTL_EXPR_RTL (exp); ! 3523: if (exp_rtl == 0) ! 3524: /* We don't know what this can modify. */ ! 3525: return 0; ! 3526: ! 3527: break; ! 3528: ! 3529: case WITH_CLEANUP_EXPR: ! 3530: exp_rtl = RTL_EXPR_RTL (exp); ! 3531: break; ! 3532: ! 3533: case SAVE_EXPR: ! 3534: exp_rtl = SAVE_EXPR_RTL (exp); ! 3535: break; ! 3536: ! 3537: case BIND_EXPR: ! 3538: /* The only operand we look at is operand 1. The rest aren't ! 3539: part of the expression. */ ! 3540: return safe_from_p (x, TREE_OPERAND (exp, 1)); ! 3541: ! 3542: case METHOD_CALL_EXPR: ! 3543: /* This takes a rtx argument, but shouldn't appear here. */ ! 3544: abort (); ! 3545: } ! 3546: ! 3547: /* If we have an rtx, we do not need to scan our operands. */ ! 3548: if (exp_rtl) ! 3549: break; ! 3550: ! 3551: nops = tree_code_length[(int) TREE_CODE (exp)]; ! 3552: for (i = 0; i < nops; i++) ! 3553: if (TREE_OPERAND (exp, i) != 0 ! 3554: && ! safe_from_p (x, TREE_OPERAND (exp, i))) ! 3555: return 0; ! 3556: } ! 3557: ! 3558: /* If we have an rtl, find any enclosed object. Then see if we conflict ! 3559: with it. */ ! 3560: if (exp_rtl) ! 3561: { ! 3562: if (GET_CODE (exp_rtl) == SUBREG) ! 3563: { ! 3564: exp_rtl = SUBREG_REG (exp_rtl); ! 3565: if (GET_CODE (exp_rtl) == REG ! 3566: && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER) ! 3567: return 0; ! 3568: } ! 3569: ! 3570: /* If the rtl is X, then it is not safe. Otherwise, it is unless both ! 3571: are memory and EXP is not readonly. */ ! 3572: return ! (rtx_equal_p (x, exp_rtl) ! 3573: || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM ! 3574: && ! TREE_READONLY (exp))); ! 3575: } ! 3576: ! 3577: /* If we reach here, it is safe. */ ! 3578: return 1; ! 3579: } ! 3580: ! 3581: /* Subroutine of expand_expr: return nonzero iff EXP is an ! 3582: expression whose type is statically determinable. */ ! 3583: ! 3584: static int ! 3585: fixed_type_p (exp) ! 3586: tree exp; ! 3587: { ! 3588: if (TREE_CODE (exp) == PARM_DECL ! 3589: || TREE_CODE (exp) == VAR_DECL ! 3590: || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR ! 3591: || TREE_CODE (exp) == COMPONENT_REF ! 3592: || TREE_CODE (exp) == ARRAY_REF) ! 3593: return 1; ! 3594: return 0; ! 3595: } ! 3596: ! 3597: /* expand_expr: generate code for computing expression EXP. ! 3598: An rtx for the computed value is returned. The value is never null. ! 3599: In the case of a void EXP, const0_rtx is returned. ! 3600: ! 3601: The value may be stored in TARGET if TARGET is nonzero. ! 3602: TARGET is just a suggestion; callers must assume that ! 3603: the rtx returned may not be the same as TARGET. ! 3604: ! 3605: If TARGET is CONST0_RTX, it means that the value will be ignored. ! 3606: ! 3607: If TMODE is not VOIDmode, it suggests generating the ! 3608: result in mode TMODE. But this is done only when convenient. ! 3609: Otherwise, TMODE is ignored and the value generated in its natural mode. ! 3610: TMODE is just a suggestion; callers must assume that ! 3611: the rtx returned may not have mode TMODE. ! 3612: ! 3613: EXPAND_CONST_ADDRESS says that it is okay to return a MEM ! 3614: with a constant address even if that address is not normally legitimate. ! 3615: EXPAND_INITIALIZER and EXPAND_SUM also have this effect. ! 3616: ! 3617: If MODIFIER is EXPAND_SUM then when EXP is an addition ! 3618: we can return an rtx of the form (MULT (REG ...) (CONST_INT ...)) ! 3619: or a nest of (PLUS ...) and (MINUS ...) where the terms are ! 3620: products as above, or REG or MEM, or constant. ! 3621: Ordinarily in such cases we would output mul or add instructions ! 3622: and then return a pseudo reg containing the sum. ! 3623: ! 3624: EXPAND_INITIALIZER is much like EXPAND_SUM except that ! 3625: it also marks a label as absolutely required (it can't be dead). ! 3626: It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns. ! 3627: This is used for outputting expressions used in initializers. */ ! 3628: ! 3629: rtx ! 3630: expand_expr (exp, target, tmode, modifier) ! 3631: register tree exp; ! 3632: rtx target; ! 3633: enum machine_mode tmode; ! 3634: enum expand_modifier modifier; ! 3635: { ! 3636: /* Chain of pending expressions for PLACEHOLDER_EXPR to replace. ! 3637: This is static so it will be accessible to our recursive callees. */ ! 3638: static tree placeholder_list = 0; ! 3639: register rtx op0, op1, temp; ! 3640: tree type = TREE_TYPE (exp); ! 3641: int unsignedp = TREE_UNSIGNED (type); ! 3642: register enum machine_mode mode = TYPE_MODE (type); ! 3643: register enum tree_code code = TREE_CODE (exp); ! 3644: optab this_optab; ! 3645: /* Use subtarget as the target for operand 0 of a binary operation. */ ! 3646: rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0); ! 3647: rtx original_target = target; ! 3648: /* Maybe defer this until sure not doing bytecode? */ ! 3649: int ignore = (target == const0_rtx ! 3650: || ((code == NON_LVALUE_EXPR || code == NOP_EXPR ! 3651: || code == CONVERT_EXPR || code == REFERENCE_EXPR ! 3652: || code == COND_EXPR) ! 3653: && TREE_CODE (type) == VOID_TYPE)); ! 3654: tree context; ! 3655: ! 3656: ! 3657: if (output_bytecode) ! 3658: { ! 3659: bc_expand_expr (exp); ! 3660: return NULL; ! 3661: } ! 3662: ! 3663: /* Don't use hard regs as subtargets, because the combiner ! 3664: can only handle pseudo regs. */ ! 3665: if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER) ! 3666: subtarget = 0; ! 3667: /* Avoid subtargets inside loops, ! 3668: since they hide some invariant expressions. */ ! 3669: if (preserve_subexpressions_p ()) ! 3670: subtarget = 0; ! 3671: ! 3672: /* If we are going to ignore this result, we need only do something ! 3673: if there is a side-effect somewhere in the expression. If there ! 3674: is, short-circuit the most common cases here. Note that we must ! 3675: not call expand_expr with anything but const0_rtx in case this ! 3676: is an initial expansion of a size that contains a PLACEHOLDER_EXPR. */ ! 3677: ! 3678: if (ignore) ! 3679: { ! 3680: if (! TREE_SIDE_EFFECTS (exp)) ! 3681: return const0_rtx; ! 3682: ! 3683: /* Ensure we reference a volatile object even if value is ignored. */ ! 3684: if (TREE_THIS_VOLATILE (exp) ! 3685: && TREE_CODE (exp) != FUNCTION_DECL ! 3686: && mode != VOIDmode && mode != BLKmode) ! 3687: { ! 3688: temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier); ! 3689: if (GET_CODE (temp) == MEM) ! 3690: temp = copy_to_reg (temp); ! 3691: return const0_rtx; ! 3692: } ! 3693: ! 3694: if (TREE_CODE_CLASS (code) == '1') ! 3695: return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, ! 3696: VOIDmode, modifier); ! 3697: else if (TREE_CODE_CLASS (code) == '2' ! 3698: || TREE_CODE_CLASS (code) == '<') ! 3699: { ! 3700: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier); ! 3701: expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier); ! 3702: return const0_rtx; ! 3703: } ! 3704: else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) ! 3705: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1))) ! 3706: /* If the second operand has no side effects, just evaluate ! 3707: the first. */ ! 3708: return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, ! 3709: VOIDmode, modifier); ! 3710: ! 3711: target = 0; ! 3712: } ! 3713: ! 3714: /* If will do cse, generate all results into pseudo registers ! 3715: since 1) that allows cse to find more things ! 3716: and 2) otherwise cse could produce an insn the machine ! 3717: cannot support. */ ! 3718: ! 3719: if (! cse_not_expected && mode != BLKmode && target ! 3720: && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 3721: target = subtarget; ! 3722: ! 3723: switch (code) ! 3724: { ! 3725: case LABEL_DECL: ! 3726: { ! 3727: tree function = decl_function_context (exp); ! 3728: /* Handle using a label in a containing function. */ ! 3729: if (function != current_function_decl && function != 0) ! 3730: { ! 3731: struct function *p = find_function_data (function); ! 3732: /* Allocate in the memory associated with the function ! 3733: that the label is in. */ ! 3734: push_obstacks (p->function_obstack, ! 3735: p->function_maybepermanent_obstack); ! 3736: ! 3737: p->forced_labels = gen_rtx (EXPR_LIST, VOIDmode, ! 3738: label_rtx (exp), p->forced_labels); ! 3739: pop_obstacks (); ! 3740: } ! 3741: else if (modifier == EXPAND_INITIALIZER) ! 3742: forced_labels = gen_rtx (EXPR_LIST, VOIDmode, ! 3743: label_rtx (exp), forced_labels); ! 3744: temp = gen_rtx (MEM, FUNCTION_MODE, ! 3745: gen_rtx (LABEL_REF, Pmode, label_rtx (exp))); ! 3746: if (function != current_function_decl && function != 0) ! 3747: LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1; ! 3748: return temp; ! 3749: } ! 3750: ! 3751: case PARM_DECL: ! 3752: if (DECL_RTL (exp) == 0) ! 3753: { ! 3754: error_with_decl (exp, "prior parameter's size depends on `%s'"); ! 3755: return CONST0_RTX (mode); ! 3756: } ! 3757: ! 3758: case VAR_DECL: ! 3759: /* If a static var's type was incomplete when the decl was written, ! 3760: but the type is complete now, lay out the decl now. */ ! 3761: if (DECL_SIZE (exp) == 0 && TYPE_SIZE (TREE_TYPE (exp)) != 0 ! 3762: && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) ! 3763: { ! 3764: push_obstacks_nochange (); ! 3765: end_temporary_allocation (); ! 3766: layout_decl (exp, 0); ! 3767: PUT_MODE (DECL_RTL (exp), DECL_MODE (exp)); ! 3768: pop_obstacks (); ! 3769: } ! 3770: case FUNCTION_DECL: ! 3771: case RESULT_DECL: ! 3772: if (DECL_RTL (exp) == 0) ! 3773: abort (); ! 3774: /* Ensure variable marked as used even if it doesn't go through ! 3775: a parser. If it hasn't be used yet, write out an external ! 3776: definition. */ ! 3777: if (! TREE_USED (exp)) ! 3778: { ! 3779: assemble_external (exp); ! 3780: TREE_USED (exp) = 1; ! 3781: } ! 3782: ! 3783: /* Handle variables inherited from containing functions. */ ! 3784: context = decl_function_context (exp); ! 3785: ! 3786: /* We treat inline_function_decl as an alias for the current function ! 3787: because that is the inline function whose vars, types, etc. ! 3788: are being merged into the current function. ! 3789: See expand_inline_function. */ ! 3790: if (context != 0 && context != current_function_decl ! 3791: && context != inline_function_decl ! 3792: /* If var is static, we don't need a static chain to access it. */ ! 3793: && ! (GET_CODE (DECL_RTL (exp)) == MEM ! 3794: && CONSTANT_P (XEXP (DECL_RTL (exp), 0)))) ! 3795: { ! 3796: rtx addr; ! 3797: ! 3798: /* Mark as non-local and addressable. */ ! 3799: DECL_NONLOCAL (exp) = 1; ! 3800: mark_addressable (exp); ! 3801: if (GET_CODE (DECL_RTL (exp)) != MEM) ! 3802: abort (); ! 3803: addr = XEXP (DECL_RTL (exp), 0); ! 3804: if (GET_CODE (addr) == MEM) ! 3805: addr = gen_rtx (MEM, Pmode, fix_lexical_addr (XEXP (addr, 0), exp)); ! 3806: else ! 3807: addr = fix_lexical_addr (addr, exp); ! 3808: return change_address (DECL_RTL (exp), mode, addr); ! 3809: } ! 3810: ! 3811: /* This is the case of an array whose size is to be determined ! 3812: from its initializer, while the initializer is still being parsed. ! 3813: See expand_decl. */ ! 3814: if (GET_CODE (DECL_RTL (exp)) == MEM ! 3815: && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG) ! 3816: return change_address (DECL_RTL (exp), GET_MODE (DECL_RTL (exp)), ! 3817: XEXP (DECL_RTL (exp), 0)); ! 3818: if (GET_CODE (DECL_RTL (exp)) == MEM ! 3819: && modifier != EXPAND_CONST_ADDRESS ! 3820: && modifier != EXPAND_SUM ! 3821: && modifier != EXPAND_INITIALIZER) ! 3822: { ! 3823: /* DECL_RTL probably contains a constant address. ! 3824: On RISC machines where a constant address isn't valid, ! 3825: make some insns to get that address into a register. */ ! 3826: if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0)) ! 3827: || (flag_force_addr ! 3828: && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (exp), 0)))) ! 3829: return change_address (DECL_RTL (exp), VOIDmode, ! 3830: copy_rtx (XEXP (DECL_RTL (exp), 0))); ! 3831: } ! 3832: ! 3833: /* If the mode of DECL_RTL does not match that of the decl, it ! 3834: must be a promoted value. We return a SUBREG of the wanted mode, ! 3835: but mark it so that we know that it was already extended. */ ! 3836: ! 3837: if (GET_CODE (DECL_RTL (exp)) == REG ! 3838: && GET_MODE (DECL_RTL (exp)) != mode) ! 3839: { ! 3840: enum machine_mode decl_mode = DECL_MODE (exp); ! 3841: ! 3842: /* Get the signedness used for this variable. Ensure we get the ! 3843: same mode we got when the variable was declared. */ ! 3844: ! 3845: PROMOTE_MODE (decl_mode, unsignedp, type); ! 3846: ! 3847: if (decl_mode != GET_MODE (DECL_RTL (exp))) ! 3848: abort (); ! 3849: ! 3850: temp = gen_rtx (SUBREG, mode, DECL_RTL (exp), 0); ! 3851: SUBREG_PROMOTED_VAR_P (temp) = 1; ! 3852: SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; ! 3853: return temp; ! 3854: } ! 3855: ! 3856: /* ! 3857: if (code == VAR_DECL ! 3858: && modifier == EXPAND_NORMAL ! 3859: && TREE_SELF_OFFSET (exp)) ! 3860: { ! 3861: rtx op0 = memory_address (mode, XEXP (DECL_RTL (exp), 0)); ! 3862: rtx op1 = gen_rtx (PLUS, mode, op0, DECL_RTL (exp)); ! 3863: temp = gen_rtx (MEM, mode, memory_address (mode, op1)); ! 3864: MEM_IN_STRUCT_P (temp) = 1; ! 3865: MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp); ! 3866: return temp; ! 3867: } ! 3868: else ! 3869: */ ! 3870: return DECL_RTL (exp); ! 3871: ! 3872: case INTEGER_CST: ! 3873: return immed_double_const (TREE_INT_CST_LOW (exp), ! 3874: TREE_INT_CST_HIGH (exp), ! 3875: mode); ! 3876: ! 3877: case CONST_DECL: ! 3878: return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); ! 3879: ! 3880: case REAL_CST: ! 3881: /* If optimized, generate immediate CONST_DOUBLE ! 3882: which will be turned into memory by reload if necessary. ! 3883: ! 3884: We used to force a register so that loop.c could see it. But ! 3885: this does not allow gen_* patterns to perform optimizations with ! 3886: the constants. It also produces two insns in cases like "x = 1.0;". ! 3887: On most machines, floating-point constants are not permitted in ! 3888: many insns, so we'd end up copying it to a register in any case. ! 3889: ! 3890: Now, we do the copying in expand_binop, if appropriate. */ ! 3891: return immed_real_const (exp); ! 3892: ! 3893: case COMPLEX_CST: ! 3894: case STRING_CST: ! 3895: if (! TREE_CST_RTL (exp)) ! 3896: output_constant_def (exp); ! 3897: ! 3898: /* TREE_CST_RTL probably contains a constant address. ! 3899: On RISC machines where a constant address isn't valid, ! 3900: make some insns to get that address into a register. */ ! 3901: if (GET_CODE (TREE_CST_RTL (exp)) == MEM ! 3902: && modifier != EXPAND_CONST_ADDRESS ! 3903: && modifier != EXPAND_INITIALIZER ! 3904: && modifier != EXPAND_SUM ! 3905: && !memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))) ! 3906: return change_address (TREE_CST_RTL (exp), VOIDmode, ! 3907: copy_rtx (XEXP (TREE_CST_RTL (exp), 0))); ! 3908: return TREE_CST_RTL (exp); ! 3909: ! 3910: case SAVE_EXPR: ! 3911: context = decl_function_context (exp); ! 3912: /* We treat inline_function_decl as an alias for the current function ! 3913: because that is the inline function whose vars, types, etc. ! 3914: are being merged into the current function. ! 3915: See expand_inline_function. */ ! 3916: if (context == current_function_decl || context == inline_function_decl) ! 3917: context = 0; ! 3918: ! 3919: /* If this is non-local, handle it. */ ! 3920: if (context) ! 3921: { ! 3922: temp = SAVE_EXPR_RTL (exp); ! 3923: if (temp && GET_CODE (temp) == REG) ! 3924: { ! 3925: put_var_into_stack (exp); ! 3926: temp = SAVE_EXPR_RTL (exp); ! 3927: } ! 3928: if (temp == 0 || GET_CODE (temp) != MEM) ! 3929: abort (); ! 3930: return change_address (temp, mode, ! 3931: fix_lexical_addr (XEXP (temp, 0), exp)); ! 3932: } ! 3933: if (SAVE_EXPR_RTL (exp) == 0) ! 3934: { ! 3935: if (mode == BLKmode) ! 3936: { ! 3937: temp ! 3938: = assign_stack_temp (mode, int_size_in_bytes (type), 0); ! 3939: MEM_IN_STRUCT_P (temp) ! 3940: = (TREE_CODE (type) == RECORD_TYPE ! 3941: || TREE_CODE (type) == UNION_TYPE ! 3942: || TREE_CODE (type) == QUAL_UNION_TYPE ! 3943: || TREE_CODE (type) == ARRAY_TYPE); ! 3944: } ! 3945: else ! 3946: { ! 3947: enum machine_mode var_mode = mode; ! 3948: ! 3949: if (TREE_CODE (type) == INTEGER_TYPE ! 3950: || TREE_CODE (type) == ENUMERAL_TYPE ! 3951: || TREE_CODE (type) == BOOLEAN_TYPE ! 3952: || TREE_CODE (type) == CHAR_TYPE ! 3953: || TREE_CODE (type) == REAL_TYPE ! 3954: || TREE_CODE (type) == POINTER_TYPE ! 3955: || TREE_CODE (type) == OFFSET_TYPE) ! 3956: { ! 3957: PROMOTE_MODE (var_mode, unsignedp, type); ! 3958: } ! 3959: ! 3960: temp = gen_reg_rtx (var_mode); ! 3961: } ! 3962: ! 3963: SAVE_EXPR_RTL (exp) = temp; ! 3964: if (!optimize && GET_CODE (temp) == REG) ! 3965: save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, temp, ! 3966: save_expr_regs); ! 3967: ! 3968: /* If the mode of TEMP does not match that of the expression, it ! 3969: must be a promoted value. We pass store_expr a SUBREG of the ! 3970: wanted mode but mark it so that we know that it was already ! 3971: extended. Note that `unsignedp' was modified above in ! 3972: this case. */ ! 3973: ! 3974: if (GET_CODE (temp) == REG && GET_MODE (temp) != mode) ! 3975: { ! 3976: temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0); ! 3977: SUBREG_PROMOTED_VAR_P (temp) = 1; ! 3978: SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; ! 3979: } ! 3980: ! 3981: store_expr (TREE_OPERAND (exp, 0), temp, 0); ! 3982: } ! 3983: ! 3984: /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it ! 3985: must be a promoted value. We return a SUBREG of the wanted mode, ! 3986: but mark it so that we know that it was already extended. */ ! 3987: ! 3988: if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG ! 3989: && GET_MODE (SAVE_EXPR_RTL (exp)) != mode) ! 3990: { ! 3991: enum machine_mode var_mode = mode; ! 3992: ! 3993: if (TREE_CODE (type) == INTEGER_TYPE ! 3994: || TREE_CODE (type) == ENUMERAL_TYPE ! 3995: || TREE_CODE (type) == BOOLEAN_TYPE ! 3996: || TREE_CODE (type) == CHAR_TYPE ! 3997: || TREE_CODE (type) == REAL_TYPE ! 3998: || TREE_CODE (type) == POINTER_TYPE ! 3999: || TREE_CODE (type) == OFFSET_TYPE) ! 4000: { ! 4001: PROMOTE_MODE (var_mode, unsignedp, type); ! 4002: } ! 4003: ! 4004: temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0); ! 4005: SUBREG_PROMOTED_VAR_P (temp) = 1; ! 4006: SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; ! 4007: return temp; ! 4008: } ! 4009: ! 4010: return SAVE_EXPR_RTL (exp); ! 4011: ! 4012: case PLACEHOLDER_EXPR: ! 4013: /* If there is an object on the head of the placeholder list, ! 4014: see if some object in it's references is of type TYPE. For ! 4015: further information, see tree.def. */ ! 4016: if (placeholder_list) ! 4017: { ! 4018: tree object; ! 4019: tree old_list = placeholder_list; ! 4020: ! 4021: for (object = TREE_PURPOSE (placeholder_list); ! 4022: TREE_TYPE (object) != type ! 4023: && (TREE_CODE_CLASS (TREE_CODE (object)) == 'r' ! 4024: || TREE_CODE_CLASS (TREE_CODE (object)) == '1' ! 4025: || TREE_CODE_CLASS (TREE_CODE (object)) == '2' ! 4026: || TREE_CODE_CLASS (TREE_CODE (object)) == 'e'); ! 4027: object = TREE_OPERAND (object, 0)) ! 4028: ; ! 4029: ! 4030: if (object && TREE_TYPE (object) == type) ! 4031: { ! 4032: /* Expand this object skipping the list entries before ! 4033: it was found in case it is also a PLACEHOLDER_EXPR. ! 4034: In that case, we want to translate it using subsequent ! 4035: entries. */ ! 4036: placeholder_list = TREE_CHAIN (placeholder_list); ! 4037: temp = expand_expr (object, original_target, tmode, modifier); ! 4038: placeholder_list = old_list; ! 4039: return temp; ! 4040: } ! 4041: } ! 4042: ! 4043: /* We can't find the object or there was a missing WITH_RECORD_EXPR. */ ! 4044: abort (); ! 4045: ! 4046: case WITH_RECORD_EXPR: ! 4047: /* Put the object on the placeholder list, expand our first operand, ! 4048: and pop the list. */ ! 4049: placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE, ! 4050: placeholder_list); ! 4051: target = expand_expr (TREE_OPERAND (exp, 0), original_target, ! 4052: tmode, modifier); ! 4053: placeholder_list = TREE_CHAIN (placeholder_list); ! 4054: return target; ! 4055: ! 4056: case EXIT_EXPR: ! 4057: expand_exit_loop_if_false (NULL_PTR, ! 4058: invert_truthvalue (TREE_OPERAND (exp, 0))); ! 4059: return const0_rtx; ! 4060: ! 4061: case LOOP_EXPR: ! 4062: push_temp_slots (); ! 4063: expand_start_loop (1); ! 4064: expand_expr_stmt (TREE_OPERAND (exp, 0)); ! 4065: expand_end_loop (); ! 4066: pop_temp_slots (); ! 4067: ! 4068: return const0_rtx; ! 4069: ! 4070: case BIND_EXPR: ! 4071: { ! 4072: tree vars = TREE_OPERAND (exp, 0); ! 4073: int vars_need_expansion = 0; ! 4074: ! 4075: /* Need to open a binding contour here because ! 4076: if there are any cleanups they most be contained here. */ ! 4077: expand_start_bindings (0); ! 4078: ! 4079: /* Mark the corresponding BLOCK for output in its proper place. */ ! 4080: if (TREE_OPERAND (exp, 2) != 0 ! 4081: && ! TREE_USED (TREE_OPERAND (exp, 2))) ! 4082: insert_block (TREE_OPERAND (exp, 2)); ! 4083: ! 4084: /* If VARS have not yet been expanded, expand them now. */ ! 4085: while (vars) ! 4086: { ! 4087: if (DECL_RTL (vars) == 0) ! 4088: { ! 4089: vars_need_expansion = 1; ! 4090: expand_decl (vars); ! 4091: } ! 4092: expand_decl_init (vars); ! 4093: vars = TREE_CHAIN (vars); ! 4094: } ! 4095: ! 4096: temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); ! 4097: ! 4098: expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); ! 4099: ! 4100: return temp; ! 4101: } ! 4102: ! 4103: case RTL_EXPR: ! 4104: if (RTL_EXPR_SEQUENCE (exp) == const0_rtx) ! 4105: abort (); ! 4106: emit_insns (RTL_EXPR_SEQUENCE (exp)); ! 4107: RTL_EXPR_SEQUENCE (exp) = const0_rtx; ! 4108: free_temps_for_rtl_expr (exp); ! 4109: return RTL_EXPR_RTL (exp); ! 4110: ! 4111: case CONSTRUCTOR: ! 4112: /* If we don't need the result, just ensure we evaluate any ! 4113: subexpressions. */ ! 4114: if (ignore) ! 4115: { ! 4116: tree elt; ! 4117: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) ! 4118: expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); ! 4119: return const0_rtx; ! 4120: } ! 4121: /* All elts simple constants => refer to a constant in memory. But ! 4122: if this is a non-BLKmode mode, let it store a field at a time ! 4123: since that should make a CONST_INT or CONST_DOUBLE when we ! 4124: fold. If we are making an initializer and all operands are ! 4125: constant, put it in memory as well. */ ! 4126: else if ((TREE_STATIC (exp) ! 4127: && (mode == BLKmode || TREE_ADDRESSABLE (exp))) ! 4128: || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp))) ! 4129: { ! 4130: rtx constructor = output_constant_def (exp); ! 4131: if (modifier != EXPAND_CONST_ADDRESS ! 4132: && modifier != EXPAND_INITIALIZER ! 4133: && modifier != EXPAND_SUM ! 4134: && !memory_address_p (GET_MODE (constructor), ! 4135: XEXP (constructor, 0))) ! 4136: constructor = change_address (constructor, VOIDmode, ! 4137: XEXP (constructor, 0)); ! 4138: return constructor; ! 4139: } ! 4140: ! 4141: else ! 4142: { ! 4143: if (target == 0 || ! safe_from_p (target, exp)) ! 4144: { ! 4145: if (mode != BLKmode && ! TREE_ADDRESSABLE (exp)) ! 4146: target = gen_reg_rtx (mode); ! 4147: else ! 4148: { ! 4149: enum tree_code c = TREE_CODE (type); ! 4150: target ! 4151: = assign_stack_temp (mode, int_size_in_bytes (type), 0); ! 4152: if (c == RECORD_TYPE || c == UNION_TYPE ! 4153: || c == QUAL_UNION_TYPE || c == ARRAY_TYPE) ! 4154: MEM_IN_STRUCT_P (target) = 1; ! 4155: } ! 4156: } ! 4157: store_constructor (exp, target); ! 4158: return target; ! 4159: } ! 4160: ! 4161: case INDIRECT_REF: ! 4162: { ! 4163: tree exp1 = TREE_OPERAND (exp, 0); ! 4164: tree exp2; ! 4165: ! 4166: /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated ! 4167: for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR. ! 4168: This code has the same general effect as simply doing ! 4169: expand_expr on the save expr, except that the expression PTR ! 4170: is computed for use as a memory address. This means different ! 4171: code, suitable for indexing, may be generated. */ ! 4172: if (TREE_CODE (exp1) == SAVE_EXPR ! 4173: && SAVE_EXPR_RTL (exp1) == 0 ! 4174: && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK ! 4175: && TYPE_MODE (TREE_TYPE (exp1)) == Pmode ! 4176: && TYPE_MODE (TREE_TYPE (exp2)) == Pmode) ! 4177: { ! 4178: temp = expand_expr (TREE_OPERAND (exp1, 0), NULL_RTX, ! 4179: VOIDmode, EXPAND_SUM); ! 4180: op0 = memory_address (mode, temp); ! 4181: op0 = copy_all_regs (op0); ! 4182: SAVE_EXPR_RTL (exp1) = op0; ! 4183: } ! 4184: else ! 4185: { ! 4186: op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM); ! 4187: op0 = memory_address (mode, op0); ! 4188: } ! 4189: ! 4190: temp = gen_rtx (MEM, mode, op0); ! 4191: /* If address was computed by addition, ! 4192: mark this as an element of an aggregate. */ ! 4193: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR ! 4194: || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR ! 4195: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR) ! 4196: || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE ! 4197: || TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE ! 4198: || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE ! 4199: || TREE_CODE (TREE_TYPE (exp)) == QUAL_UNION_TYPE ! 4200: || (TREE_CODE (exp1) == ADDR_EXPR ! 4201: && (exp2 = TREE_OPERAND (exp1, 0)) ! 4202: && (TREE_CODE (TREE_TYPE (exp2)) == ARRAY_TYPE ! 4203: || TREE_CODE (TREE_TYPE (exp2)) == RECORD_TYPE ! 4204: || TREE_CODE (TREE_TYPE (exp2)) == UNION_TYPE ! 4205: || TREE_CODE (TREE_TYPE (exp2)) == QUAL_UNION_TYPE))) ! 4206: MEM_IN_STRUCT_P (temp) = 1; ! 4207: MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile; ! 4208: #if 0 /* It is incorrect to set RTX_UNCHANGING_P here, because the fact that ! 4209: a location is accessed through a pointer to const does not mean ! 4210: that the value there can never change. */ ! 4211: RTX_UNCHANGING_P (temp) = TREE_READONLY (exp); ! 4212: #endif ! 4213: return temp; ! 4214: } ! 4215: ! 4216: case ARRAY_REF: ! 4217: if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE) ! 4218: abort (); ! 4219: ! 4220: { ! 4221: tree array = TREE_OPERAND (exp, 0); ! 4222: tree domain = TYPE_DOMAIN (TREE_TYPE (array)); ! 4223: tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; ! 4224: tree index = TREE_OPERAND (exp, 1); ! 4225: tree index_type = TREE_TYPE (index); ! 4226: int i; ! 4227: ! 4228: if (TREE_CODE (low_bound) != INTEGER_CST ! 4229: && contains_placeholder_p (low_bound)) ! 4230: low_bound = build (WITH_RECORD_EXPR, sizetype, low_bound, exp); ! 4231: ! 4232: /* Optimize the special-case of a zero lower bound. ! 4233: ! 4234: We convert the low_bound to sizetype to avoid some problems ! 4235: with constant folding. (E.g. suppose the lower bound is 1, ! 4236: and its mode is QI. Without the conversion, (ARRAY ! 4237: +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1)) ! 4238: +INDEX), which becomes (ARRAY+255+INDEX). Oops!) ! 4239: ! 4240: But sizetype isn't quite right either (especially if ! 4241: the lowbound is negative). FIXME */ ! 4242: ! 4243: if (! integer_zerop (low_bound)) ! 4244: index = fold (build (MINUS_EXPR, index_type, index, ! 4245: convert (sizetype, low_bound))); ! 4246: ! 4247: if (TREE_CODE (index) != INTEGER_CST ! 4248: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 4249: { ! 4250: /* Nonconstant array index or nonconstant element size. ! 4251: Generate the tree for *(&array+index) and expand that, ! 4252: except do it in a language-independent way ! 4253: and don't complain about non-lvalue arrays. ! 4254: `mark_addressable' should already have been called ! 4255: for any array for which this case will be reached. */ ! 4256: ! 4257: /* Don't forget the const or volatile flag from the array ! 4258: element. */ ! 4259: tree variant_type = build_type_variant (type, ! 4260: TREE_READONLY (exp), ! 4261: TREE_THIS_VOLATILE (exp)); ! 4262: tree array_adr = build1 (ADDR_EXPR, ! 4263: build_pointer_type (variant_type), array); ! 4264: tree elt; ! 4265: tree size = size_in_bytes (type); ! 4266: ! 4267: /* Convert the integer argument to a type the same size as a ! 4268: pointer so the multiply won't overflow spuriously. */ ! 4269: if (TYPE_PRECISION (index_type) != POINTER_SIZE) ! 4270: index = convert (type_for_size (POINTER_SIZE, 0), index); ! 4271: ! 4272: if (TREE_CODE (size) != INTEGER_CST ! 4273: && contains_placeholder_p (size)) ! 4274: size = build (WITH_RECORD_EXPR, sizetype, size, exp); ! 4275: ! 4276: /* Don't think the address has side effects ! 4277: just because the array does. ! 4278: (In some cases the address might have side effects, ! 4279: and we fail to record that fact here. However, it should not ! 4280: matter, since expand_expr should not care.) */ ! 4281: TREE_SIDE_EFFECTS (array_adr) = 0; ! 4282: ! 4283: elt = build1 (INDIRECT_REF, type, ! 4284: fold (build (PLUS_EXPR, ! 4285: TYPE_POINTER_TO (variant_type), ! 4286: array_adr, ! 4287: fold (build (MULT_EXPR, ! 4288: TYPE_POINTER_TO (variant_type), ! 4289: index, size))))); ! 4290: ! 4291: /* Volatility, etc., of new expression is same as old ! 4292: expression. */ ! 4293: TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp); ! 4294: TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp); ! 4295: TREE_READONLY (elt) = TREE_READONLY (exp); ! 4296: ! 4297: return expand_expr (elt, target, tmode, modifier); ! 4298: } ! 4299: ! 4300: /* Fold an expression like: "foo"[2]. ! 4301: This is not done in fold so it won't happen inside &. */ ! 4302: ! 4303: if (TREE_CODE (array) == STRING_CST ! 4304: && TREE_CODE (index) == INTEGER_CST ! 4305: && !TREE_INT_CST_HIGH (index) ! 4306: && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array)) ! 4307: { ! 4308: if (TREE_TYPE (TREE_TYPE (array)) == integer_type_node) ! 4309: { ! 4310: exp = build_int_2 (((int *)TREE_STRING_POINTER (array))[i], 0); ! 4311: TREE_TYPE (exp) = integer_type_node; ! 4312: return expand_expr (exp, target, tmode, modifier); ! 4313: } ! 4314: if (TREE_TYPE (TREE_TYPE (array)) == char_type_node) ! 4315: { ! 4316: exp = build_int_2 (TREE_STRING_POINTER (array)[i], 0); ! 4317: TREE_TYPE (exp) = integer_type_node; ! 4318: return expand_expr (convert (TREE_TYPE (TREE_TYPE (array)), ! 4319: exp), ! 4320: target, tmode, modifier); ! 4321: } ! 4322: } ! 4323: ! 4324: /* If this is a constant index into a constant array, ! 4325: just get the value from the array. Handle both the cases when ! 4326: we have an explicit constructor and when our operand is a variable ! 4327: that was declared const. */ ! 4328: ! 4329: if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)) ! 4330: { ! 4331: if (TREE_CODE (index) == INTEGER_CST ! 4332: && TREE_INT_CST_HIGH (index) == 0) ! 4333: { ! 4334: tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); ! 4335: ! 4336: i = TREE_INT_CST_LOW (index); ! 4337: while (elem && i--) ! 4338: elem = TREE_CHAIN (elem); ! 4339: if (elem) ! 4340: return expand_expr (fold (TREE_VALUE (elem)), target, ! 4341: tmode, modifier); ! 4342: } ! 4343: } ! 4344: ! 4345: else if (optimize >= 1 ! 4346: && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array) ! 4347: && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array) ! 4348: && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK) ! 4349: { ! 4350: if (TREE_CODE (index) == INTEGER_CST ! 4351: && TREE_INT_CST_HIGH (index) == 0) ! 4352: { ! 4353: tree init = DECL_INITIAL (array); ! 4354: ! 4355: i = TREE_INT_CST_LOW (index); ! 4356: if (TREE_CODE (init) == CONSTRUCTOR) ! 4357: { ! 4358: tree elem = CONSTRUCTOR_ELTS (init); ! 4359: ! 4360: while (elem ! 4361: && !tree_int_cst_equal (TREE_PURPOSE (elem), index)) ! 4362: elem = TREE_CHAIN (elem); ! 4363: if (elem) ! 4364: return expand_expr (fold (TREE_VALUE (elem)), target, ! 4365: tmode, modifier); ! 4366: } ! 4367: else if (TREE_CODE (init) == STRING_CST ! 4368: && i < TREE_STRING_LENGTH (init)) ! 4369: { ! 4370: temp = GEN_INT (TREE_STRING_POINTER (init)[i]); ! 4371: return convert_to_mode (mode, temp, 0); ! 4372: } ! 4373: } ! 4374: } ! 4375: } ! 4376: ! 4377: /* Treat array-ref with constant index as a component-ref. */ ! 4378: ! 4379: case COMPONENT_REF: ! 4380: /* Treat union-cast as an ordinary cast, i.e. translate ! 4381: "((union foo*)X)->elem" into "*(typeof (foo.elem)*)X", ! 4382: so that MEM_IN_STRUCT_P will not be set for the resulting rtl. */ ! 4383: ! 4384: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INDIRECT_REF ! 4385: && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == UNION_TYPE ! 4386: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == NOP_EXPR) ! 4387: { ! 4388: tree addr = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), 0); ! 4389: tree casted_type = build_pointer_type (TREE_TYPE (exp)); ! 4390: tree casted_addr = build1 (NOP_EXPR, casted_type, addr); ! 4391: return expand_expr (build1 (INDIRECT_REF, TREE_TYPE (exp), casted_addr), ! 4392: target, tmode, modifier); ! 4393: } ! 4394: ! 4395: /* Treat bit fields and component refs the same */ ! 4396: ! 4397: case BIT_FIELD_REF: ! 4398: /* If the operand is a CONSTRUCTOR, we can just extract the ! 4399: appropriate field if it is present. */ ! 4400: if (code != ARRAY_REF ! 4401: && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR) ! 4402: { ! 4403: tree elt; ! 4404: ! 4405: for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt; ! 4406: elt = TREE_CHAIN (elt)) ! 4407: if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1)) ! 4408: return expand_expr (TREE_VALUE (elt), target, tmode, modifier); ! 4409: } ! 4410: ! 4411: { ! 4412: enum machine_mode mode1; ! 4413: int bitsize; ! 4414: int bitpos; ! 4415: tree offset; ! 4416: int volatilep = 0; ! 4417: tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, ! 4418: &mode1, &unsignedp, &volatilep); ! 4419: int alignment; ! 4420: ! 4421: /* If we got back the original object, something is wrong. Perhaps ! 4422: we are evaluating an expression too early. In any event, don't ! 4423: infinitely recurse. */ ! 4424: if (tem == exp) ! 4425: abort (); ! 4426: ! 4427: /* In some cases, we will be offsetting OP0's address by a constant. ! 4428: So get it as a sum, if possible. If we will be using it ! 4429: directly in an insn, we validate it. */ ! 4430: op0 = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_SUM); ! 4431: ! 4432: /* If this is a constant, put it into a register if it is a ! 4433: legitimate constant and memory if it isn't. */ ! 4434: if (CONSTANT_P (op0)) ! 4435: { ! 4436: enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem)); ! 4437: if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)) ! 4438: op0 = force_reg (mode, op0); ! 4439: else ! 4440: op0 = validize_mem (force_const_mem (mode, op0)); ! 4441: } ! 4442: ! 4443: alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT; ! 4444: if (offset != 0) ! 4445: { ! 4446: rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); ! 4447: ! 4448: if (GET_CODE (op0) != MEM) ! 4449: abort (); ! 4450: op0 = change_address (op0, VOIDmode, ! 4451: gen_rtx (PLUS, Pmode, XEXP (op0, 0), ! 4452: force_reg (Pmode, offset_rtx))); ! 4453: /* If we have a variable offset, the known alignment ! 4454: is only that of the innermost structure containing the field. ! 4455: (Actually, we could sometimes do better by using the ! 4456: size of an element of the innermost array, but no need.) */ ! 4457: if (TREE_CODE (exp) == COMPONENT_REF ! 4458: || TREE_CODE (exp) == BIT_FIELD_REF) ! 4459: alignment = (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))) ! 4460: / BITS_PER_UNIT); ! 4461: } ! 4462: ! 4463: /* Don't forget about volatility even if this is a bitfield. */ ! 4464: if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0)) ! 4465: { ! 4466: op0 = copy_rtx (op0); ! 4467: MEM_VOLATILE_P (op0) = 1; ! 4468: } ! 4469: ! 4470: /* In cases where an aligned union has an unaligned object ! 4471: as a field, we might be extracting a BLKmode value from ! 4472: an integer-mode (e.g., SImode) object. Handle this case ! 4473: by doing the extract into an object as wide as the field ! 4474: (which we know to be the width of a basic mode), then ! 4475: storing into memory, and changing the mode to BLKmode. */ ! 4476: if (mode1 == VOIDmode ! 4477: || (mode1 != BLKmode && ! direct_load[(int) mode1] ! 4478: && modifier != EXPAND_CONST_ADDRESS ! 4479: && modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 4480: || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG ! 4481: /* If the field isn't aligned enough to fetch as a memref, ! 4482: fetch it as a bit field. */ ! 4483: || (STRICT_ALIGNMENT ! 4484: && TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode)) ! 4485: || (STRICT_ALIGNMENT && bitpos % GET_MODE_ALIGNMENT (mode) != 0)) ! 4486: { ! 4487: enum machine_mode ext_mode = mode; ! 4488: ! 4489: if (ext_mode == BLKmode) ! 4490: ext_mode = mode_for_size (bitsize, MODE_INT, 1); ! 4491: ! 4492: if (ext_mode == BLKmode) ! 4493: abort (); ! 4494: ! 4495: op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos, ! 4496: unsignedp, target, ext_mode, ext_mode, ! 4497: alignment, ! 4498: int_size_in_bytes (TREE_TYPE (tem))); ! 4499: if (mode == BLKmode) ! 4500: { ! 4501: rtx new = assign_stack_temp (ext_mode, ! 4502: bitsize / BITS_PER_UNIT, 0); ! 4503: ! 4504: emit_move_insn (new, op0); ! 4505: op0 = copy_rtx (new); ! 4506: PUT_MODE (op0, BLKmode); ! 4507: MEM_IN_STRUCT_P (op0) = 1; ! 4508: } ! 4509: ! 4510: return op0; ! 4511: } ! 4512: ! 4513: /* Get a reference to just this component. */ ! 4514: if (modifier == EXPAND_CONST_ADDRESS ! 4515: || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 4516: op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0), ! 4517: (bitpos / BITS_PER_UNIT))); ! 4518: else ! 4519: op0 = change_address (op0, mode1, ! 4520: plus_constant (XEXP (op0, 0), ! 4521: (bitpos / BITS_PER_UNIT))); ! 4522: MEM_IN_STRUCT_P (op0) = 1; ! 4523: MEM_VOLATILE_P (op0) |= volatilep; ! 4524: if (mode == mode1 || mode1 == BLKmode || mode1 == tmode) ! 4525: target = op0; ! 4526: else ! 4527: { ! 4528: if (target == 0) ! 4529: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); ! 4530: convert_move (target, op0, unsignedp); ! 4531: } ! 4532: /* ! 4533: if (modifier == EXPAND_NORMAL ! 4534: && TREE_SELF_OFFSET (TREE_OPERAND (exp, 1))) ! 4535: { ! 4536: rtx op0 = memory_address (mode, XEXP (target, 0)); ! 4537: rtx op1 = gen_rtx (PLUS, mode, op0, target); ! 4538: temp = gen_rtx (MEM, mode, memory_address (mode, op1)); ! 4539: MEM_IN_STRUCT_P (temp) = 1; ! 4540: MEM_VOLATILE_P (temp) = MEM_VOLATILE_P (target); ! 4541: return temp; ! 4542: } ! 4543: else ! 4544: */ ! 4545: return target; ! 4546: } ! 4547: ! 4548: case OFFSET_REF: ! 4549: { ! 4550: tree base = build1 (ADDR_EXPR, type, TREE_OPERAND (exp, 0)); ! 4551: tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1)); ! 4552: op0 = expand_expr (addr, NULL_RTX, VOIDmode, EXPAND_SUM); ! 4553: temp = gen_rtx (MEM, mode, memory_address (mode, op0)); ! 4554: MEM_IN_STRUCT_P (temp) = 1; ! 4555: MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp); ! 4556: #if 0 /* It is incorrect to set RTX_UNCHANGING_P here, because the fact that ! 4557: a location is accessed through a pointer to const does not mean ! 4558: that the value there can never change. */ ! 4559: RTX_UNCHANGING_P (temp) = TREE_READONLY (exp); ! 4560: #endif ! 4561: return temp; ! 4562: } ! 4563: ! 4564: /* Intended for a reference to a buffer of a file-object in Pascal. ! 4565: But it's not certain that a special tree code will really be ! 4566: necessary for these. INDIRECT_REF might work for them. */ ! 4567: case BUFFER_REF: ! 4568: abort (); ! 4569: ! 4570: /* IN_EXPR: Inlined pascal set IN expression. ! 4571: ! 4572: Algorithm: ! 4573: rlo = set_low - (set_low%bits_per_word); ! 4574: the_word = set [ (index - rlo)/bits_per_word ]; ! 4575: bit_index = index % bits_per_word; ! 4576: bitmask = 1 << bit_index; ! 4577: return !!(the_word & bitmask); */ ! 4578: case IN_EXPR: ! 4579: preexpand_calls (exp); ! 4580: { ! 4581: tree set = TREE_OPERAND (exp, 0); ! 4582: tree index = TREE_OPERAND (exp, 1); ! 4583: tree set_type = TREE_TYPE (set); ! 4584: ! 4585: tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type)); ! 4586: tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type)); ! 4587: ! 4588: rtx index_val; ! 4589: rtx lo_r; ! 4590: rtx hi_r; ! 4591: rtx rlow; ! 4592: rtx diff, quo, rem, addr, bit, result; ! 4593: rtx setval, setaddr; ! 4594: enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index)); ! 4595: ! 4596: if (target == 0) ! 4597: target = gen_reg_rtx (mode); ! 4598: ! 4599: /* If domain is empty, answer is no. */ ! 4600: if (tree_int_cst_lt (set_high_bound, set_low_bound)) ! 4601: return const0_rtx; ! 4602: ! 4603: index_val = expand_expr (index, 0, VOIDmode, 0); ! 4604: lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0); ! 4605: hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0); ! 4606: setval = expand_expr (set, 0, VOIDmode, 0); ! 4607: setaddr = XEXP (setval, 0); ! 4608: ! 4609: /* Compare index against bounds, if they are constant. */ ! 4610: if (GET_CODE (index_val) == CONST_INT ! 4611: && GET_CODE (lo_r) == CONST_INT ! 4612: && INTVAL (index_val) < INTVAL (lo_r)) ! 4613: return const0_rtx; ! 4614: ! 4615: if (GET_CODE (index_val) == CONST_INT ! 4616: && GET_CODE (hi_r) == CONST_INT ! 4617: && INTVAL (hi_r) < INTVAL (index_val)) ! 4618: return const0_rtx; ! 4619: ! 4620: /* If we get here, we have to generate the code for both cases ! 4621: (in range and out of range). */ ! 4622: ! 4623: op0 = gen_label_rtx (); ! 4624: op1 = gen_label_rtx (); ! 4625: ! 4626: if (! (GET_CODE (index_val) == CONST_INT ! 4627: && GET_CODE (lo_r) == CONST_INT)) ! 4628: { ! 4629: emit_cmp_insn (index_val, lo_r, LT, NULL_RTX, ! 4630: GET_MODE (index_val), 0, 0); ! 4631: emit_jump_insn (gen_blt (op1)); ! 4632: } ! 4633: ! 4634: if (! (GET_CODE (index_val) == CONST_INT ! 4635: && GET_CODE (hi_r) == CONST_INT)) ! 4636: { ! 4637: emit_cmp_insn (index_val, hi_r, GT, NULL_RTX, ! 4638: GET_MODE (index_val), 0, 0); ! 4639: emit_jump_insn (gen_bgt (op1)); ! 4640: } ! 4641: ! 4642: /* Calculate the element number of bit zero in the first word ! 4643: of the set. */ ! 4644: if (GET_CODE (lo_r) == CONST_INT) ! 4645: rlow = GEN_INT (INTVAL (lo_r) ! 4646: & ~ ((HOST_WIDE_INT) 1 << BITS_PER_UNIT)); ! 4647: else ! 4648: rlow = expand_binop (index_mode, and_optab, lo_r, ! 4649: GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)), ! 4650: NULL_RTX, 0, OPTAB_LIB_WIDEN); ! 4651: ! 4652: diff = expand_binop (index_mode, sub_optab, ! 4653: index_val, rlow, NULL_RTX, 0, OPTAB_LIB_WIDEN); ! 4654: ! 4655: quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff, ! 4656: GEN_INT (BITS_PER_UNIT), NULL_RTX, 0); ! 4657: rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val, ! 4658: GEN_INT (BITS_PER_UNIT), NULL_RTX, 0); ! 4659: addr = memory_address (byte_mode, ! 4660: expand_binop (index_mode, add_optab, ! 4661: diff, setaddr, NULL_RTX, 0, ! 4662: OPTAB_LIB_WIDEN)); ! 4663: /* Extract the bit we want to examine */ ! 4664: bit = expand_shift (RSHIFT_EXPR, byte_mode, ! 4665: gen_rtx (MEM, byte_mode, addr), ! 4666: make_tree (TREE_TYPE (index), rem), ! 4667: NULL_RTX, 1); ! 4668: result = expand_binop (byte_mode, and_optab, bit, const1_rtx, ! 4669: GET_MODE (target) == byte_mode ? target : 0, ! 4670: 1, OPTAB_LIB_WIDEN); ! 4671: ! 4672: if (result != target) ! 4673: convert_move (target, result, 1); ! 4674: ! 4675: /* Output the code to handle the out-of-range case. */ ! 4676: emit_jump (op0); ! 4677: emit_label (op1); ! 4678: emit_move_insn (target, const0_rtx); ! 4679: emit_label (op0); ! 4680: return target; ! 4681: } ! 4682: ! 4683: case WITH_CLEANUP_EXPR: ! 4684: if (RTL_EXPR_RTL (exp) == 0) ! 4685: { ! 4686: RTL_EXPR_RTL (exp) ! 4687: = expand_expr (TREE_OPERAND (exp, 0), ! 4688: target ? target : const0_rtx, ! 4689: tmode, modifier); ! 4690: cleanups_this_call ! 4691: = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), cleanups_this_call); ! 4692: /* That's it for this cleanup. */ ! 4693: TREE_OPERAND (exp, 2) = 0; ! 4694: } ! 4695: return RTL_EXPR_RTL (exp); ! 4696: ! 4697: case CALL_EXPR: ! 4698: /* Check for a built-in function. */ ! 4699: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR ! 4700: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL ! 4701: && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 4702: return expand_builtin (exp, target, subtarget, tmode, ignore); ! 4703: /* If this call was expanded already by preexpand_calls, ! 4704: just return the result we got. */ ! 4705: if (CALL_EXPR_RTL (exp) != 0) ! 4706: return CALL_EXPR_RTL (exp); ! 4707: return expand_call (exp, target, ignore); ! 4708: ! 4709: case NON_LVALUE_EXPR: ! 4710: case NOP_EXPR: ! 4711: case CONVERT_EXPR: ! 4712: case REFERENCE_EXPR: ! 4713: if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 4714: return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier); ! 4715: if (TREE_CODE (type) == UNION_TYPE) ! 4716: { ! 4717: tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 4718: if (target == 0) ! 4719: { ! 4720: if (mode == BLKmode) ! 4721: { ! 4722: if (TYPE_SIZE (type) == 0 ! 4723: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 4724: abort (); ! 4725: target = assign_stack_temp (BLKmode, ! 4726: (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! 4727: + BITS_PER_UNIT - 1) ! 4728: / BITS_PER_UNIT, 0); ! 4729: } ! 4730: else ! 4731: target = gen_reg_rtx (mode); ! 4732: } ! 4733: if (GET_CODE (target) == MEM) ! 4734: /* Store data into beginning of memory target. */ ! 4735: store_expr (TREE_OPERAND (exp, 0), ! 4736: change_address (target, TYPE_MODE (valtype), 0), 0); ! 4737: ! 4738: else if (GET_CODE (target) == REG) ! 4739: /* Store this field into a union of the proper type. */ ! 4740: store_field (target, GET_MODE_BITSIZE (TYPE_MODE (valtype)), 0, ! 4741: TYPE_MODE (valtype), TREE_OPERAND (exp, 0), ! 4742: VOIDmode, 0, 1, ! 4743: int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 4744: else ! 4745: abort (); ! 4746: ! 4747: /* Return the entire union. */ ! 4748: return target; ! 4749: } ! 4750: op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0); ! 4751: if (GET_MODE (op0) == mode) ! 4752: return op0; ! 4753: /* If arg is a constant integer being extended from a narrower mode, ! 4754: we must really truncate to get the extended bits right. Otherwise ! 4755: (unsigned long) (unsigned char) ("\377"[0]) ! 4756: would come out as ffffffff. */ ! 4757: if (GET_MODE (op0) == VOIDmode ! 4758: && (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 4759: < GET_MODE_BITSIZE (mode))) ! 4760: { ! 4761: /* MODE must be narrower than HOST_BITS_PER_INT. */ ! 4762: int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 4763: ! 4764: if (width < HOST_BITS_PER_WIDE_INT) ! 4765: { ! 4766: HOST_WIDE_INT val = (GET_CODE (op0) == CONST_INT ? INTVAL (op0) ! 4767: : CONST_DOUBLE_LOW (op0)); ! 4768: if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) ! 4769: || !(val & ((HOST_WIDE_INT) 1 << (width - 1)))) ! 4770: val &= ((HOST_WIDE_INT) 1 << width) - 1; ! 4771: else ! 4772: val |= ~(((HOST_WIDE_INT) 1 << width) - 1); ! 4773: ! 4774: op0 = GEN_INT (val); ! 4775: } ! 4776: else ! 4777: { ! 4778: op0 = (simplify_unary_operation ! 4779: ((TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) ! 4780: ? ZERO_EXTEND : SIGN_EXTEND), ! 4781: mode, op0, ! 4782: TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))); ! 4783: if (op0 == 0) ! 4784: abort (); ! 4785: } ! 4786: } ! 4787: if (GET_MODE (op0) == VOIDmode) ! 4788: return op0; ! 4789: if (modifier == EXPAND_INITIALIZER) ! 4790: return gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0); ! 4791: if (flag_force_mem && GET_CODE (op0) == MEM) ! 4792: op0 = copy_to_reg (op0); ! 4793: ! 4794: if (target == 0) ! 4795: return convert_to_mode (mode, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 4796: else ! 4797: convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 4798: return target; ! 4799: ! 4800: case PLUS_EXPR: ! 4801: /* We come here from MINUS_EXPR when the second operand is a constant. */ ! 4802: plus_expr: ! 4803: this_optab = add_optab; ! 4804: ! 4805: /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and ! 4806: something else, make sure we add the register to the constant and ! 4807: then to the other thing. This case can occur during strength ! 4808: reduction and doing it this way will produce better code if the ! 4809: frame pointer or argument pointer is eliminated. ! 4810: ! 4811: fold-const.c will ensure that the constant is always in the inner ! 4812: PLUS_EXPR, so the only case we need to do anything about is if ! 4813: sp, ap, or fp is our second argument, in which case we must swap ! 4814: the innermost first argument and our second argument. */ ! 4815: ! 4816: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR ! 4817: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST ! 4818: && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR ! 4819: && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx ! 4820: || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx ! 4821: || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx)) ! 4822: { ! 4823: tree t = TREE_OPERAND (exp, 1); ! 4824: ! 4825: TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); ! 4826: TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t; ! 4827: } ! 4828: ! 4829: /* If the result is to be Pmode and we are adding an integer to ! 4830: something, we might be forming a constant. So try to use ! 4831: plus_constant. If it produces a sum and we can't accept it, ! 4832: use force_operand. This allows P = &ARR[const] to generate ! 4833: efficient code on machines where a SYMBOL_REF is not a valid ! 4834: address. ! 4835: ! 4836: If this is an EXPAND_SUM call, always return the sum. */ ! 4837: if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER ! 4838: || mode == Pmode) ! 4839: { ! 4840: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST ! 4841: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! 4842: && TREE_CONSTANT (TREE_OPERAND (exp, 1))) ! 4843: { ! 4844: op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, ! 4845: EXPAND_SUM); ! 4846: op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0))); ! 4847: if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 4848: op1 = force_operand (op1, target); ! 4849: return op1; ! 4850: } ! 4851: ! 4852: else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 4853: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! 4854: && TREE_CONSTANT (TREE_OPERAND (exp, 0))) ! 4855: { ! 4856: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, ! 4857: EXPAND_SUM); ! 4858: if (! CONSTANT_P (op0)) ! 4859: { ! 4860: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, ! 4861: VOIDmode, modifier); ! 4862: /* Don't go to both_summands if modifier ! 4863: says it's not right to return a PLUS. */ ! 4864: if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 4865: goto binop2; ! 4866: goto both_summands; ! 4867: } ! 4868: op0 = plus_constant (op0, TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))); ! 4869: if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 4870: op0 = force_operand (op0, target); ! 4871: return op0; ! 4872: } ! 4873: } ! 4874: ! 4875: /* No sense saving up arithmetic to be done ! 4876: if it's all in the wrong mode to form part of an address. ! 4877: And force_operand won't know whether to sign-extend or ! 4878: zero-extend. */ ! 4879: if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) ! 4880: || mode != Pmode) ! 4881: goto binop; ! 4882: ! 4883: preexpand_calls (exp); ! 4884: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 4885: subtarget = 0; ! 4886: ! 4887: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); ! 4888: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); ! 4889: ! 4890: both_summands: ! 4891: /* Make sure any term that's a sum with a constant comes last. */ ! 4892: if (GET_CODE (op0) == PLUS ! 4893: && CONSTANT_P (XEXP (op0, 1))) ! 4894: { ! 4895: temp = op0; ! 4896: op0 = op1; ! 4897: op1 = temp; ! 4898: } ! 4899: /* If adding to a sum including a constant, ! 4900: associate it to put the constant outside. */ ! 4901: if (GET_CODE (op1) == PLUS ! 4902: && CONSTANT_P (XEXP (op1, 1))) ! 4903: { ! 4904: rtx constant_term = const0_rtx; ! 4905: ! 4906: temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0); ! 4907: if (temp != 0) ! 4908: op0 = temp; ! 4909: /* Ensure that MULT comes first if there is one. */ ! 4910: else if (GET_CODE (op0) == MULT) ! 4911: op0 = gen_rtx (PLUS, mode, op0, XEXP (op1, 0)); ! 4912: else ! 4913: op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0); ! 4914: ! 4915: /* Let's also eliminate constants from op0 if possible. */ ! 4916: op0 = eliminate_constant_term (op0, &constant_term); ! 4917: ! 4918: /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so ! 4919: their sum should be a constant. Form it into OP1, since the ! 4920: result we want will then be OP0 + OP1. */ ! 4921: ! 4922: temp = simplify_binary_operation (PLUS, mode, constant_term, ! 4923: XEXP (op1, 1)); ! 4924: if (temp != 0) ! 4925: op1 = temp; ! 4926: else ! 4927: op1 = gen_rtx (PLUS, mode, constant_term, XEXP (op1, 1)); ! 4928: } ! 4929: ! 4930: /* Put a constant term last and put a multiplication first. */ ! 4931: if (CONSTANT_P (op0) || GET_CODE (op1) == MULT) ! 4932: temp = op1, op1 = op0, op0 = temp; ! 4933: ! 4934: temp = simplify_binary_operation (PLUS, mode, op0, op1); ! 4935: return temp ? temp : gen_rtx (PLUS, mode, op0, op1); ! 4936: ! 4937: case MINUS_EXPR: ! 4938: /* For initializers, we are allowed to return a MINUS of two ! 4939: symbolic constants. Here we handle all cases when both operands ! 4940: are constant. */ ! 4941: /* Handle difference of two symbolic constants, ! 4942: for the sake of an initializer. */ ! 4943: if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 4944: && really_constant_p (TREE_OPERAND (exp, 0)) ! 4945: && really_constant_p (TREE_OPERAND (exp, 1))) ! 4946: { ! 4947: rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, ! 4948: VOIDmode, modifier); ! 4949: rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, ! 4950: VOIDmode, modifier); ! 4951: ! 4952: /* If one operand is a CONST_INT, put it last. */ ! 4953: if (GET_CODE (op0) == CONST_INT) ! 4954: temp = op0, op0 = op1, op1 = temp; ! 4955: ! 4956: /* If the last operand is a CONST_INT, use plus_constant of ! 4957: the negated constant. Else make the MINUS. */ ! 4958: if (GET_CODE (op1) == CONST_INT) ! 4959: return plus_constant (op0, - INTVAL (op1)); ! 4960: else ! 4961: return gen_rtx (MINUS, mode, op0, op1); ! 4962: } ! 4963: /* Convert A - const to A + (-const). */ ! 4964: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! 4965: { ! 4966: exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), ! 4967: fold (build1 (NEGATE_EXPR, type, ! 4968: TREE_OPERAND (exp, 1)))); ! 4969: goto plus_expr; ! 4970: } ! 4971: this_optab = sub_optab; ! 4972: goto binop; ! 4973: ! 4974: case MULT_EXPR: ! 4975: preexpand_calls (exp); ! 4976: /* If first operand is constant, swap them. ! 4977: Thus the following special case checks need only ! 4978: check the second operand. */ ! 4979: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST) ! 4980: { ! 4981: register tree t1 = TREE_OPERAND (exp, 0); ! 4982: TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1); ! 4983: TREE_OPERAND (exp, 1) = t1; ! 4984: } ! 4985: ! 4986: /* Attempt to return something suitable for generating an ! 4987: indexed address, for machines that support that. */ ! 4988: ! 4989: if (modifier == EXPAND_SUM && mode == Pmode ! 4990: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 4991: && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) ! 4992: { ! 4993: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); ! 4994: ! 4995: /* Apply distributive law if OP0 is x+c. */ ! 4996: if (GET_CODE (op0) == PLUS ! 4997: && GET_CODE (XEXP (op0, 1)) == CONST_INT) ! 4998: return gen_rtx (PLUS, mode, ! 4999: gen_rtx (MULT, mode, XEXP (op0, 0), ! 5000: GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), ! 5001: GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! 5002: * INTVAL (XEXP (op0, 1)))); ! 5003: ! 5004: if (GET_CODE (op0) != REG) ! 5005: op0 = force_operand (op0, NULL_RTX); ! 5006: if (GET_CODE (op0) != REG) ! 5007: op0 = copy_to_mode_reg (mode, op0); ! 5008: ! 5009: return gen_rtx (MULT, mode, op0, ! 5010: GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); ! 5011: } ! 5012: ! 5013: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 5014: subtarget = 0; ! 5015: ! 5016: /* Check for multiplying things that have been extended ! 5017: from a narrower type. If this machine supports multiplying ! 5018: in that narrower type with a result in the desired type, ! 5019: do it that way, and avoid the explicit type-conversion. */ ! 5020: if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR ! 5021: && TREE_CODE (type) == INTEGER_TYPE ! 5022: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 5023: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5024: && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 5025: && int_fits_type_p (TREE_OPERAND (exp, 1), ! 5026: TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 5027: /* Don't use a widening multiply if a shift will do. */ ! 5028: && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)))) ! 5029: > HOST_BITS_PER_WIDE_INT) ! 5030: || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)) ! 5031: || ! 5032: (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR ! 5033: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) ! 5034: == ! 5035: TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))) ! 5036: /* If both operands are extended, they must either both ! 5037: be zero-extended or both be sign-extended. */ ! 5038: && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))) ! 5039: == ! 5040: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))))) ! 5041: { ! 5042: enum machine_mode innermode ! 5043: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))); ! 5044: this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 5045: ? umul_widen_optab : smul_widen_optab); ! 5046: if (mode == GET_MODE_WIDER_MODE (innermode) ! 5047: && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 5048: { ! 5049: op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 5050: NULL_RTX, VOIDmode, 0); ! 5051: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! 5052: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, ! 5053: VOIDmode, 0); ! 5054: else ! 5055: op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), ! 5056: NULL_RTX, VOIDmode, 0); ! 5057: goto binop2; ! 5058: } ! 5059: } ! 5060: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5061: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 5062: return expand_mult (mode, op0, op1, target, unsignedp); ! 5063: ! 5064: case TRUNC_DIV_EXPR: ! 5065: case FLOOR_DIV_EXPR: ! 5066: case CEIL_DIV_EXPR: ! 5067: case ROUND_DIV_EXPR: ! 5068: case EXACT_DIV_EXPR: ! 5069: preexpand_calls (exp); ! 5070: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 5071: subtarget = 0; ! 5072: /* Possible optimization: compute the dividend with EXPAND_SUM ! 5073: then if the divisor is constant can optimize the case ! 5074: where some terms of the dividend have coeffs divisible by it. */ ! 5075: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5076: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 5077: return expand_divmod (0, code, mode, op0, op1, target, unsignedp); ! 5078: ! 5079: case RDIV_EXPR: ! 5080: this_optab = flodiv_optab; ! 5081: goto binop; ! 5082: ! 5083: case TRUNC_MOD_EXPR: ! 5084: case FLOOR_MOD_EXPR: ! 5085: case CEIL_MOD_EXPR: ! 5086: case ROUND_MOD_EXPR: ! 5087: preexpand_calls (exp); ! 5088: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 5089: subtarget = 0; ! 5090: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5091: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 5092: return expand_divmod (1, code, mode, op0, op1, target, unsignedp); ! 5093: ! 5094: case FIX_ROUND_EXPR: ! 5095: case FIX_FLOOR_EXPR: ! 5096: case FIX_CEIL_EXPR: ! 5097: abort (); /* Not used for C. */ ! 5098: ! 5099: case FIX_TRUNC_EXPR: ! 5100: op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! 5101: if (target == 0) ! 5102: target = gen_reg_rtx (mode); ! 5103: expand_fix (target, op0, unsignedp); ! 5104: return target; ! 5105: ! 5106: case FLOAT_EXPR: ! 5107: op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! 5108: if (target == 0) ! 5109: target = gen_reg_rtx (mode); ! 5110: /* expand_float can't figure out what to do if FROM has VOIDmode. ! 5111: So give it the correct mode. With -O, cse will optimize this. */ ! 5112: if (GET_MODE (op0) == VOIDmode) ! 5113: op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), ! 5114: op0); ! 5115: expand_float (target, op0, ! 5116: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 5117: return target; ! 5118: ! 5119: case NEGATE_EXPR: ! 5120: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 5121: temp = expand_unop (mode, neg_optab, op0, target, 0); ! 5122: if (temp == 0) ! 5123: abort (); ! 5124: return temp; ! 5125: ! 5126: case ABS_EXPR: ! 5127: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5128: ! 5129: /* Handle complex values specially. */ ! 5130: { ! 5131: enum machine_mode opmode ! 5132: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 5133: ! 5134: if (GET_MODE_CLASS (opmode) == MODE_COMPLEX_INT ! 5135: || GET_MODE_CLASS (opmode) == MODE_COMPLEX_FLOAT) ! 5136: return expand_complex_abs (opmode, op0, target, unsignedp); ! 5137: } ! 5138: ! 5139: /* Unsigned abs is simply the operand. Testing here means we don't ! 5140: risk generating incorrect code below. */ ! 5141: if (TREE_UNSIGNED (type)) ! 5142: return op0; ! 5143: ! 5144: /* First try to do it with a special abs instruction. */ ! 5145: temp = expand_unop (mode, abs_optab, op0, target, 0); ! 5146: if (temp != 0) ! 5147: return temp; ! 5148: ! 5149: /* If this machine has expensive jumps, we can do integer absolute ! 5150: value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)), ! 5151: where W is the width of MODE. */ ! 5152: ! 5153: if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2) ! 5154: { ! 5155: rtx extended = expand_shift (RSHIFT_EXPR, mode, op0, ! 5156: size_int (GET_MODE_BITSIZE (mode) - 1), ! 5157: NULL_RTX, 0); ! 5158: ! 5159: temp = expand_binop (mode, xor_optab, extended, op0, target, 0, ! 5160: OPTAB_LIB_WIDEN); ! 5161: if (temp != 0) ! 5162: temp = expand_binop (mode, sub_optab, temp, extended, target, 0, ! 5163: OPTAB_LIB_WIDEN); ! 5164: ! 5165: if (temp != 0) ! 5166: return temp; ! 5167: } ! 5168: ! 5169: /* If that does not win, use conditional jump and negate. */ ! 5170: target = original_target; ! 5171: temp = gen_label_rtx (); ! 5172: if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 0)) ! 5173: || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) ! 5174: || (GET_CODE (target) == REG ! 5175: && REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 5176: target = gen_reg_rtx (mode); ! 5177: emit_move_insn (target, op0); ! 5178: emit_cmp_insn (target, ! 5179: expand_expr (convert (type, integer_zero_node), ! 5180: NULL_RTX, VOIDmode, 0), ! 5181: GE, NULL_RTX, mode, 0, 0); ! 5182: NO_DEFER_POP; ! 5183: emit_jump_insn (gen_bge (temp)); ! 5184: op0 = expand_unop (mode, neg_optab, target, target, 0); ! 5185: if (op0 != target) ! 5186: emit_move_insn (target, op0); ! 5187: emit_label (temp); ! 5188: OK_DEFER_POP; ! 5189: return target; ! 5190: ! 5191: case MAX_EXPR: ! 5192: case MIN_EXPR: ! 5193: target = original_target; ! 5194: if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1)) ! 5195: || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) ! 5196: || (GET_CODE (target) == REG ! 5197: && REGNO (target) < FIRST_PSEUDO_REGISTER)) ! 5198: target = gen_reg_rtx (mode); ! 5199: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 5200: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 5201: ! 5202: /* First try to do it with a special MIN or MAX instruction. ! 5203: If that does not win, use a conditional jump to select the proper ! 5204: value. */ ! 5205: this_optab = (TREE_UNSIGNED (type) ! 5206: ? (code == MIN_EXPR ? umin_optab : umax_optab) ! 5207: : (code == MIN_EXPR ? smin_optab : smax_optab)); ! 5208: ! 5209: temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp, ! 5210: OPTAB_WIDEN); ! 5211: if (temp != 0) ! 5212: return temp; ! 5213: ! 5214: if (target != op0) ! 5215: emit_move_insn (target, op0); ! 5216: op0 = gen_label_rtx (); ! 5217: /* If this mode is an integer too wide to compare properly, ! 5218: compare word by word. Rely on cse to optimize constant cases. */ ! 5219: if (GET_MODE_CLASS (mode) == MODE_INT ! 5220: && !can_compare_p (mode)) ! 5221: { ! 5222: if (code == MAX_EXPR) ! 5223: do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type), target, op1, NULL, op0); ! 5224: else ! 5225: do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type), op1, target, NULL, op0); ! 5226: emit_move_insn (target, op1); ! 5227: } ! 5228: else ! 5229: { ! 5230: if (code == MAX_EXPR) ! 5231: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 5232: ? compare_from_rtx (target, op1, GEU, 1, mode, NULL_RTX, 0) ! 5233: : compare_from_rtx (target, op1, GE, 0, mode, NULL_RTX, 0)); ! 5234: else ! 5235: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! 5236: ? compare_from_rtx (target, op1, LEU, 1, mode, NULL_RTX, 0) ! 5237: : compare_from_rtx (target, op1, LE, 0, mode, NULL_RTX, 0)); ! 5238: if (temp == const0_rtx) ! 5239: emit_move_insn (target, op1); ! 5240: else if (temp != const_true_rtx) ! 5241: { ! 5242: if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0) ! 5243: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op0)); ! 5244: else ! 5245: abort (); ! 5246: emit_move_insn (target, op1); ! 5247: } ! 5248: } ! 5249: emit_label (op0); ! 5250: return target; ! 5251: ! 5252: /* ??? Can optimize when the operand of this is a bitwise operation, ! 5253: by using a different bitwise operation. */ ! 5254: case BIT_NOT_EXPR: ! 5255: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5256: temp = expand_unop (mode, one_cmpl_optab, op0, target, 1); ! 5257: if (temp == 0) ! 5258: abort (); ! 5259: return temp; ! 5260: ! 5261: case FFS_EXPR: ! 5262: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5263: temp = expand_unop (mode, ffs_optab, op0, target, 1); ! 5264: if (temp == 0) ! 5265: abort (); ! 5266: return temp; ! 5267: ! 5268: /* ??? Can optimize bitwise operations with one arg constant. ! 5269: Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b) ! 5270: and (a bitwise1 b) bitwise2 b (etc) ! 5271: but that is probably not worth while. */ ! 5272: ! 5273: /* BIT_AND_EXPR is for bitwise anding. ! 5274: TRUTH_AND_EXPR is for anding two boolean values ! 5275: when we want in all cases to compute both of them. ! 5276: In general it is fastest to do TRUTH_AND_EXPR by ! 5277: computing both operands as actual zero-or-1 values ! 5278: and then bitwise anding. In cases where there cannot ! 5279: be any side effects, better code would be made by ! 5280: treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR; ! 5281: but the question is how to recognize those cases. */ ! 5282: ! 5283: /* TRUTH_AND_EXPR can have a result whose mode doesn't match ! 5284: th operands. If so, don't use our target. */ ! 5285: case TRUTH_AND_EXPR: ! 5286: if (mode != TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5287: subtarget = 0; ! 5288: case BIT_AND_EXPR: ! 5289: this_optab = and_optab; ! 5290: goto binop; ! 5291: ! 5292: /* See comment above about TRUTH_AND_EXPR; it applies here too. */ ! 5293: case TRUTH_OR_EXPR: ! 5294: if (mode != TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5295: subtarget = 0; ! 5296: case BIT_IOR_EXPR: ! 5297: this_optab = ior_optab; ! 5298: goto binop; ! 5299: ! 5300: case TRUTH_XOR_EXPR: ! 5301: if (mode != TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 5302: subtarget = 0; ! 5303: case BIT_XOR_EXPR: ! 5304: this_optab = xor_optab; ! 5305: goto binop; ! 5306: ! 5307: case LSHIFT_EXPR: ! 5308: case RSHIFT_EXPR: ! 5309: case LROTATE_EXPR: ! 5310: case RROTATE_EXPR: ! 5311: preexpand_calls (exp); ! 5312: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 5313: subtarget = 0; ! 5314: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 5315: return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, ! 5316: unsignedp); ! 5317: ! 5318: /* Could determine the answer when only additive constants differ. ! 5319: Also, the addition of one can be handled by changing the condition. */ ! 5320: case LT_EXPR: ! 5321: case LE_EXPR: ! 5322: case GT_EXPR: ! 5323: case GE_EXPR: ! 5324: case EQ_EXPR: ! 5325: case NE_EXPR: ! 5326: preexpand_calls (exp); ! 5327: temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0); ! 5328: if (temp != 0) ! 5329: return temp; ! 5330: /* For foo != 0, load foo, and if it is nonzero load 1 instead. */ ! 5331: if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1)) ! 5332: && original_target ! 5333: && GET_CODE (original_target) == REG ! 5334: && (GET_MODE (original_target) ! 5335: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 5336: { ! 5337: temp = expand_expr (TREE_OPERAND (exp, 0), original_target, VOIDmode, 0); ! 5338: if (temp != original_target) ! 5339: temp = copy_to_reg (temp); ! 5340: op1 = gen_label_rtx (); ! 5341: emit_cmp_insn (temp, const0_rtx, EQ, NULL_RTX, ! 5342: GET_MODE (temp), unsignedp, 0); ! 5343: emit_jump_insn (gen_beq (op1)); ! 5344: emit_move_insn (temp, const1_rtx); ! 5345: emit_label (op1); ! 5346: return temp; ! 5347: } ! 5348: /* If no set-flag instruction, must generate a conditional ! 5349: store into a temporary variable. Drop through ! 5350: and handle this like && and ||. */ ! 5351: ! 5352: case TRUTH_ANDIF_EXPR: ! 5353: case TRUTH_ORIF_EXPR: ! 5354: if (! ignore ! 5355: && (target == 0 || ! safe_from_p (target, exp) ! 5356: /* Make sure we don't have a hard reg (such as function's return ! 5357: value) live across basic blocks, if not optimizing. */ ! 5358: || (!optimize && GET_CODE (target) == REG ! 5359: && REGNO (target) < FIRST_PSEUDO_REGISTER))) ! 5360: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode); ! 5361: ! 5362: if (target) ! 5363: emit_clr_insn (target); ! 5364: ! 5365: op1 = gen_label_rtx (); ! 5366: jumpifnot (exp, op1); ! 5367: ! 5368: if (target) ! 5369: emit_0_to_1_insn (target); ! 5370: ! 5371: emit_label (op1); ! 5372: return ignore ? const0_rtx : target; ! 5373: ! 5374: case TRUTH_NOT_EXPR: ! 5375: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); ! 5376: /* The parser is careful to generate TRUTH_NOT_EXPR ! 5377: only with operands that are always zero or one. */ ! 5378: temp = expand_binop (mode, xor_optab, op0, const1_rtx, ! 5379: target, 1, OPTAB_LIB_WIDEN); ! 5380: if (temp == 0) ! 5381: abort (); ! 5382: return temp; ! 5383: ! 5384: case COMPOUND_EXPR: ! 5385: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 5386: emit_queue (); ! 5387: return expand_expr (TREE_OPERAND (exp, 1), ! 5388: (ignore ? const0_rtx : target), ! 5389: VOIDmode, 0); ! 5390: ! 5391: case COND_EXPR: ! 5392: { ! 5393: /* Note that COND_EXPRs whose type is a structure or union ! 5394: are required to be constructed to contain assignments of ! 5395: a temporary variable, so that we can evaluate them here ! 5396: for side effect only. If type is void, we must do likewise. */ ! 5397: ! 5398: /* If an arm of the branch requires a cleanup, ! 5399: only that cleanup is performed. */ ! 5400: ! 5401: tree singleton = 0; ! 5402: tree binary_op = 0, unary_op = 0; ! 5403: tree old_cleanups = cleanups_this_call; ! 5404: cleanups_this_call = 0; ! 5405: ! 5406: /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and ! 5407: convert it to our mode, if necessary. */ ! 5408: if (integer_onep (TREE_OPERAND (exp, 1)) ! 5409: && integer_zerop (TREE_OPERAND (exp, 2)) ! 5410: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') ! 5411: { ! 5412: if (ignore) ! 5413: { ! 5414: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, ! 5415: modifier); ! 5416: return const0_rtx; ! 5417: } ! 5418: ! 5419: op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier); ! 5420: if (GET_MODE (op0) == mode) ! 5421: return op0; ! 5422: if (target == 0) ! 5423: target = gen_reg_rtx (mode); ! 5424: convert_move (target, op0, unsignedp); ! 5425: return target; ! 5426: } ! 5427: ! 5428: /* If we are not to produce a result, we have no target. Otherwise, ! 5429: if a target was specified use it; it will not be used as an ! 5430: intermediate target unless it is safe. If no target, use a ! 5431: temporary. */ ! 5432: ! 5433: if (ignore) ! 5434: temp = 0; ! 5435: else if (original_target ! 5436: && safe_from_p (original_target, TREE_OPERAND (exp, 0))) ! 5437: temp = original_target; ! 5438: else if (mode == BLKmode) ! 5439: { ! 5440: if (TYPE_SIZE (type) == 0 ! 5441: || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) ! 5442: abort (); ! 5443: ! 5444: temp = assign_stack_temp (BLKmode, ! 5445: (TREE_INT_CST_LOW (TYPE_SIZE (type)) ! 5446: + BITS_PER_UNIT - 1) ! 5447: / BITS_PER_UNIT, 0); ! 5448: MEM_IN_STRUCT_P (temp) ! 5449: = (TREE_CODE (type) == RECORD_TYPE ! 5450: || TREE_CODE (type) == UNION_TYPE ! 5451: || TREE_CODE (type) == QUAL_UNION_TYPE ! 5452: || TREE_CODE (type) == ARRAY_TYPE); ! 5453: } ! 5454: else ! 5455: temp = gen_reg_rtx (mode); ! 5456: ! 5457: /* Check for X ? A + B : A. If we have this, we can copy ! 5458: A to the output and conditionally add B. Similarly for unary ! 5459: operations. Don't do this if X has side-effects because ! 5460: those side effects might affect A or B and the "?" operation is ! 5461: a sequence point in ANSI. (We test for side effects later.) */ ! 5462: ! 5463: if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2' ! 5464: && operand_equal_p (TREE_OPERAND (exp, 2), ! 5465: TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0)) ! 5466: singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1); ! 5467: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2' ! 5468: && operand_equal_p (TREE_OPERAND (exp, 1), ! 5469: TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0)) ! 5470: singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2); ! 5471: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1' ! 5472: && operand_equal_p (TREE_OPERAND (exp, 2), ! 5473: TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0)) ! 5474: singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1); ! 5475: else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1' ! 5476: && operand_equal_p (TREE_OPERAND (exp, 1), ! 5477: TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0)) ! 5478: singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2); ! 5479: ! 5480: /* If we had X ? A + 1 : A and we can do the test of X as a store-flag ! 5481: operation, do this as A + (X != 0). Similarly for other simple ! 5482: binary operators. */ ! 5483: if (temp && singleton && binary_op ! 5484: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 5485: && (TREE_CODE (binary_op) == PLUS_EXPR ! 5486: || TREE_CODE (binary_op) == MINUS_EXPR ! 5487: || TREE_CODE (binary_op) == BIT_IOR_EXPR ! 5488: || TREE_CODE (binary_op) == BIT_XOR_EXPR ! 5489: || TREE_CODE (binary_op) == BIT_AND_EXPR) ! 5490: && integer_onep (TREE_OPERAND (binary_op, 1)) ! 5491: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') ! 5492: { ! 5493: rtx result; ! 5494: optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab ! 5495: : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab ! 5496: : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab ! 5497: : TREE_CODE (binary_op) == BIT_XOR_EXPR ? xor_optab ! 5498: : and_optab); ! 5499: ! 5500: /* If we had X ? A : A + 1, do this as A + (X == 0). ! 5501: ! 5502: We have to invert the truth value here and then put it ! 5503: back later if do_store_flag fails. We cannot simply copy ! 5504: TREE_OPERAND (exp, 0) to another variable and modify that ! 5505: because invert_truthvalue can modify the tree pointed to ! 5506: by its argument. */ ! 5507: if (singleton == TREE_OPERAND (exp, 1)) ! 5508: TREE_OPERAND (exp, 0) ! 5509: = invert_truthvalue (TREE_OPERAND (exp, 0)); ! 5510: ! 5511: result = do_store_flag (TREE_OPERAND (exp, 0), ! 5512: (safe_from_p (temp, singleton) ! 5513: ? temp : NULL_RTX), ! 5514: mode, BRANCH_COST <= 1); ! 5515: ! 5516: if (result) ! 5517: { ! 5518: op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0); ! 5519: return expand_binop (mode, boptab, op1, result, temp, ! 5520: unsignedp, OPTAB_LIB_WIDEN); ! 5521: } ! 5522: else if (singleton == TREE_OPERAND (exp, 1)) ! 5523: TREE_OPERAND (exp, 0) ! 5524: = invert_truthvalue (TREE_OPERAND (exp, 0)); ! 5525: } ! 5526: ! 5527: NO_DEFER_POP; ! 5528: op0 = gen_label_rtx (); ! 5529: ! 5530: if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))) ! 5531: { ! 5532: if (temp != 0) ! 5533: { ! 5534: /* If the target conflicts with the other operand of the ! 5535: binary op, we can't use it. Also, we can't use the target ! 5536: if it is a hard register, because evaluating the condition ! 5537: might clobber it. */ ! 5538: if ((binary_op ! 5539: && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1))) ! 5540: || (GET_CODE (temp) == REG ! 5541: && REGNO (temp) < FIRST_PSEUDO_REGISTER)) ! 5542: temp = gen_reg_rtx (mode); ! 5543: store_expr (singleton, temp, 0); ! 5544: } ! 5545: else ! 5546: expand_expr (singleton, ! 5547: ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); ! 5548: if (cleanups_this_call) ! 5549: { ! 5550: sorry ("aggregate value in COND_EXPR"); ! 5551: cleanups_this_call = 0; ! 5552: } ! 5553: if (singleton == TREE_OPERAND (exp, 1)) ! 5554: jumpif (TREE_OPERAND (exp, 0), op0); ! 5555: else ! 5556: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 5557: ! 5558: if (binary_op && temp == 0) ! 5559: /* Just touch the other operand. */ ! 5560: expand_expr (TREE_OPERAND (binary_op, 1), ! 5561: ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); ! 5562: else if (binary_op) ! 5563: store_expr (build (TREE_CODE (binary_op), type, ! 5564: make_tree (type, temp), ! 5565: TREE_OPERAND (binary_op, 1)), ! 5566: temp, 0); ! 5567: else ! 5568: store_expr (build1 (TREE_CODE (unary_op), type, ! 5569: make_tree (type, temp)), ! 5570: temp, 0); ! 5571: op1 = op0; ! 5572: } ! 5573: #if 0 ! 5574: /* This is now done in jump.c and is better done there because it ! 5575: produces shorter register lifetimes. */ ! 5576: ! 5577: /* Check for both possibilities either constants or variables ! 5578: in registers (but not the same as the target!). If so, can ! 5579: save branches by assigning one, branching, and assigning the ! 5580: other. */ ! 5581: else if (temp && GET_MODE (temp) != BLKmode ! 5582: && (TREE_CONSTANT (TREE_OPERAND (exp, 1)) ! 5583: || ((TREE_CODE (TREE_OPERAND (exp, 1)) == PARM_DECL ! 5584: || TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL) ! 5585: && DECL_RTL (TREE_OPERAND (exp, 1)) ! 5586: && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 1))) == REG ! 5587: && DECL_RTL (TREE_OPERAND (exp, 1)) != temp)) ! 5588: && (TREE_CONSTANT (TREE_OPERAND (exp, 2)) ! 5589: || ((TREE_CODE (TREE_OPERAND (exp, 2)) == PARM_DECL ! 5590: || TREE_CODE (TREE_OPERAND (exp, 2)) == VAR_DECL) ! 5591: && DECL_RTL (TREE_OPERAND (exp, 2)) ! 5592: && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 2))) == REG ! 5593: && DECL_RTL (TREE_OPERAND (exp, 2)) != temp))) ! 5594: { ! 5595: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 5596: temp = gen_reg_rtx (mode); ! 5597: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 5598: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 5599: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 5600: op1 = op0; ! 5601: } ! 5602: #endif ! 5603: /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any ! 5604: comparison operator. If we have one of these cases, set the ! 5605: output to A, branch on A (cse will merge these two references), ! 5606: then set the output to FOO. */ ! 5607: else if (temp ! 5608: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<' ! 5609: && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) ! 5610: && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 5611: TREE_OPERAND (exp, 1), 0) ! 5612: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 5613: && safe_from_p (temp, TREE_OPERAND (exp, 2))) ! 5614: { ! 5615: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 5616: temp = gen_reg_rtx (mode); ! 5617: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 5618: jumpif (TREE_OPERAND (exp, 0), op0); ! 5619: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 5620: op1 = op0; ! 5621: } ! 5622: else if (temp ! 5623: && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<' ! 5624: && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) ! 5625: && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 5626: TREE_OPERAND (exp, 2), 0) ! 5627: && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)) ! 5628: && safe_from_p (temp, TREE_OPERAND (exp, 1))) ! 5629: { ! 5630: if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) ! 5631: temp = gen_reg_rtx (mode); ! 5632: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 5633: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 5634: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 5635: op1 = op0; ! 5636: } ! 5637: else ! 5638: { ! 5639: op1 = gen_label_rtx (); ! 5640: jumpifnot (TREE_OPERAND (exp, 0), op0); ! 5641: if (temp != 0) ! 5642: store_expr (TREE_OPERAND (exp, 1), temp, 0); ! 5643: else ! 5644: expand_expr (TREE_OPERAND (exp, 1), ! 5645: ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); ! 5646: if (cleanups_this_call) ! 5647: { ! 5648: sorry ("aggregate value in COND_EXPR"); ! 5649: cleanups_this_call = 0; ! 5650: } ! 5651: ! 5652: emit_queue (); ! 5653: emit_jump_insn (gen_jump (op1)); ! 5654: emit_barrier (); ! 5655: emit_label (op0); ! 5656: if (temp != 0) ! 5657: store_expr (TREE_OPERAND (exp, 2), temp, 0); ! 5658: else ! 5659: expand_expr (TREE_OPERAND (exp, 2), ! 5660: ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); ! 5661: } ! 5662: ! 5663: if (cleanups_this_call) ! 5664: { ! 5665: sorry ("aggregate value in COND_EXPR"); ! 5666: cleanups_this_call = 0; ! 5667: } ! 5668: ! 5669: emit_queue (); ! 5670: emit_label (op1); ! 5671: OK_DEFER_POP; ! 5672: cleanups_this_call = old_cleanups; ! 5673: return temp; ! 5674: } ! 5675: ! 5676: case TARGET_EXPR: ! 5677: { ! 5678: /* Something needs to be initialized, but we didn't know ! 5679: where that thing was when building the tree. For example, ! 5680: it could be the return value of a function, or a parameter ! 5681: to a function which lays down in the stack, or a temporary ! 5682: variable which must be passed by reference. ! 5683: ! 5684: We guarantee that the expression will either be constructed ! 5685: or copied into our original target. */ ! 5686: ! 5687: tree slot = TREE_OPERAND (exp, 0); ! 5688: tree exp1; ! 5689: ! 5690: if (TREE_CODE (slot) != VAR_DECL) ! 5691: abort (); ! 5692: ! 5693: if (target == 0) ! 5694: { ! 5695: if (DECL_RTL (slot) != 0) ! 5696: { ! 5697: target = DECL_RTL (slot); ! 5698: /* If we have already expanded the slot, so don't do ! 5699: it again. (mrs) */ ! 5700: if (TREE_OPERAND (exp, 1) == NULL_TREE) ! 5701: return target; ! 5702: } ! 5703: else ! 5704: { ! 5705: target = assign_stack_temp (mode, int_size_in_bytes (type), 0); ! 5706: /* All temp slots at this level must not conflict. */ ! 5707: preserve_temp_slots (target); ! 5708: DECL_RTL (slot) = target; ! 5709: } ! 5710: ! 5711: /* We set IGNORE when we know that we're already ! 5712: doing this for a cleanup. */ ! 5713: if (ignore == 0) ! 5714: { ! 5715: /* Since SLOT is not known to the called function ! 5716: to belong to its stack frame, we must build an explicit ! 5717: cleanup. This case occurs when we must build up a reference ! 5718: to pass the reference as an argument. In this case, ! 5719: it is very likely that such a reference need not be ! 5720: built here. */ ! 5721: ! 5722: if (TREE_OPERAND (exp, 2) == 0) ! 5723: TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot); ! 5724: if (TREE_OPERAND (exp, 2)) ! 5725: cleanups_this_call = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), ! 5726: cleanups_this_call); ! 5727: } ! 5728: } ! 5729: else ! 5730: { ! 5731: /* This case does occur, when expanding a parameter which ! 5732: needs to be constructed on the stack. The target ! 5733: is the actual stack address that we want to initialize. ! 5734: The function we call will perform the cleanup in this case. */ ! 5735: ! 5736: /* If we have already assigned it space, use that space, ! 5737: not target that we were passed in, as our target ! 5738: parameter is only a hint. */ ! 5739: if (DECL_RTL (slot) != 0) ! 5740: { ! 5741: target = DECL_RTL (slot); ! 5742: /* If we have already expanded the slot, so don't do ! 5743: it again. (mrs) */ ! 5744: if (TREE_OPERAND (exp, 1) == NULL_TREE) ! 5745: return target; ! 5746: } ! 5747: ! 5748: DECL_RTL (slot) = target; ! 5749: } ! 5750: ! 5751: exp1 = TREE_OPERAND (exp, 1); ! 5752: /* Mark it as expanded. */ ! 5753: TREE_OPERAND (exp, 1) = NULL_TREE; ! 5754: ! 5755: return expand_expr (exp1, target, tmode, modifier); ! 5756: } ! 5757: ! 5758: case INIT_EXPR: ! 5759: { ! 5760: tree lhs = TREE_OPERAND (exp, 0); ! 5761: tree rhs = TREE_OPERAND (exp, 1); ! 5762: tree noncopied_parts = 0; ! 5763: tree lhs_type = TREE_TYPE (lhs); ! 5764: ! 5765: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); ! 5766: if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs)) ! 5767: noncopied_parts = init_noncopied_parts (stabilize_reference (lhs), ! 5768: TYPE_NONCOPIED_PARTS (lhs_type)); ! 5769: while (noncopied_parts != 0) ! 5770: { ! 5771: expand_assignment (TREE_VALUE (noncopied_parts), ! 5772: TREE_PURPOSE (noncopied_parts), 0, 0); ! 5773: noncopied_parts = TREE_CHAIN (noncopied_parts); ! 5774: } ! 5775: return temp; ! 5776: } ! 5777: ! 5778: case MODIFY_EXPR: ! 5779: { ! 5780: /* If lhs is complex, expand calls in rhs before computing it. ! 5781: That's so we don't compute a pointer and save it over a call. ! 5782: If lhs is simple, compute it first so we can give it as a ! 5783: target if the rhs is just a call. This avoids an extra temp and copy ! 5784: and that prevents a partial-subsumption which makes bad code. ! 5785: Actually we could treat component_ref's of vars like vars. */ ! 5786: ! 5787: tree lhs = TREE_OPERAND (exp, 0); ! 5788: tree rhs = TREE_OPERAND (exp, 1); ! 5789: tree noncopied_parts = 0; ! 5790: tree lhs_type = TREE_TYPE (lhs); ! 5791: ! 5792: temp = 0; ! 5793: ! 5794: if (TREE_CODE (lhs) != VAR_DECL ! 5795: && TREE_CODE (lhs) != RESULT_DECL ! 5796: && TREE_CODE (lhs) != PARM_DECL) ! 5797: preexpand_calls (exp); ! 5798: ! 5799: /* Check for |= or &= of a bitfield of size one into another bitfield ! 5800: of size 1. In this case, (unless we need the result of the ! 5801: assignment) we can do this more efficiently with a ! 5802: test followed by an assignment, if necessary. ! 5803: ! 5804: ??? At this point, we can't get a BIT_FIELD_REF here. But if ! 5805: things change so we do, this code should be enhanced to ! 5806: support it. */ ! 5807: if (ignore ! 5808: && TREE_CODE (lhs) == COMPONENT_REF ! 5809: && (TREE_CODE (rhs) == BIT_IOR_EXPR ! 5810: || TREE_CODE (rhs) == BIT_AND_EXPR) ! 5811: && TREE_OPERAND (rhs, 0) == lhs ! 5812: && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF ! 5813: && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (lhs, 1))) == 1 ! 5814: && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))) == 1) ! 5815: { ! 5816: rtx label = gen_label_rtx (); ! 5817: ! 5818: do_jump (TREE_OPERAND (rhs, 1), ! 5819: TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0, ! 5820: TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0); ! 5821: expand_assignment (lhs, convert (TREE_TYPE (rhs), ! 5822: (TREE_CODE (rhs) == BIT_IOR_EXPR ! 5823: ? integer_one_node ! 5824: : integer_zero_node)), ! 5825: 0, 0); ! 5826: do_pending_stack_adjust (); ! 5827: emit_label (label); ! 5828: return const0_rtx; ! 5829: } ! 5830: ! 5831: if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 ! 5832: && ! (fixed_type_p (lhs) && fixed_type_p (rhs))) ! 5833: noncopied_parts = save_noncopied_parts (stabilize_reference (lhs), ! 5834: TYPE_NONCOPIED_PARTS (lhs_type)); ! 5835: ! 5836: temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0); ! 5837: while (noncopied_parts != 0) ! 5838: { ! 5839: expand_assignment (TREE_PURPOSE (noncopied_parts), ! 5840: TREE_VALUE (noncopied_parts), 0, 0); ! 5841: noncopied_parts = TREE_CHAIN (noncopied_parts); ! 5842: } ! 5843: return temp; ! 5844: } ! 5845: ! 5846: case PREINCREMENT_EXPR: ! 5847: case PREDECREMENT_EXPR: ! 5848: return expand_increment (exp, 0); ! 5849: ! 5850: case POSTINCREMENT_EXPR: ! 5851: case POSTDECREMENT_EXPR: ! 5852: /* Faster to treat as pre-increment if result is not used. */ ! 5853: return expand_increment (exp, ! ignore); ! 5854: ! 5855: case ADDR_EXPR: ! 5856: /* Are we taking the address of a nested function? */ ! 5857: if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL ! 5858: && decl_function_context (TREE_OPERAND (exp, 0)) != 0) ! 5859: { ! 5860: op0 = trampoline_address (TREE_OPERAND (exp, 0)); ! 5861: op0 = force_operand (op0, target); ! 5862: } ! 5863: else ! 5864: { ! 5865: /* We make sure to pass const0_rtx down if we came in with ! 5866: ignore set, to avoid doing the cleanups twice for something. */ ! 5867: op0 = expand_expr (TREE_OPERAND (exp, 0), ! 5868: ignore ? const0_rtx : NULL_RTX, VOIDmode, ! 5869: (modifier == EXPAND_INITIALIZER ! 5870: ? modifier : EXPAND_CONST_ADDRESS)); ! 5871: ! 5872: /* We would like the object in memory. If it is a constant, ! 5873: we can have it be statically allocated into memory. For ! 5874: a non-constant (REG or SUBREG), we need to allocate some ! 5875: memory and store the value into it. */ ! 5876: ! 5877: if (CONSTANT_P (op0)) ! 5878: op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), ! 5879: op0); ! 5880: ! 5881: /* These cases happen in Fortran. Is that legitimate? ! 5882: Should Fortran work in another way? ! 5883: Do they happen in C? */ ! 5884: if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG ! 5885: || GET_CODE (op0) == CONCAT) ! 5886: { ! 5887: /* If this object is in a register, it must be not ! 5888: be BLKmode. */ ! 5889: tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 5890: enum machine_mode inner_mode = TYPE_MODE (inner_type); ! 5891: rtx memloc ! 5892: = assign_stack_temp (inner_mode, ! 5893: int_size_in_bytes (inner_type), 1); ! 5894: ! 5895: emit_move_insn (memloc, op0); ! 5896: op0 = memloc; ! 5897: } ! 5898: ! 5899: if (GET_CODE (op0) != MEM) ! 5900: abort (); ! 5901: ! 5902: if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER) ! 5903: return XEXP (op0, 0); ! 5904: op0 = force_operand (XEXP (op0, 0), target); ! 5905: } ! 5906: if (flag_force_addr && GET_CODE (op0) != REG) ! 5907: return force_reg (Pmode, op0); ! 5908: return op0; ! 5909: ! 5910: case ENTRY_VALUE_EXPR: ! 5911: abort (); ! 5912: ! 5913: /* COMPLEX type for Extended Pascal & Fortran */ ! 5914: case COMPLEX_EXPR: ! 5915: { ! 5916: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp))); ! 5917: ! 5918: rtx prev; ! 5919: ! 5920: /* Get the rtx code of the operands. */ ! 5921: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5922: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); ! 5923: ! 5924: if (! target) ! 5925: target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ! 5926: ! 5927: prev = get_last_insn (); ! 5928: ! 5929: /* Tell flow that the whole of the destination is being set. */ ! 5930: if (GET_CODE (target) == REG) ! 5931: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 5932: ! 5933: /* Move the real (op0) and imaginary (op1) parts to their location. */ ! 5934: emit_move_insn (gen_realpart (mode, target), op0); ! 5935: emit_move_insn (gen_imagpart (mode, target), op1); ! 5936: ! 5937: /* Complex construction should appear as a single unit. */ ! 5938: if (GET_CODE (target) != CONCAT) ! 5939: /* If TARGET is a CONCAT, we got insns like RD = RS, ID = IS, ! 5940: each with a separate pseudo as destination. ! 5941: It's not correct for flow to treat them as a unit. */ ! 5942: group_insns (prev); ! 5943: ! 5944: return target; ! 5945: } ! 5946: ! 5947: case REALPART_EXPR: ! 5948: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5949: return gen_realpart (mode, op0); ! 5950: ! 5951: case IMAGPART_EXPR: ! 5952: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5953: return gen_imagpart (mode, op0); ! 5954: ! 5955: case CONJ_EXPR: ! 5956: { ! 5957: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp))); ! 5958: rtx imag_t; ! 5959: rtx prev; ! 5960: ! 5961: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! 5962: ! 5963: if (! target) ! 5964: target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ! 5965: ! 5966: prev = get_last_insn (); ! 5967: ! 5968: /* Tell flow that the whole of the destination is being set. */ ! 5969: if (GET_CODE (target) == REG) ! 5970: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 5971: ! 5972: /* Store the realpart and the negated imagpart to target. */ ! 5973: emit_move_insn (gen_realpart (mode, target), gen_realpart (mode, op0)); ! 5974: ! 5975: imag_t = gen_imagpart (mode, target); ! 5976: temp = expand_unop (mode, neg_optab, ! 5977: gen_imagpart (mode, op0), imag_t, 0); ! 5978: if (temp != imag_t) ! 5979: emit_move_insn (imag_t, temp); ! 5980: ! 5981: /* Conjugate should appear as a single unit */ ! 5982: if (GET_CODE (target) != CONCAT) ! 5983: /* If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS, ! 5984: each with a separate pseudo as destination. ! 5985: It's not correct for flow to treat them as a unit. */ ! 5986: group_insns (prev); ! 5987: ! 5988: return target; ! 5989: } ! 5990: ! 5991: case ERROR_MARK: ! 5992: op0 = CONST0_RTX (tmode); ! 5993: if (op0 != 0) ! 5994: return op0; ! 5995: return const0_rtx; ! 5996: ! 5997: default: ! 5998: return (*lang_expand_expr) (exp, original_target, tmode, modifier); ! 5999: } ! 6000: ! 6001: /* Here to do an ordinary binary operator, generating an instruction ! 6002: from the optab already placed in `this_optab'. */ ! 6003: binop: ! 6004: preexpand_calls (exp); ! 6005: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) ! 6006: subtarget = 0; ! 6007: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! 6008: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 6009: binop2: ! 6010: temp = expand_binop (mode, this_optab, op0, op1, target, ! 6011: unsignedp, OPTAB_LIB_WIDEN); ! 6012: if (temp == 0) ! 6013: abort (); ! 6014: return temp; ! 6015: } ! 6016: ! 6017: ! 6018: /* Emit bytecode to evaluate the given expression EXP to the stack. */ ! 6019: void ! 6020: bc_expand_expr (exp) ! 6021: tree exp; ! 6022: { ! 6023: enum tree_code code; ! 6024: tree type, arg0; ! 6025: rtx r; ! 6026: struct binary_operator *binoptab; ! 6027: struct unary_operator *unoptab; ! 6028: struct increment_operator *incroptab; ! 6029: struct bc_label *lab, *lab1; ! 6030: enum bytecode_opcode opcode; ! 6031: ! 6032: ! 6033: code = TREE_CODE (exp); ! 6034: ! 6035: switch (code) ! 6036: { ! 6037: case PARM_DECL: ! 6038: ! 6039: if (DECL_RTL (exp) == 0) ! 6040: { ! 6041: error_with_decl (exp, "prior parameter's size depends on `%s'"); ! 6042: return; ! 6043: } ! 6044: ! 6045: bc_load_parmaddr (DECL_RTL (exp)); ! 6046: bc_load_memory (TREE_TYPE (exp), exp); ! 6047: ! 6048: return; ! 6049: ! 6050: case VAR_DECL: ! 6051: ! 6052: if (DECL_RTL (exp) == 0) ! 6053: abort (); ! 6054: ! 6055: #if 0 ! 6056: if (BYTECODE_LABEL (DECL_RTL (exp))) ! 6057: bc_load_externaddr (DECL_RTL (exp)); ! 6058: else ! 6059: bc_load_localaddr (DECL_RTL (exp)); ! 6060: #endif ! 6061: if (TREE_PUBLIC (exp)) ! 6062: bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp), ! 6063: BYTECODE_BC_LABEL (DECL_RTL (exp))->offset); ! 6064: else ! 6065: bc_load_localaddr (DECL_RTL (exp)); ! 6066: ! 6067: bc_load_memory (TREE_TYPE (exp), exp); ! 6068: return; ! 6069: ! 6070: case INTEGER_CST: ! 6071: ! 6072: #ifdef DEBUG_PRINT_CODE ! 6073: fprintf (stderr, " [%x]\n", TREE_INT_CST_LOW (exp)); ! 6074: #endif ! 6075: bc_emit_instruction (mode_to_const_map[(int) (DECL_BIT_FIELD (exp) ! 6076: ? SImode ! 6077: : TYPE_MODE (TREE_TYPE (exp)))], ! 6078: (HOST_WIDE_INT) TREE_INT_CST_LOW (exp)); ! 6079: return; ! 6080: ! 6081: case REAL_CST: ! 6082: ! 6083: #if 0 ! 6084: #ifdef DEBUG_PRINT_CODE ! 6085: fprintf (stderr, " [%g]\n", (double) TREE_INT_CST_LOW (exp)); ! 6086: #endif ! 6087: /* FIX THIS: find a better way to pass real_cst's. -bson */ ! 6088: bc_emit_instruction (mode_to_const_map[TYPE_MODE (TREE_TYPE (exp))], ! 6089: (double) TREE_REAL_CST (exp)); ! 6090: #else ! 6091: abort (); ! 6092: #endif ! 6093: ! 6094: return; ! 6095: ! 6096: case CALL_EXPR: ! 6097: ! 6098: /* We build a call description vector describing the type of ! 6099: the return value and of the arguments; this call vector, ! 6100: together with a pointer to a location for the return value ! 6101: and the base of the argument list, is passed to the low ! 6102: level machine dependent call subroutine, which is responsible ! 6103: for putting the arguments wherever real functions expect ! 6104: them, as well as getting the return value back. */ ! 6105: { ! 6106: tree calldesc = 0, arg; ! 6107: int nargs = 0, i; ! 6108: rtx retval; ! 6109: ! 6110: /* Push the evaluated args on the evaluation stack in reverse ! 6111: order. Also make an entry for each arg in the calldesc ! 6112: vector while we're at it. */ ! 6113: ! 6114: TREE_OPERAND (exp, 1) = nreverse (TREE_OPERAND (exp, 1)); ! 6115: ! 6116: for (arg = TREE_OPERAND (exp, 1); arg; arg = TREE_CHAIN (arg)) ! 6117: { ! 6118: ++nargs; ! 6119: bc_expand_expr (TREE_VALUE (arg)); ! 6120: ! 6121: calldesc = tree_cons ((tree) 0, ! 6122: size_in_bytes (TREE_TYPE (TREE_VALUE (arg))), ! 6123: calldesc); ! 6124: calldesc = tree_cons ((tree) 0, ! 6125: bc_runtime_type_code (TREE_TYPE (TREE_VALUE (arg))), ! 6126: calldesc); ! 6127: } ! 6128: ! 6129: TREE_OPERAND (exp, 1) = nreverse (TREE_OPERAND (exp, 1)); ! 6130: ! 6131: /* Allocate a location for the return value and push its ! 6132: address on the evaluation stack. Also make an entry ! 6133: at the front of the calldesc for the return value type. */ ! 6134: ! 6135: type = TREE_TYPE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); ! 6136: retval = bc_allocate_local (int_size_in_bytes (type), TYPE_ALIGN (type)); ! 6137: bc_load_localaddr (retval); ! 6138: ! 6139: calldesc = tree_cons ((tree) 0, size_in_bytes (type), calldesc); ! 6140: calldesc = tree_cons ((tree) 0, bc_runtime_type_code (type), calldesc); ! 6141: ! 6142: /* Prepend the argument count. */ ! 6143: calldesc = tree_cons ((tree) 0, ! 6144: build_int_2 (nargs, 0), ! 6145: calldesc); ! 6146: ! 6147: /* Push the address of the call description vector on the stack. */ ! 6148: calldesc = build_nt (CONSTRUCTOR, (tree) 0, calldesc); ! 6149: TREE_TYPE (calldesc) = build_array_type (integer_type_node, ! 6150: build_index_type (build_int_2 (nargs * 2, 0))); ! 6151: r = output_constant_def (calldesc); ! 6152: bc_load_externaddr (r); ! 6153: ! 6154: /* Push the address of the function to be called. */ ! 6155: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6156: ! 6157: /* Call the function, popping its address and the calldesc vector ! 6158: address off the evaluation stack in the process. */ ! 6159: bc_emit_instruction (call); ! 6160: ! 6161: /* Pop the arguments off the stack. */ ! 6162: bc_adjust_stack (nargs); ! 6163: ! 6164: /* Load the return value onto the stack. */ ! 6165: bc_load_localaddr (retval); ! 6166: bc_load_memory (type, TREE_OPERAND (exp, 0)); ! 6167: } ! 6168: return; ! 6169: ! 6170: case SAVE_EXPR: ! 6171: ! 6172: if (!SAVE_EXPR_RTL (exp)) ! 6173: { ! 6174: /* First time around: copy to local variable */ ! 6175: SAVE_EXPR_RTL (exp) = bc_allocate_local (int_size_in_bytes (TREE_TYPE (exp)), ! 6176: TYPE_ALIGN (TREE_TYPE(exp))); ! 6177: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6178: bc_emit_instruction (duplicate); ! 6179: ! 6180: bc_load_localaddr (SAVE_EXPR_RTL (exp)); ! 6181: bc_store_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0)); ! 6182: } ! 6183: else ! 6184: { ! 6185: /* Consecutive reference: use saved copy */ ! 6186: bc_load_localaddr (SAVE_EXPR_RTL (exp)); ! 6187: bc_load_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0)); ! 6188: } ! 6189: return; ! 6190: ! 6191: #if 0 ! 6192: /* FIXME: the XXXX_STMT codes have been removed in GCC2, but ! 6193: how are they handled instead? */ ! 6194: case LET_STMT: ! 6195: ! 6196: TREE_USED (exp) = 1; ! 6197: bc_expand_expr (STMT_BODY (exp)); ! 6198: return; ! 6199: #endif ! 6200: ! 6201: case NOP_EXPR: ! 6202: case CONVERT_EXPR: ! 6203: ! 6204: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6205: bc_expand_conversion (TREE_TYPE (TREE_OPERAND (exp, 0)), TREE_TYPE (exp)); ! 6206: return; ! 6207: ! 6208: case MODIFY_EXPR: ! 6209: ! 6210: expand_assignment (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), 0, 0); ! 6211: return; ! 6212: ! 6213: case ADDR_EXPR: ! 6214: ! 6215: bc_expand_address (TREE_OPERAND (exp, 0)); ! 6216: return; ! 6217: ! 6218: case INDIRECT_REF: ! 6219: ! 6220: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6221: bc_load_memory (TREE_TYPE (exp), TREE_OPERAND (exp, 0)); ! 6222: return; ! 6223: ! 6224: case ARRAY_REF: ! 6225: ! 6226: bc_expand_expr (bc_canonicalize_array_ref (exp)); ! 6227: return; ! 6228: ! 6229: case COMPONENT_REF: ! 6230: ! 6231: bc_expand_component_address (exp); ! 6232: ! 6233: /* If we have a bitfield, generate a proper load */ ! 6234: bc_load_memory (TREE_TYPE (TREE_OPERAND (exp, 1)), TREE_OPERAND (exp, 1)); ! 6235: return; ! 6236: ! 6237: case COMPOUND_EXPR: ! 6238: ! 6239: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6240: bc_emit_instruction (drop); ! 6241: bc_expand_expr (TREE_OPERAND (exp, 1)); ! 6242: return; ! 6243: ! 6244: case COND_EXPR: ! 6245: ! 6246: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6247: bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 6248: lab = bc_get_bytecode_label (); ! 6249: bc_emit_bytecode (xjumpifnot); ! 6250: bc_emit_bytecode_labelref (lab); ! 6251: ! 6252: #ifdef DEBUG_PRINT_CODE ! 6253: fputc ('\n', stderr); ! 6254: #endif ! 6255: bc_expand_expr (TREE_OPERAND (exp, 1)); ! 6256: lab1 = bc_get_bytecode_label (); ! 6257: bc_emit_bytecode (jump); ! 6258: bc_emit_bytecode_labelref (lab1); ! 6259: ! 6260: #ifdef DEBUG_PRINT_CODE ! 6261: fputc ('\n', stderr); ! 6262: #endif ! 6263: ! 6264: bc_emit_bytecode_labeldef (lab); ! 6265: bc_expand_expr (TREE_OPERAND (exp, 2)); ! 6266: bc_emit_bytecode_labeldef (lab1); ! 6267: return; ! 6268: ! 6269: case TRUTH_ANDIF_EXPR: ! 6270: ! 6271: opcode = xjumpifnot; ! 6272: goto andorif; ! 6273: ! 6274: case TRUTH_ORIF_EXPR: ! 6275: ! 6276: opcode = xjumpif; ! 6277: goto andorif; ! 6278: ! 6279: case PLUS_EXPR: ! 6280: ! 6281: binoptab = optab_plus_expr; ! 6282: goto binop; ! 6283: ! 6284: case MINUS_EXPR: ! 6285: ! 6286: binoptab = optab_minus_expr; ! 6287: goto binop; ! 6288: ! 6289: case MULT_EXPR: ! 6290: ! 6291: binoptab = optab_mult_expr; ! 6292: goto binop; ! 6293: ! 6294: case TRUNC_DIV_EXPR: ! 6295: case FLOOR_DIV_EXPR: ! 6296: case CEIL_DIV_EXPR: ! 6297: case ROUND_DIV_EXPR: ! 6298: case EXACT_DIV_EXPR: ! 6299: ! 6300: binoptab = optab_trunc_div_expr; ! 6301: goto binop; ! 6302: ! 6303: case TRUNC_MOD_EXPR: ! 6304: case FLOOR_MOD_EXPR: ! 6305: case CEIL_MOD_EXPR: ! 6306: case ROUND_MOD_EXPR: ! 6307: ! 6308: binoptab = optab_trunc_mod_expr; ! 6309: goto binop; ! 6310: ! 6311: case FIX_ROUND_EXPR: ! 6312: case FIX_FLOOR_EXPR: ! 6313: case FIX_CEIL_EXPR: ! 6314: abort (); /* Not used for C. */ ! 6315: ! 6316: case FIX_TRUNC_EXPR: ! 6317: case FLOAT_EXPR: ! 6318: case MAX_EXPR: ! 6319: case MIN_EXPR: ! 6320: case FFS_EXPR: ! 6321: case LROTATE_EXPR: ! 6322: case RROTATE_EXPR: ! 6323: abort (); /* FIXME */ ! 6324: ! 6325: case RDIV_EXPR: ! 6326: ! 6327: binoptab = optab_rdiv_expr; ! 6328: goto binop; ! 6329: ! 6330: case BIT_AND_EXPR: ! 6331: ! 6332: binoptab = optab_bit_and_expr; ! 6333: goto binop; ! 6334: ! 6335: case BIT_IOR_EXPR: ! 6336: ! 6337: binoptab = optab_bit_ior_expr; ! 6338: goto binop; ! 6339: ! 6340: case BIT_XOR_EXPR: ! 6341: ! 6342: binoptab = optab_bit_xor_expr; ! 6343: goto binop; ! 6344: ! 6345: case LSHIFT_EXPR: ! 6346: ! 6347: binoptab = optab_lshift_expr; ! 6348: goto binop; ! 6349: ! 6350: case RSHIFT_EXPR: ! 6351: ! 6352: binoptab = optab_rshift_expr; ! 6353: goto binop; ! 6354: ! 6355: case TRUTH_AND_EXPR: ! 6356: ! 6357: binoptab = optab_truth_and_expr; ! 6358: goto binop; ! 6359: ! 6360: case TRUTH_OR_EXPR: ! 6361: ! 6362: binoptab = optab_truth_or_expr; ! 6363: goto binop; ! 6364: ! 6365: case LT_EXPR: ! 6366: ! 6367: binoptab = optab_lt_expr; ! 6368: goto binop; ! 6369: ! 6370: case LE_EXPR: ! 6371: ! 6372: binoptab = optab_le_expr; ! 6373: goto binop; ! 6374: ! 6375: case GE_EXPR: ! 6376: ! 6377: binoptab = optab_ge_expr; ! 6378: goto binop; ! 6379: ! 6380: case GT_EXPR: ! 6381: ! 6382: binoptab = optab_gt_expr; ! 6383: goto binop; ! 6384: ! 6385: case EQ_EXPR: ! 6386: ! 6387: binoptab = optab_eq_expr; ! 6388: goto binop; ! 6389: ! 6390: case NE_EXPR: ! 6391: ! 6392: binoptab = optab_ne_expr; ! 6393: goto binop; ! 6394: ! 6395: case NEGATE_EXPR: ! 6396: ! 6397: unoptab = optab_negate_expr; ! 6398: goto unop; ! 6399: ! 6400: case BIT_NOT_EXPR: ! 6401: ! 6402: unoptab = optab_bit_not_expr; ! 6403: goto unop; ! 6404: ! 6405: case TRUTH_NOT_EXPR: ! 6406: ! 6407: unoptab = optab_truth_not_expr; ! 6408: goto unop; ! 6409: ! 6410: case PREDECREMENT_EXPR: ! 6411: ! 6412: incroptab = optab_predecrement_expr; ! 6413: goto increment; ! 6414: ! 6415: case PREINCREMENT_EXPR: ! 6416: ! 6417: incroptab = optab_preincrement_expr; ! 6418: goto increment; ! 6419: ! 6420: case POSTDECREMENT_EXPR: ! 6421: ! 6422: incroptab = optab_postdecrement_expr; ! 6423: goto increment; ! 6424: ! 6425: case POSTINCREMENT_EXPR: ! 6426: ! 6427: incroptab = optab_postincrement_expr; ! 6428: goto increment; ! 6429: ! 6430: case CONSTRUCTOR: ! 6431: ! 6432: bc_expand_constructor (exp); ! 6433: return; ! 6434: ! 6435: case ERROR_MARK: ! 6436: case RTL_EXPR: ! 6437: ! 6438: return; ! 6439: ! 6440: case BIND_EXPR: ! 6441: { ! 6442: tree vars = TREE_OPERAND (exp, 0); ! 6443: int vars_need_expansion = 0; ! 6444: ! 6445: /* Need to open a binding contour here because ! 6446: if there are any cleanups they most be contained here. */ ! 6447: expand_start_bindings (0); ! 6448: ! 6449: /* Mark the corresponding BLOCK for output. */ ! 6450: if (TREE_OPERAND (exp, 2) != 0) ! 6451: TREE_USED (TREE_OPERAND (exp, 2)) = 1; ! 6452: ! 6453: /* If VARS have not yet been expanded, expand them now. */ ! 6454: while (vars) ! 6455: { ! 6456: if (DECL_RTL (vars) == 0) ! 6457: { ! 6458: vars_need_expansion = 1; ! 6459: bc_expand_decl (vars, 0); ! 6460: } ! 6461: bc_expand_decl_init (vars); ! 6462: vars = TREE_CHAIN (vars); ! 6463: } ! 6464: ! 6465: bc_expand_expr (TREE_OPERAND (exp, 1)); ! 6466: ! 6467: expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); ! 6468: ! 6469: return; ! 6470: } ! 6471: } ! 6472: ! 6473: abort (); ! 6474: ! 6475: binop: ! 6476: ! 6477: bc_expand_binary_operation (binoptab, TREE_TYPE (exp), ! 6478: TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1)); ! 6479: return; ! 6480: ! 6481: ! 6482: unop: ! 6483: ! 6484: bc_expand_unary_operation (unoptab, TREE_TYPE (exp), TREE_OPERAND (exp, 0)); ! 6485: return; ! 6486: ! 6487: ! 6488: andorif: ! 6489: ! 6490: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 6491: bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 6492: lab = bc_get_bytecode_label (); ! 6493: ! 6494: bc_emit_instruction (duplicate); ! 6495: bc_emit_bytecode (opcode); ! 6496: bc_emit_bytecode_labelref (lab); ! 6497: ! 6498: #ifdef DEBUG_PRINT_CODE ! 6499: fputc ('\n', stderr); ! 6500: #endif ! 6501: ! 6502: bc_emit_instruction (drop); ! 6503: ! 6504: bc_expand_expr (TREE_OPERAND (exp, 1)); ! 6505: bc_expand_truth_conversion (TREE_TYPE (TREE_OPERAND (exp, 1))); ! 6506: bc_emit_bytecode_labeldef (lab); ! 6507: return; ! 6508: ! 6509: ! 6510: increment: ! 6511: ! 6512: type = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 6513: ! 6514: /* Push the quantum. */ ! 6515: bc_expand_expr (TREE_OPERAND (exp, 1)); ! 6516: ! 6517: /* Convert it to the lvalue's type. */ ! 6518: bc_expand_conversion (TREE_TYPE (TREE_OPERAND (exp, 1)), type); ! 6519: ! 6520: /* Push the address of the lvalue */ ! 6521: bc_expand_expr (build1 (ADDR_EXPR, TYPE_POINTER_TO (type), TREE_OPERAND (exp, 0))); ! 6522: ! 6523: /* Perform actual increment */ ! 6524: bc_expand_increment (incroptab, type); ! 6525: return; ! 6526: } ! 6527: ! 6528: /* Return the alignment in bits of EXP, a pointer valued expression. ! 6529: But don't return more than MAX_ALIGN no matter what. ! 6530: The alignment returned is, by default, the alignment of the thing that ! 6531: EXP points to (if it is not a POINTER_TYPE, 0 is returned). ! 6532: ! 6533: Otherwise, look at the expression to see if we can do better, i.e., if the ! 6534: expression is actually pointing at an object whose alignment is tighter. */ ! 6535: ! 6536: static int ! 6537: get_pointer_alignment (exp, max_align) ! 6538: tree exp; ! 6539: unsigned max_align; ! 6540: { ! 6541: unsigned align, inner; ! 6542: ! 6543: if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) ! 6544: return 0; ! 6545: ! 6546: align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); ! 6547: align = MIN (align, max_align); ! 6548: ! 6549: while (1) ! 6550: { ! 6551: switch (TREE_CODE (exp)) ! 6552: { ! 6553: case NOP_EXPR: ! 6554: case CONVERT_EXPR: ! 6555: case NON_LVALUE_EXPR: ! 6556: exp = TREE_OPERAND (exp, 0); ! 6557: if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE) ! 6558: return align; ! 6559: inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))); ! 6560: inner = MIN (inner, max_align); ! 6561: align = MAX (align, inner); ! 6562: break; ! 6563: ! 6564: case PLUS_EXPR: ! 6565: /* If sum of pointer + int, restrict our maximum alignment to that ! 6566: imposed by the integer. If not, we can't do any better than ! 6567: ALIGN. */ ! 6568: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST) ! 6569: return align; ! 6570: ! 6571: while (((TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT) ! 6572: & (max_align - 1)) ! 6573: != 0) ! 6574: max_align >>= 1; ! 6575: ! 6576: exp = TREE_OPERAND (exp, 0); ! 6577: break; ! 6578: ! 6579: case ADDR_EXPR: ! 6580: /* See what we are pointing at and look at its alignment. */ ! 6581: exp = TREE_OPERAND (exp, 0); ! 6582: if (TREE_CODE (exp) == FUNCTION_DECL) ! 6583: align = MAX (align, FUNCTION_BOUNDARY); ! 6584: else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd') ! 6585: align = MAX (align, DECL_ALIGN (exp)); ! 6586: #ifdef CONSTANT_ALIGNMENT ! 6587: else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c') ! 6588: align = CONSTANT_ALIGNMENT (exp, align); ! 6589: #endif ! 6590: return MIN (align, max_align); ! 6591: ! 6592: default: ! 6593: return align; ! 6594: } ! 6595: } ! 6596: } ! 6597: ! 6598: /* Return the tree node and offset if a given argument corresponds to ! 6599: a string constant. */ ! 6600: ! 6601: static tree ! 6602: string_constant (arg, ptr_offset) ! 6603: tree arg; ! 6604: tree *ptr_offset; ! 6605: { ! 6606: STRIP_NOPS (arg); ! 6607: ! 6608: if (TREE_CODE (arg) == ADDR_EXPR ! 6609: && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST) ! 6610: { ! 6611: *ptr_offset = integer_zero_node; ! 6612: return TREE_OPERAND (arg, 0); ! 6613: } ! 6614: else if (TREE_CODE (arg) == PLUS_EXPR) ! 6615: { ! 6616: tree arg0 = TREE_OPERAND (arg, 0); ! 6617: tree arg1 = TREE_OPERAND (arg, 1); ! 6618: ! 6619: STRIP_NOPS (arg0); ! 6620: STRIP_NOPS (arg1); ! 6621: ! 6622: if (TREE_CODE (arg0) == ADDR_EXPR ! 6623: && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST) ! 6624: { ! 6625: *ptr_offset = arg1; ! 6626: return TREE_OPERAND (arg0, 0); ! 6627: } ! 6628: else if (TREE_CODE (arg1) == ADDR_EXPR ! 6629: && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST) ! 6630: { ! 6631: *ptr_offset = arg0; ! 6632: return TREE_OPERAND (arg1, 0); ! 6633: } ! 6634: } ! 6635: ! 6636: return 0; ! 6637: } ! 6638: ! 6639: /* Compute the length of a C string. TREE_STRING_LENGTH is not the right ! 6640: way, because it could contain a zero byte in the middle. ! 6641: TREE_STRING_LENGTH is the size of the character array, not the string. ! 6642: ! 6643: Unfortunately, string_constant can't access the values of const char ! 6644: arrays with initializers, so neither can we do so here. */ ! 6645: ! 6646: static tree ! 6647: c_strlen (src) ! 6648: tree src; ! 6649: { ! 6650: tree offset_node; ! 6651: int offset, max; ! 6652: char *ptr; ! 6653: ! 6654: src = string_constant (src, &offset_node); ! 6655: if (src == 0) ! 6656: return 0; ! 6657: max = TREE_STRING_LENGTH (src); ! 6658: ptr = TREE_STRING_POINTER (src); ! 6659: if (offset_node && TREE_CODE (offset_node) != INTEGER_CST) ! 6660: { ! 6661: /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't ! 6662: compute the offset to the following null if we don't know where to ! 6663: start searching for it. */ ! 6664: int i; ! 6665: for (i = 0; i < max; i++) ! 6666: if (ptr[i] == 0) ! 6667: return 0; ! 6668: /* We don't know the starting offset, but we do know that the string ! 6669: has no internal zero bytes. We can assume that the offset falls ! 6670: within the bounds of the string; otherwise, the programmer deserves ! 6671: what he gets. Subtract the offset from the length of the string, ! 6672: and return that. */ ! 6673: /* This would perhaps not be valid if we were dealing with named ! 6674: arrays in addition to literal string constants. */ ! 6675: return size_binop (MINUS_EXPR, size_int (max), offset_node); ! 6676: } ! 6677: ! 6678: /* We have a known offset into the string. Start searching there for ! 6679: a null character. */ ! 6680: if (offset_node == 0) ! 6681: offset = 0; ! 6682: else ! 6683: { ! 6684: /* Did we get a long long offset? If so, punt. */ ! 6685: if (TREE_INT_CST_HIGH (offset_node) != 0) ! 6686: return 0; ! 6687: offset = TREE_INT_CST_LOW (offset_node); ! 6688: } ! 6689: /* If the offset is known to be out of bounds, warn, and call strlen at ! 6690: runtime. */ ! 6691: if (offset < 0 || offset > max) ! 6692: { ! 6693: warning ("offset outside bounds of constant string"); ! 6694: return 0; ! 6695: } ! 6696: /* Use strlen to search for the first zero byte. Since any strings ! 6697: constructed with build_string will have nulls appended, we win even ! 6698: if we get handed something like (char[4])"abcd". ! 6699: ! 6700: Since OFFSET is our starting index into the string, no further ! 6701: calculation is needed. */ ! 6702: return size_int (strlen (ptr + offset)); ! 6703: } ! 6704: ! 6705: /* Expand an expression EXP that calls a built-in function, ! 6706: with result going to TARGET if that's convenient ! 6707: (and in mode MODE if that's convenient). ! 6708: SUBTARGET may be used as the target for computing one of EXP's operands. ! 6709: IGNORE is nonzero if the value is to be ignored. */ ! 6710: ! 6711: static rtx ! 6712: expand_builtin (exp, target, subtarget, mode, ignore) ! 6713: tree exp; ! 6714: rtx target; ! 6715: rtx subtarget; ! 6716: enum machine_mode mode; ! 6717: int ignore; ! 6718: { ! 6719: tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); ! 6720: tree arglist = TREE_OPERAND (exp, 1); ! 6721: rtx op0; ! 6722: rtx lab1, insns; ! 6723: enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); ! 6724: optab builtin_optab; ! 6725: ! 6726: switch (DECL_FUNCTION_CODE (fndecl)) ! 6727: { ! 6728: case BUILT_IN_ABS: ! 6729: case BUILT_IN_LABS: ! 6730: case BUILT_IN_FABS: ! 6731: /* build_function_call changes these into ABS_EXPR. */ ! 6732: abort (); ! 6733: ! 6734: case BUILT_IN_SIN: ! 6735: case BUILT_IN_COS: ! 6736: case BUILT_IN_FSQRT: ! 6737: /* If not optimizing, call the library function. */ ! 6738: if (! optimize) ! 6739: break; ! 6740: ! 6741: if (arglist == 0 ! 6742: /* Arg could be wrong type if user redeclared this fcn wrong. */ ! 6743: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE) ! 6744: break; ! 6745: ! 6746: /* Stabilize and compute the argument. */ ! 6747: if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL ! 6748: && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL) ! 6749: { ! 6750: exp = copy_node (exp); ! 6751: arglist = copy_node (arglist); ! 6752: TREE_OPERAND (exp, 1) = arglist; ! 6753: TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist)); ! 6754: } ! 6755: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); ! 6756: ! 6757: /* Make a suitable register to place result in. */ ! 6758: target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ! 6759: ! 6760: emit_queue (); ! 6761: start_sequence (); ! 6762: ! 6763: switch (DECL_FUNCTION_CODE (fndecl)) ! 6764: { ! 6765: case BUILT_IN_SIN: ! 6766: builtin_optab = sin_optab; break; ! 6767: case BUILT_IN_COS: ! 6768: builtin_optab = cos_optab; break; ! 6769: case BUILT_IN_FSQRT: ! 6770: builtin_optab = sqrt_optab; break; ! 6771: default: ! 6772: abort (); ! 6773: } ! 6774: ! 6775: /* Compute into TARGET. ! 6776: Set TARGET to wherever the result comes back. */ ! 6777: target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), ! 6778: builtin_optab, op0, target, 0); ! 6779: ! 6780: /* If we were unable to expand via the builtin, stop the ! 6781: sequence (without outputting the insns) and break, causing ! 6782: a call the the library function. */ ! 6783: if (target == 0) ! 6784: { ! 6785: end_sequence (); ! 6786: break; ! 6787: } ! 6788: ! 6789: /* Check the results by default. But if flag_fast_math is turned on, ! 6790: then assume sqrt will always be called with valid arguments. */ ! 6791: ! 6792: if (! flag_fast_math) ! 6793: { ! 6794: /* Don't define the builtin FP instructions ! 6795: if your machine is not IEEE. */ ! 6796: if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT) ! 6797: abort (); ! 6798: ! 6799: lab1 = gen_label_rtx (); ! 6800: ! 6801: /* Test the result; if it is NaN, set errno=EDOM because ! 6802: the argument was not in the domain. */ ! 6803: emit_cmp_insn (target, target, EQ, 0, GET_MODE (target), 0, 0); ! 6804: emit_jump_insn (gen_beq (lab1)); ! 6805: ! 6806: #if TARGET_EDOM ! 6807: { ! 6808: #ifdef GEN_ERRNO_RTX ! 6809: rtx errno_rtx = GEN_ERRNO_RTX; ! 6810: #else ! 6811: rtx errno_rtx ! 6812: = gen_rtx (MEM, word_mode, gen_rtx (SYMBOL_REF, Pmode, "*errno")); ! 6813: #endif ! 6814: ! 6815: emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM)); ! 6816: } ! 6817: #else ! 6818: /* We can't set errno=EDOM directly; let the library call do it. ! 6819: Pop the arguments right away in case the call gets deleted. */ ! 6820: NO_DEFER_POP; ! 6821: expand_call (exp, target, 0); ! 6822: OK_DEFER_POP; ! 6823: #endif ! 6824: ! 6825: emit_label (lab1); ! 6826: } ! 6827: ! 6828: /* Output the entire sequence. */ ! 6829: insns = get_insns (); ! 6830: end_sequence (); ! 6831: emit_insns (insns); ! 6832: ! 6833: return target; ! 6834: ! 6835: /* __builtin_apply_args returns block of memory allocated on ! 6836: the stack into which is stored the arg pointer, structure ! 6837: value address, static chain, and all the registers that might ! 6838: possibly be used in performing a function call. The code is ! 6839: moved to the start of the function so the incoming values are ! 6840: saved. */ ! 6841: case BUILT_IN_APPLY_ARGS: ! 6842: /* Don't do __builtin_apply_args more than once in a function. ! 6843: Save the result of the first call and reuse it. */ ! 6844: if (apply_args_value != 0) ! 6845: return apply_args_value; ! 6846: { ! 6847: /* When this function is called, it means that registers must be ! 6848: saved on entry to this function. So we migrate the ! 6849: call to the first insn of this function. */ ! 6850: rtx temp; ! 6851: rtx seq; ! 6852: ! 6853: start_sequence (); ! 6854: temp = expand_builtin_apply_args (); ! 6855: seq = get_insns (); ! 6856: end_sequence (); ! 6857: ! 6858: apply_args_value = temp; ! 6859: ! 6860: /* Put the sequence after the NOTE that starts the function. ! 6861: If this is inside a SEQUENCE, make the outer-level insn ! 6862: chain current, so the code is placed at the start of the ! 6863: function. */ ! 6864: push_topmost_sequence (); ! 6865: emit_insns_before (seq, NEXT_INSN (get_insns ())); ! 6866: pop_topmost_sequence (); ! 6867: return temp; ! 6868: } ! 6869: ! 6870: /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes ! 6871: FUNCTION with a copy of the parameters described by ! 6872: ARGUMENTS, and ARGSIZE. It returns a block of memory ! 6873: allocated on the stack into which is stored all the registers ! 6874: that might possibly be used for returning the result of a ! 6875: function. ARGUMENTS is the value returned by ! 6876: __builtin_apply_args. ARGSIZE is the number of bytes of ! 6877: arguments that must be copied. ??? How should this value be ! 6878: computed? We'll also need a safe worst case value for varargs ! 6879: functions. */ ! 6880: case BUILT_IN_APPLY: ! 6881: if (arglist == 0 ! 6882: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 6883: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 6884: || TREE_CHAIN (arglist) == 0 ! 6885: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE ! 6886: || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 ! 6887: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE) ! 6888: return const0_rtx; ! 6889: else ! 6890: { ! 6891: int i; ! 6892: tree t; ! 6893: rtx ops[3]; ! 6894: ! 6895: for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++) ! 6896: ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0); ! 6897: ! 6898: return expand_builtin_apply (ops[0], ops[1], ops[2]); ! 6899: } ! 6900: ! 6901: /* __builtin_return (RESULT) causes the function to return the ! 6902: value described by RESULT. RESULT is address of the block of ! 6903: memory returned by __builtin_apply. */ ! 6904: case BUILT_IN_RETURN: ! 6905: if (arglist ! 6906: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 6907: && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE) ! 6908: expand_builtin_return (expand_expr (TREE_VALUE (arglist), ! 6909: NULL_RTX, VOIDmode, 0)); ! 6910: return const0_rtx; ! 6911: ! 6912: case BUILT_IN_SAVEREGS: ! 6913: /* Don't do __builtin_saveregs more than once in a function. ! 6914: Save the result of the first call and reuse it. */ ! 6915: if (saveregs_value != 0) ! 6916: return saveregs_value; ! 6917: { ! 6918: /* When this function is called, it means that registers must be ! 6919: saved on entry to this function. So we migrate the ! 6920: call to the first insn of this function. */ ! 6921: rtx temp; ! 6922: rtx seq; ! 6923: rtx valreg, saved_valreg; ! 6924: ! 6925: /* Now really call the function. `expand_call' does not call ! 6926: expand_builtin, so there is no danger of infinite recursion here. */ ! 6927: start_sequence (); ! 6928: ! 6929: #ifdef EXPAND_BUILTIN_SAVEREGS ! 6930: /* Do whatever the machine needs done in this case. */ ! 6931: temp = EXPAND_BUILTIN_SAVEREGS (arglist); ! 6932: #else ! 6933: /* The register where the function returns its value ! 6934: is likely to have something else in it, such as an argument. ! 6935: So preserve that register around the call. */ ! 6936: if (value_mode != VOIDmode) ! 6937: { ! 6938: valreg = hard_libcall_value (value_mode); ! 6939: saved_valreg = gen_reg_rtx (value_mode); ! 6940: emit_move_insn (saved_valreg, valreg); ! 6941: } ! 6942: ! 6943: /* Generate the call, putting the value in a pseudo. */ ! 6944: temp = expand_call (exp, target, ignore); ! 6945: ! 6946: if (value_mode != VOIDmode) ! 6947: emit_move_insn (valreg, saved_valreg); ! 6948: #endif ! 6949: ! 6950: seq = get_insns (); ! 6951: end_sequence (); ! 6952: ! 6953: saveregs_value = temp; ! 6954: ! 6955: /* Put the sequence after the NOTE that starts the function. ! 6956: If this is inside a SEQUENCE, make the outer-level insn ! 6957: chain current, so the code is placed at the start of the ! 6958: function. */ ! 6959: push_topmost_sequence (); ! 6960: emit_insns_before (seq, NEXT_INSN (get_insns ())); ! 6961: pop_topmost_sequence (); ! 6962: return temp; ! 6963: } ! 6964: ! 6965: /* __builtin_args_info (N) returns word N of the arg space info ! 6966: for the current function. The number and meanings of words ! 6967: is controlled by the definition of CUMULATIVE_ARGS. */ ! 6968: case BUILT_IN_ARGS_INFO: ! 6969: { ! 6970: int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int); ! 6971: int i; ! 6972: int *word_ptr = (int *) ¤t_function_args_info; ! 6973: tree type, elts, result; ! 6974: ! 6975: if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0) ! 6976: fatal ("CUMULATIVE_ARGS type defined badly; see %s, line %d", ! 6977: __FILE__, __LINE__); ! 6978: ! 6979: if (arglist != 0) ! 6980: { ! 6981: tree arg = TREE_VALUE (arglist); ! 6982: if (TREE_CODE (arg) != INTEGER_CST) ! 6983: error ("argument of `__builtin_args_info' must be constant"); ! 6984: else ! 6985: { ! 6986: int wordnum = TREE_INT_CST_LOW (arg); ! 6987: ! 6988: if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg)) ! 6989: error ("argument of `__builtin_args_info' out of range"); ! 6990: else ! 6991: return GEN_INT (word_ptr[wordnum]); ! 6992: } ! 6993: } ! 6994: else ! 6995: error ("missing argument in `__builtin_args_info'"); ! 6996: ! 6997: return const0_rtx; ! 6998: ! 6999: #if 0 ! 7000: for (i = 0; i < nwords; i++) ! 7001: elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0)); ! 7002: ! 7003: type = build_array_type (integer_type_node, ! 7004: build_index_type (build_int_2 (nwords, 0))); ! 7005: result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts)); ! 7006: TREE_CONSTANT (result) = 1; ! 7007: TREE_STATIC (result) = 1; ! 7008: result = build (INDIRECT_REF, build_pointer_type (type), result); ! 7009: TREE_CONSTANT (result) = 1; ! 7010: return expand_expr (result, NULL_RTX, VOIDmode, 0); ! 7011: #endif ! 7012: } ! 7013: ! 7014: /* Return the address of the first anonymous stack arg. */ ! 7015: case BUILT_IN_NEXT_ARG: ! 7016: { ! 7017: tree fntype = TREE_TYPE (current_function_decl); ! 7018: if (!(TYPE_ARG_TYPES (fntype) != 0 ! 7019: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) ! 7020: != void_type_node))) ! 7021: { ! 7022: error ("`va_start' used in function with fixed args"); ! 7023: return const0_rtx; ! 7024: } ! 7025: } ! 7026: ! 7027: return expand_binop (Pmode, add_optab, ! 7028: current_function_internal_arg_pointer, ! 7029: current_function_arg_offset_rtx, ! 7030: NULL_RTX, 0, OPTAB_LIB_WIDEN); ! 7031: ! 7032: case BUILT_IN_CLASSIFY_TYPE: ! 7033: if (arglist != 0) ! 7034: { ! 7035: tree type = TREE_TYPE (TREE_VALUE (arglist)); ! 7036: enum tree_code code = TREE_CODE (type); ! 7037: if (code == VOID_TYPE) ! 7038: return GEN_INT (void_type_class); ! 7039: if (code == INTEGER_TYPE) ! 7040: return GEN_INT (integer_type_class); ! 7041: if (code == CHAR_TYPE) ! 7042: return GEN_INT (char_type_class); ! 7043: if (code == ENUMERAL_TYPE) ! 7044: return GEN_INT (enumeral_type_class); ! 7045: if (code == BOOLEAN_TYPE) ! 7046: return GEN_INT (boolean_type_class); ! 7047: if (code == POINTER_TYPE) ! 7048: return GEN_INT (pointer_type_class); ! 7049: if (code == REFERENCE_TYPE) ! 7050: return GEN_INT (reference_type_class); ! 7051: if (code == OFFSET_TYPE) ! 7052: return GEN_INT (offset_type_class); ! 7053: if (code == REAL_TYPE) ! 7054: return GEN_INT (real_type_class); ! 7055: if (code == COMPLEX_TYPE) ! 7056: return GEN_INT (complex_type_class); ! 7057: if (code == FUNCTION_TYPE) ! 7058: return GEN_INT (function_type_class); ! 7059: if (code == METHOD_TYPE) ! 7060: return GEN_INT (method_type_class); ! 7061: if (code == RECORD_TYPE) ! 7062: return GEN_INT (record_type_class); ! 7063: if (code == UNION_TYPE || code == QUAL_UNION_TYPE) ! 7064: return GEN_INT (union_type_class); ! 7065: if (code == ARRAY_TYPE) ! 7066: return GEN_INT (array_type_class); ! 7067: if (code == STRING_TYPE) ! 7068: return GEN_INT (string_type_class); ! 7069: if (code == SET_TYPE) ! 7070: return GEN_INT (set_type_class); ! 7071: if (code == FILE_TYPE) ! 7072: return GEN_INT (file_type_class); ! 7073: if (code == LANG_TYPE) ! 7074: return GEN_INT (lang_type_class); ! 7075: } ! 7076: return GEN_INT (no_type_class); ! 7077: ! 7078: case BUILT_IN_CONSTANT_P: ! 7079: if (arglist == 0) ! 7080: return const0_rtx; ! 7081: else ! 7082: return (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (arglist))) == 'c' ! 7083: ? const1_rtx : const0_rtx); ! 7084: ! 7085: case BUILT_IN_FRAME_ADDRESS: ! 7086: /* The argument must be a nonnegative integer constant. ! 7087: It counts the number of frames to scan up the stack. ! 7088: The value is the address of that frame. */ ! 7089: case BUILT_IN_RETURN_ADDRESS: ! 7090: /* The argument must be a nonnegative integer constant. ! 7091: It counts the number of frames to scan up the stack. ! 7092: The value is the return address saved in that frame. */ ! 7093: if (arglist == 0) ! 7094: /* Warning about missing arg was already issued. */ ! 7095: return const0_rtx; ! 7096: else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST) ! 7097: { ! 7098: error ("invalid arg to `__builtin_return_address'"); ! 7099: return const0_rtx; ! 7100: } ! 7101: else if (tree_int_cst_lt (TREE_VALUE (arglist), integer_zero_node)) ! 7102: { ! 7103: error ("invalid arg to `__builtin_return_address'"); ! 7104: return const0_rtx; ! 7105: } ! 7106: else ! 7107: { ! 7108: int count = TREE_INT_CST_LOW (TREE_VALUE (arglist)); ! 7109: rtx tem = frame_pointer_rtx; ! 7110: int i; ! 7111: ! 7112: /* Some machines need special handling before we can access arbitrary ! 7113: frames. For example, on the sparc, we must first flush all ! 7114: register windows to the stack. */ ! 7115: #ifdef SETUP_FRAME_ADDRESSES ! 7116: SETUP_FRAME_ADDRESSES (); ! 7117: #endif ! 7118: ! 7119: /* On the sparc, the return address is not in the frame, it is ! 7120: in a register. There is no way to access it off of the current ! 7121: frame pointer, but it can be accessed off the previous frame ! 7122: pointer by reading the value from the register window save ! 7123: area. */ ! 7124: #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME ! 7125: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_RETURN_ADDRESS) ! 7126: count--; ! 7127: #endif ! 7128: ! 7129: /* Scan back COUNT frames to the specified frame. */ ! 7130: for (i = 0; i < count; i++) ! 7131: { ! 7132: /* Assume the dynamic chain pointer is in the word that ! 7133: the frame address points to, unless otherwise specified. */ ! 7134: #ifdef DYNAMIC_CHAIN_ADDRESS ! 7135: tem = DYNAMIC_CHAIN_ADDRESS (tem); ! 7136: #endif ! 7137: tem = memory_address (Pmode, tem); ! 7138: tem = copy_to_reg (gen_rtx (MEM, Pmode, tem)); ! 7139: } ! 7140: ! 7141: /* For __builtin_frame_address, return what we've got. */ ! 7142: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) ! 7143: return tem; ! 7144: ! 7145: /* For __builtin_return_address, ! 7146: Get the return address from that frame. */ ! 7147: #ifdef RETURN_ADDR_RTX ! 7148: return RETURN_ADDR_RTX (count, tem); ! 7149: #else ! 7150: tem = memory_address (Pmode, ! 7151: plus_constant (tem, GET_MODE_SIZE (Pmode))); ! 7152: return copy_to_reg (gen_rtx (MEM, Pmode, tem)); ! 7153: #endif ! 7154: } ! 7155: ! 7156: case BUILT_IN_ALLOCA: ! 7157: if (arglist == 0 ! 7158: /* Arg could be non-integer if user redeclared this fcn wrong. */ ! 7159: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE) ! 7160: break; ! 7161: current_function_calls_alloca = 1; ! 7162: /* Compute the argument. */ ! 7163: op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); ! 7164: ! 7165: /* Allocate the desired space. */ ! 7166: target = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT); ! 7167: ! 7168: /* Record the new stack level for nonlocal gotos. */ ! 7169: if (nonlocal_goto_handler_slot != 0) ! 7170: emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX); ! 7171: return target; ! 7172: ! 7173: case BUILT_IN_FFS: ! 7174: /* If not optimizing, call the library function. */ ! 7175: if (!optimize) ! 7176: break; ! 7177: ! 7178: if (arglist == 0 ! 7179: /* Arg could be non-integer if user redeclared this fcn wrong. */ ! 7180: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE) ! 7181: break; ! 7182: ! 7183: /* Compute the argument. */ ! 7184: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); ! 7185: /* Compute ffs, into TARGET if possible. ! 7186: Set TARGET to wherever the result comes back. */ ! 7187: target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), ! 7188: ffs_optab, op0, target, 1); ! 7189: if (target == 0) ! 7190: abort (); ! 7191: return target; ! 7192: ! 7193: case BUILT_IN_STRLEN: ! 7194: /* If not optimizing, call the library function. */ ! 7195: if (!optimize) ! 7196: break; ! 7197: ! 7198: if (arglist == 0 ! 7199: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 7200: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) ! 7201: break; ! 7202: else ! 7203: { ! 7204: tree src = TREE_VALUE (arglist); ! 7205: tree len = c_strlen (src); ! 7206: ! 7207: int align ! 7208: = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 7209: ! 7210: rtx result, src_rtx, char_rtx; ! 7211: enum machine_mode insn_mode = value_mode, char_mode; ! 7212: enum insn_code icode; ! 7213: ! 7214: /* If the length is known, just return it. */ ! 7215: if (len != 0) ! 7216: return expand_expr (len, target, mode, 0); ! 7217: ! 7218: /* If SRC is not a pointer type, don't do this operation inline. */ ! 7219: if (align == 0) ! 7220: break; ! 7221: ! 7222: /* Call a function if we can't compute strlen in the right mode. */ ! 7223: ! 7224: while (insn_mode != VOIDmode) ! 7225: { ! 7226: icode = strlen_optab->handlers[(int) insn_mode].insn_code; ! 7227: if (icode != CODE_FOR_nothing) ! 7228: break; ! 7229: ! 7230: insn_mode = GET_MODE_WIDER_MODE (insn_mode); ! 7231: } ! 7232: if (insn_mode == VOIDmode) ! 7233: break; ! 7234: ! 7235: /* Make a place to write the result of the instruction. */ ! 7236: result = target; ! 7237: if (! (result != 0 ! 7238: && GET_CODE (result) == REG ! 7239: && GET_MODE (result) == insn_mode ! 7240: && REGNO (result) >= FIRST_PSEUDO_REGISTER)) ! 7241: result = gen_reg_rtx (insn_mode); ! 7242: ! 7243: /* Make sure the operands are acceptable to the predicates. */ ! 7244: ! 7245: if (! (*insn_operand_predicate[(int)icode][0]) (result, insn_mode)) ! 7246: result = gen_reg_rtx (insn_mode); ! 7247: ! 7248: src_rtx = memory_address (BLKmode, ! 7249: expand_expr (src, NULL_RTX, Pmode, ! 7250: EXPAND_NORMAL)); ! 7251: if (! (*insn_operand_predicate[(int)icode][1]) (src_rtx, Pmode)) ! 7252: src_rtx = copy_to_mode_reg (Pmode, src_rtx); ! 7253: ! 7254: char_rtx = const0_rtx; ! 7255: char_mode = insn_operand_mode[(int)icode][2]; ! 7256: if (! (*insn_operand_predicate[(int)icode][2]) (char_rtx, char_mode)) ! 7257: char_rtx = copy_to_mode_reg (char_mode, char_rtx); ! 7258: ! 7259: emit_insn (GEN_FCN (icode) (result, ! 7260: gen_rtx (MEM, BLKmode, src_rtx), ! 7261: char_rtx, GEN_INT (align))); ! 7262: ! 7263: /* Return the value in the proper mode for this function. */ ! 7264: if (GET_MODE (result) == value_mode) ! 7265: return result; ! 7266: else if (target != 0) ! 7267: { ! 7268: convert_move (target, result, 0); ! 7269: return target; ! 7270: } ! 7271: else ! 7272: return convert_to_mode (value_mode, result, 0); ! 7273: } ! 7274: ! 7275: case BUILT_IN_STRCPY: ! 7276: /* If not optimizing, call the library function. */ ! 7277: if (!optimize) ! 7278: break; ! 7279: ! 7280: if (arglist == 0 ! 7281: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 7282: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 7283: || TREE_CHAIN (arglist) == 0 ! 7284: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE) ! 7285: break; ! 7286: else ! 7287: { ! 7288: tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist))); ! 7289: ! 7290: if (len == 0) ! 7291: break; ! 7292: ! 7293: len = size_binop (PLUS_EXPR, len, integer_one_node); ! 7294: ! 7295: chainon (arglist, build_tree_list (NULL_TREE, len)); ! 7296: } ! 7297: ! 7298: /* Drops in. */ ! 7299: case BUILT_IN_MEMCPY: ! 7300: /* If not optimizing, call the library function. */ ! 7301: if (!optimize) ! 7302: break; ! 7303: ! 7304: if (arglist == 0 ! 7305: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 7306: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 7307: || TREE_CHAIN (arglist) == 0 ! 7308: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE ! 7309: || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 ! 7310: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE) ! 7311: break; ! 7312: else ! 7313: { ! 7314: tree dest = TREE_VALUE (arglist); ! 7315: tree src = TREE_VALUE (TREE_CHAIN (arglist)); ! 7316: tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); ! 7317: ! 7318: int src_align ! 7319: = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 7320: int dest_align ! 7321: = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 7322: rtx dest_rtx, dest_mem, src_mem; ! 7323: ! 7324: /* If either SRC or DEST is not a pointer type, don't do ! 7325: this operation in-line. */ ! 7326: if (src_align == 0 || dest_align == 0) ! 7327: { ! 7328: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCPY) ! 7329: TREE_CHAIN (TREE_CHAIN (arglist)) = 0; ! 7330: break; ! 7331: } ! 7332: ! 7333: dest_rtx = expand_expr (dest, NULL_RTX, Pmode, EXPAND_NORMAL); ! 7334: dest_mem = gen_rtx (MEM, BLKmode, ! 7335: memory_address (BLKmode, dest_rtx)); ! 7336: src_mem = gen_rtx (MEM, BLKmode, ! 7337: memory_address (BLKmode, ! 7338: expand_expr (src, NULL_RTX, ! 7339: Pmode, ! 7340: EXPAND_NORMAL))); ! 7341: ! 7342: /* Copy word part most expediently. */ ! 7343: emit_block_move (dest_mem, src_mem, ! 7344: expand_expr (len, NULL_RTX, VOIDmode, 0), ! 7345: MIN (src_align, dest_align)); ! 7346: return dest_rtx; ! 7347: } ! 7348: ! 7349: /* These comparison functions need an instruction that returns an actual ! 7350: index. An ordinary compare that just sets the condition codes ! 7351: is not enough. */ ! 7352: #ifdef HAVE_cmpstrsi ! 7353: case BUILT_IN_STRCMP: ! 7354: /* If not optimizing, call the library function. */ ! 7355: if (!optimize) ! 7356: break; ! 7357: ! 7358: if (arglist == 0 ! 7359: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 7360: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 7361: || TREE_CHAIN (arglist) == 0 ! 7362: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE) ! 7363: break; ! 7364: else if (!HAVE_cmpstrsi) ! 7365: break; ! 7366: { ! 7367: tree arg1 = TREE_VALUE (arglist); ! 7368: tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); ! 7369: tree offset; ! 7370: tree len, len2; ! 7371: ! 7372: len = c_strlen (arg1); ! 7373: if (len) ! 7374: len = size_binop (PLUS_EXPR, integer_one_node, len); ! 7375: len2 = c_strlen (arg2); ! 7376: if (len2) ! 7377: len2 = size_binop (PLUS_EXPR, integer_one_node, len2); ! 7378: ! 7379: /* If we don't have a constant length for the first, use the length ! 7380: of the second, if we know it. We don't require a constant for ! 7381: this case; some cost analysis could be done if both are available ! 7382: but neither is constant. For now, assume they're equally cheap. ! 7383: ! 7384: If both strings have constant lengths, use the smaller. This ! 7385: could arise if optimization results in strcpy being called with ! 7386: two fixed strings, or if the code was machine-generated. We should ! 7387: add some code to the `memcmp' handler below to deal with such ! 7388: situations, someday. */ ! 7389: if (!len || TREE_CODE (len) != INTEGER_CST) ! 7390: { ! 7391: if (len2) ! 7392: len = len2; ! 7393: else if (len == 0) ! 7394: break; ! 7395: } ! 7396: else if (len2 && TREE_CODE (len2) == INTEGER_CST) ! 7397: { ! 7398: if (tree_int_cst_lt (len2, len)) ! 7399: len = len2; ! 7400: } ! 7401: ! 7402: chainon (arglist, build_tree_list (NULL_TREE, len)); ! 7403: } ! 7404: ! 7405: /* Drops in. */ ! 7406: case BUILT_IN_MEMCMP: ! 7407: /* If not optimizing, call the library function. */ ! 7408: if (!optimize) ! 7409: break; ! 7410: ! 7411: if (arglist == 0 ! 7412: /* Arg could be non-pointer if user redeclared this fcn wrong. */ ! 7413: || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE ! 7414: || TREE_CHAIN (arglist) == 0 ! 7415: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE ! 7416: || TREE_CHAIN (TREE_CHAIN (arglist)) == 0 ! 7417: || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE) ! 7418: break; ! 7419: else if (!HAVE_cmpstrsi) ! 7420: break; ! 7421: { ! 7422: tree arg1 = TREE_VALUE (arglist); ! 7423: tree arg2 = TREE_VALUE (TREE_CHAIN (arglist)); ! 7424: tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); ! 7425: rtx result; ! 7426: ! 7427: int arg1_align ! 7428: = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 7429: int arg2_align ! 7430: = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; ! 7431: enum machine_mode insn_mode ! 7432: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; ! 7433: ! 7434: /* If we don't have POINTER_TYPE, call the function. */ ! 7435: if (arg1_align == 0 || arg2_align == 0) ! 7436: { ! 7437: if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCMP) ! 7438: TREE_CHAIN (TREE_CHAIN (arglist)) = 0; ! 7439: break; ! 7440: } ! 7441: ! 7442: /* Make a place to write the result of the instruction. */ ! 7443: result = target; ! 7444: if (! (result != 0 ! 7445: && GET_CODE (result) == REG && GET_MODE (result) == insn_mode ! 7446: && REGNO (result) >= FIRST_PSEUDO_REGISTER)) ! 7447: result = gen_reg_rtx (insn_mode); ! 7448: ! 7449: emit_insn (gen_cmpstrsi (result, ! 7450: gen_rtx (MEM, BLKmode, ! 7451: expand_expr (arg1, NULL_RTX, Pmode, ! 7452: EXPAND_NORMAL)), ! 7453: gen_rtx (MEM, BLKmode, ! 7454: expand_expr (arg2, NULL_RTX, Pmode, ! 7455: EXPAND_NORMAL)), ! 7456: expand_expr (len, NULL_RTX, VOIDmode, 0), ! 7457: GEN_INT (MIN (arg1_align, arg2_align)))); ! 7458: ! 7459: /* Return the value in the proper mode for this function. */ ! 7460: mode = TYPE_MODE (TREE_TYPE (exp)); ! 7461: if (GET_MODE (result) == mode) ! 7462: return result; ! 7463: else if (target != 0) ! 7464: { ! 7465: convert_move (target, result, 0); ! 7466: return target; ! 7467: } ! 7468: else ! 7469: return convert_to_mode (mode, result, 0); ! 7470: } ! 7471: #else ! 7472: case BUILT_IN_STRCMP: ! 7473: case BUILT_IN_MEMCMP: ! 7474: break; ! 7475: #endif ! 7476: ! 7477: default: /* just do library call, if unknown builtin */ ! 7478: error ("built-in function `%s' not currently supported", ! 7479: IDENTIFIER_POINTER (DECL_NAME (fndecl))); ! 7480: } ! 7481: ! 7482: /* The switch statement above can drop through to cause the function ! 7483: to be called normally. */ ! 7484: ! 7485: return expand_call (exp, target, ignore); ! 7486: } ! 7487: ! 7488: /* Built-in functions to perform an untyped call and return. */ ! 7489: ! 7490: /* For each register that may be used for calling a function, this ! 7491: gives a mode used to copy the register's value. VOIDmode indicates ! 7492: the register is not used for calling a function. If the machine ! 7493: has register windows, this gives only the outbound registers. ! 7494: INCOMING_REGNO gives the corresponding inbound register. */ ! 7495: static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER]; ! 7496: ! 7497: /* For each register that may be used for returning values, this gives ! 7498: a mode used to copy the register's value. VOIDmode indicates the ! 7499: register is not used for returning values. If the machine has ! 7500: register windows, this gives only the outbound registers. ! 7501: INCOMING_REGNO gives the corresponding inbound register. */ ! 7502: static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER]; ! 7503: ! 7504: /* For each register that may be used for calling a function, this ! 7505: gives the offset of that register into the block returned by ! 7506: __bultin_apply_args. 0 indicates that the register is not ! 7507: used for calling a function. */ ! 7508: static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER]; ! 7509: ! 7510: /* Return the offset of register REGNO into the block returned by ! 7511: __builtin_apply_args. This is not declared static, since it is ! 7512: needed in objc-act.c. */ ! 7513: ! 7514: int ! 7515: apply_args_register_offset (regno) ! 7516: int regno; ! 7517: { ! 7518: apply_args_size (); ! 7519: ! 7520: /* Arguments are always put in outgoing registers (in the argument ! 7521: block) if such make sense. */ ! 7522: #ifdef OUTGOING_REGNO ! 7523: regno = OUTGOING_REGNO(regno); ! 7524: #endif ! 7525: return apply_args_reg_offset[regno]; ! 7526: } ! 7527: ! 7528: /* Return the size required for the block returned by __builtin_apply_args, ! 7529: and initialize apply_args_mode. */ ! 7530: ! 7531: static int ! 7532: apply_args_size () ! 7533: { ! 7534: static int size = -1; ! 7535: int align, regno; ! 7536: enum machine_mode mode; ! 7537: ! 7538: /* The values computed by this function never change. */ ! 7539: if (size < 0) ! 7540: { ! 7541: /* The first value is the incoming arg-pointer. */ ! 7542: size = GET_MODE_SIZE (Pmode); ! 7543: ! 7544: /* The second value is the structure value address unless this is ! 7545: passed as an "invisible" first argument. */ ! 7546: if (struct_value_rtx) ! 7547: size += GET_MODE_SIZE (Pmode); ! 7548: ! 7549: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7550: if (FUNCTION_ARG_REGNO_P (regno)) ! 7551: { ! 7552: /* Search for the proper mode for copying this register's ! 7553: value. I'm not sure this is right, but it works so far. */ ! 7554: enum machine_mode best_mode = VOIDmode; ! 7555: ! 7556: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); ! 7557: mode != VOIDmode; ! 7558: mode = GET_MODE_WIDER_MODE (mode)) ! 7559: if (HARD_REGNO_MODE_OK (regno, mode) ! 7560: && HARD_REGNO_NREGS (regno, mode) == 1) ! 7561: best_mode = mode; ! 7562: ! 7563: if (best_mode == VOIDmode) ! 7564: for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); ! 7565: mode != VOIDmode; ! 7566: mode = GET_MODE_WIDER_MODE (mode)) ! 7567: if (HARD_REGNO_MODE_OK (regno, mode) ! 7568: && (mov_optab->handlers[(int) mode].insn_code ! 7569: != CODE_FOR_nothing)) ! 7570: best_mode = mode; ! 7571: ! 7572: mode = best_mode; ! 7573: if (mode == VOIDmode) ! 7574: abort (); ! 7575: ! 7576: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7577: if (size % align != 0) ! 7578: size = CEIL (size, align) * align; ! 7579: apply_args_reg_offset[regno] = size; ! 7580: size += GET_MODE_SIZE (mode); ! 7581: apply_args_mode[regno] = mode; ! 7582: } ! 7583: else ! 7584: { ! 7585: apply_args_mode[regno] = VOIDmode; ! 7586: apply_args_reg_offset[regno] = 0; ! 7587: } ! 7588: } ! 7589: return size; ! 7590: } ! 7591: ! 7592: /* Return the size required for the block returned by __builtin_apply, ! 7593: and initialize apply_result_mode. */ ! 7594: ! 7595: static int ! 7596: apply_result_size () ! 7597: { ! 7598: static int size = -1; ! 7599: int align, regno; ! 7600: enum machine_mode mode; ! 7601: ! 7602: /* The values computed by this function never change. */ ! 7603: if (size < 0) ! 7604: { ! 7605: size = 0; ! 7606: ! 7607: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7608: if (FUNCTION_VALUE_REGNO_P (regno)) ! 7609: { ! 7610: /* Search for the proper mode for copying this register's ! 7611: value. I'm not sure this is right, but it works so far. */ ! 7612: enum machine_mode best_mode = VOIDmode; ! 7613: ! 7614: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); ! 7615: mode != TImode; ! 7616: mode = GET_MODE_WIDER_MODE (mode)) ! 7617: if (HARD_REGNO_MODE_OK (regno, mode)) ! 7618: best_mode = mode; ! 7619: ! 7620: if (best_mode == VOIDmode) ! 7621: for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); ! 7622: mode != VOIDmode; ! 7623: mode = GET_MODE_WIDER_MODE (mode)) ! 7624: if (HARD_REGNO_MODE_OK (regno, mode) ! 7625: && (mov_optab->handlers[(int) mode].insn_code ! 7626: != CODE_FOR_nothing)) ! 7627: best_mode = mode; ! 7628: ! 7629: mode = best_mode; ! 7630: if (mode == VOIDmode) ! 7631: abort (); ! 7632: ! 7633: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7634: if (size % align != 0) ! 7635: size = CEIL (size, align) * align; ! 7636: size += GET_MODE_SIZE (mode); ! 7637: apply_result_mode[regno] = mode; ! 7638: } ! 7639: else ! 7640: apply_result_mode[regno] = VOIDmode; ! 7641: ! 7642: /* Allow targets that use untyped_call and untyped_return to override ! 7643: the size so that machine-specific information can be stored here. */ ! 7644: #ifdef APPLY_RESULT_SIZE ! 7645: size = APPLY_RESULT_SIZE; ! 7646: #endif ! 7647: } ! 7648: return size; ! 7649: } ! 7650: ! 7651: #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return) ! 7652: /* Create a vector describing the result block RESULT. If SAVEP is true, ! 7653: the result block is used to save the values; otherwise it is used to ! 7654: restore the values. */ ! 7655: ! 7656: static rtx ! 7657: result_vector (savep, result) ! 7658: int savep; ! 7659: rtx result; ! 7660: { ! 7661: int regno, size, align, nelts; ! 7662: enum machine_mode mode; ! 7663: rtx reg, mem; ! 7664: rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx)); ! 7665: ! 7666: size = nelts = 0; ! 7667: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7668: if ((mode = apply_result_mode[regno]) != VOIDmode) ! 7669: { ! 7670: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7671: if (size % align != 0) ! 7672: size = CEIL (size, align) * align; ! 7673: reg = gen_rtx (REG, mode, savep ? INCOMING_REGNO (regno) : regno); ! 7674: mem = change_address (result, mode, ! 7675: plus_constant (XEXP (result, 0), size)); ! 7676: savevec[nelts++] = (savep ! 7677: ? gen_rtx (SET, VOIDmode, mem, reg) ! 7678: : gen_rtx (SET, VOIDmode, reg, mem)); ! 7679: size += GET_MODE_SIZE (mode); ! 7680: } ! 7681: return gen_rtx (PARALLEL, VOIDmode, gen_rtvec_v (nelts, savevec)); ! 7682: } ! 7683: #endif /* HAVE_untyped_call or HAVE_untyped_return */ ! 7684: ! 7685: /* Save the state required to perform an untyped call with the same ! 7686: arguments as were passed to the current function. */ ! 7687: ! 7688: static rtx ! 7689: expand_builtin_apply_args () ! 7690: { ! 7691: rtx registers; ! 7692: int size, align, regno; ! 7693: enum machine_mode mode; ! 7694: ! 7695: /* Create a block where the arg-pointer, structure value address, ! 7696: and argument registers can be saved. */ ! 7697: registers = assign_stack_local (BLKmode, apply_args_size (), -1); ! 7698: ! 7699: /* Walk past the arg-pointer and structure value address. */ ! 7700: size = GET_MODE_SIZE (Pmode); ! 7701: if (struct_value_rtx) ! 7702: size += GET_MODE_SIZE (Pmode); ! 7703: ! 7704: /* Save each register used in calling a function to the block. */ ! 7705: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7706: if ((mode = apply_args_mode[regno]) != VOIDmode) ! 7707: { ! 7708: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7709: if (size % align != 0) ! 7710: size = CEIL (size, align) * align; ! 7711: emit_move_insn (change_address (registers, mode, ! 7712: plus_constant (XEXP (registers, 0), ! 7713: size)), ! 7714: gen_rtx (REG, mode, INCOMING_REGNO (regno))); ! 7715: size += GET_MODE_SIZE (mode); ! 7716: } ! 7717: ! 7718: /* Save the arg pointer to the block. */ ! 7719: emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)), ! 7720: copy_to_reg (virtual_incoming_args_rtx)); ! 7721: size = GET_MODE_SIZE (Pmode); ! 7722: ! 7723: /* Save the structure value address unless this is passed as an ! 7724: "invisible" first argument. */ ! 7725: if (struct_value_incoming_rtx) ! 7726: { ! 7727: emit_move_insn (change_address (registers, Pmode, ! 7728: plus_constant (XEXP (registers, 0), ! 7729: size)), ! 7730: copy_to_reg (struct_value_incoming_rtx)); ! 7731: size += GET_MODE_SIZE (Pmode); ! 7732: } ! 7733: ! 7734: /* Return the address of the block. */ ! 7735: return copy_addr_to_reg (XEXP (registers, 0)); ! 7736: } ! 7737: ! 7738: /* Perform an untyped call and save the state required to perform an ! 7739: untyped return of whatever value was returned by the given function. */ ! 7740: ! 7741: static rtx ! 7742: expand_builtin_apply (function, arguments, argsize) ! 7743: rtx function, arguments, argsize; ! 7744: { ! 7745: int size, align, regno; ! 7746: enum machine_mode mode; ! 7747: rtx incoming_args, result, reg, dest, call_insn; ! 7748: rtx old_stack_level = 0; ! 7749: rtx use_insns = 0; ! 7750: ! 7751: /* Create a block where the return registers can be saved. */ ! 7752: result = assign_stack_local (BLKmode, apply_result_size (), -1); ! 7753: ! 7754: /* ??? The argsize value should be adjusted here. */ ! 7755: ! 7756: /* Fetch the arg pointer from the ARGUMENTS block. */ ! 7757: incoming_args = gen_reg_rtx (Pmode); ! 7758: emit_move_insn (incoming_args, ! 7759: gen_rtx (MEM, Pmode, arguments)); ! 7760: #ifndef STACK_GROWS_DOWNWARD ! 7761: incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize, ! 7762: incoming_args, 0, OPTAB_LIB_WIDEN); ! 7763: #endif ! 7764: ! 7765: /* Perform postincrements before actually calling the function. */ ! 7766: emit_queue (); ! 7767: ! 7768: /* Push a new argument block and copy the arguments. */ ! 7769: do_pending_stack_adjust (); ! 7770: emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); ! 7771: ! 7772: /* Push a block of memory onto the stack to store the memory arguments. ! 7773: Save the address in a register, and copy the memory arguments. ??? I ! 7774: haven't figured out how the calling convention macros effect this, ! 7775: but it's likely that the source and/or destination addresses in ! 7776: the block copy will need updating in machine specific ways. */ ! 7777: dest = copy_addr_to_reg (push_block (argsize, 0, 0)); ! 7778: emit_block_move (gen_rtx (MEM, BLKmode, dest), ! 7779: gen_rtx (MEM, BLKmode, incoming_args), ! 7780: argsize, ! 7781: PARM_BOUNDARY / BITS_PER_UNIT); ! 7782: ! 7783: /* Refer to the argument block. */ ! 7784: apply_args_size (); ! 7785: arguments = gen_rtx (MEM, BLKmode, arguments); ! 7786: ! 7787: /* Walk past the arg-pointer and structure value address. */ ! 7788: size = GET_MODE_SIZE (Pmode); ! 7789: if (struct_value_rtx) ! 7790: size += GET_MODE_SIZE (Pmode); ! 7791: ! 7792: /* Restore each of the registers previously saved. Make USE insns ! 7793: for each of these registers for use in making the call. */ ! 7794: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7795: if ((mode = apply_args_mode[regno]) != VOIDmode) ! 7796: { ! 7797: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7798: if (size % align != 0) ! 7799: size = CEIL (size, align) * align; ! 7800: reg = gen_rtx (REG, mode, regno); ! 7801: emit_move_insn (reg, ! 7802: change_address (arguments, mode, ! 7803: plus_constant (XEXP (arguments, 0), ! 7804: size))); ! 7805: ! 7806: push_to_sequence (use_insns); ! 7807: emit_insn (gen_rtx (USE, VOIDmode, reg)); ! 7808: use_insns = get_insns (); ! 7809: end_sequence (); ! 7810: size += GET_MODE_SIZE (mode); ! 7811: } ! 7812: ! 7813: /* Restore the structure value address unless this is passed as an ! 7814: "invisible" first argument. */ ! 7815: size = GET_MODE_SIZE (Pmode); ! 7816: if (struct_value_rtx) ! 7817: { ! 7818: rtx value = gen_reg_rtx (Pmode); ! 7819: emit_move_insn (value, ! 7820: change_address (arguments, Pmode, ! 7821: plus_constant (XEXP (arguments, 0), ! 7822: size))); ! 7823: emit_move_insn (struct_value_rtx, value); ! 7824: if (GET_CODE (struct_value_rtx) == REG) ! 7825: { ! 7826: push_to_sequence (use_insns); ! 7827: emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx)); ! 7828: use_insns = get_insns (); ! 7829: end_sequence (); ! 7830: } ! 7831: size += GET_MODE_SIZE (Pmode); ! 7832: } ! 7833: ! 7834: /* All arguments and registers used for the call are set up by now! */ ! 7835: function = prepare_call_address (function, NULL_TREE, &use_insns); ! 7836: ! 7837: /* Ensure address is valid. SYMBOL_REF is already valid, so no need, ! 7838: and we don't want to load it into a register as an optimization, ! 7839: because prepare_call_address already did it if it should be done. */ ! 7840: if (GET_CODE (function) != SYMBOL_REF) ! 7841: function = memory_address (FUNCTION_MODE, function); ! 7842: ! 7843: /* Generate the actual call instruction and save the return value. */ ! 7844: #ifdef HAVE_untyped_call ! 7845: if (HAVE_untyped_call) ! 7846: emit_call_insn (gen_untyped_call (gen_rtx (MEM, FUNCTION_MODE, function), ! 7847: result, result_vector (1, result))); ! 7848: else ! 7849: #endif ! 7850: #ifdef HAVE_call_value ! 7851: if (HAVE_call_value) ! 7852: { ! 7853: rtx valreg = 0; ! 7854: ! 7855: /* Locate the unique return register. It is not possible to ! 7856: express a call that sets more than one return register using ! 7857: call_value; use untyped_call for that. In fact, untyped_call ! 7858: only needs to save the return registers in the given block. */ ! 7859: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7860: if ((mode = apply_result_mode[regno]) != VOIDmode) ! 7861: { ! 7862: if (valreg) ! 7863: abort (); /* HAVE_untyped_call required. */ ! 7864: valreg = gen_rtx (REG, mode, regno); ! 7865: } ! 7866: ! 7867: emit_call_insn (gen_call_value (valreg, ! 7868: gen_rtx (MEM, FUNCTION_MODE, function), ! 7869: const0_rtx, NULL_RTX, const0_rtx)); ! 7870: ! 7871: emit_move_insn (change_address (result, GET_MODE (valreg), ! 7872: XEXP (result, 0)), ! 7873: valreg); ! 7874: } ! 7875: else ! 7876: #endif ! 7877: abort (); ! 7878: ! 7879: /* Find the CALL insn we just emitted and write the USE insns before it. */ ! 7880: for (call_insn = get_last_insn (); ! 7881: call_insn && GET_CODE (call_insn) != CALL_INSN; ! 7882: call_insn = PREV_INSN (call_insn)) ! 7883: ; ! 7884: ! 7885: if (! call_insn) ! 7886: abort (); ! 7887: ! 7888: /* Put the USE insns before the CALL. */ ! 7889: emit_insns_before (use_insns, call_insn); ! 7890: ! 7891: /* Restore the stack. */ ! 7892: emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); ! 7893: ! 7894: /* Return the address of the result block. */ ! 7895: return copy_addr_to_reg (XEXP (result, 0)); ! 7896: } ! 7897: ! 7898: /* Perform an untyped return. */ ! 7899: ! 7900: static void ! 7901: expand_builtin_return (result) ! 7902: rtx result; ! 7903: { ! 7904: int size, align, regno; ! 7905: enum machine_mode mode; ! 7906: rtx reg; ! 7907: rtx use_insns = 0; ! 7908: ! 7909: apply_result_size (); ! 7910: result = gen_rtx (MEM, BLKmode, result); ! 7911: ! 7912: #ifdef HAVE_untyped_return ! 7913: if (HAVE_untyped_return) ! 7914: { ! 7915: emit_jump_insn (gen_untyped_return (result, result_vector (0, result))); ! 7916: emit_barrier (); ! 7917: return; ! 7918: } ! 7919: #endif ! 7920: ! 7921: /* Restore the return value and note that each value is used. */ ! 7922: size = 0; ! 7923: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! 7924: if ((mode = apply_result_mode[regno]) != VOIDmode) ! 7925: { ! 7926: align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; ! 7927: if (size % align != 0) ! 7928: size = CEIL (size, align) * align; ! 7929: reg = gen_rtx (REG, mode, INCOMING_REGNO (regno)); ! 7930: emit_move_insn (reg, ! 7931: change_address (result, mode, ! 7932: plus_constant (XEXP (result, 0), ! 7933: size))); ! 7934: ! 7935: push_to_sequence (use_insns); ! 7936: emit_insn (gen_rtx (USE, VOIDmode, reg)); ! 7937: use_insns = get_insns (); ! 7938: end_sequence (); ! 7939: size += GET_MODE_SIZE (mode); ! 7940: } ! 7941: ! 7942: /* Put the USE insns before the return. */ ! 7943: emit_insns (use_insns); ! 7944: ! 7945: /* Return whatever values was restored by jumping directly to the end ! 7946: of the function. */ ! 7947: expand_null_return (); ! 7948: } ! 7949: ! 7950: /* Expand code for a post- or pre- increment or decrement ! 7951: and return the RTX for the result. ! 7952: POST is 1 for postinc/decrements and 0 for preinc/decrements. */ ! 7953: ! 7954: static rtx ! 7955: expand_increment (exp, post) ! 7956: register tree exp; ! 7957: int post; ! 7958: { ! 7959: register rtx op0, op1; ! 7960: register rtx temp, value; ! 7961: register tree incremented = TREE_OPERAND (exp, 0); ! 7962: optab this_optab = add_optab; ! 7963: int icode; ! 7964: enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); ! 7965: int op0_is_copy = 0; ! 7966: int single_insn = 0; ! 7967: /* 1 means we can't store into OP0 directly, ! 7968: because it is a subreg narrower than a word, ! 7969: and we don't dare clobber the rest of the word. */ ! 7970: int bad_subreg = 0; ! 7971: ! 7972: if (output_bytecode) ! 7973: { ! 7974: bc_expand_expr (exp); ! 7975: return NULL_RTX; ! 7976: } ! 7977: ! 7978: /* Stabilize any component ref that might need to be ! 7979: evaluated more than once below. */ ! 7980: if (!post ! 7981: || TREE_CODE (incremented) == BIT_FIELD_REF ! 7982: || (TREE_CODE (incremented) == COMPONENT_REF ! 7983: && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF ! 7984: || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1))))) ! 7985: incremented = stabilize_reference (incremented); ! 7986: /* Nested *INCREMENT_EXPRs can happen in C++. We must force innermost ! 7987: ones into save exprs so that they don't accidentally get evaluated ! 7988: more than once by the code below. */ ! 7989: if (TREE_CODE (incremented) == PREINCREMENT_EXPR ! 7990: || TREE_CODE (incremented) == PREDECREMENT_EXPR) ! 7991: incremented = save_expr (incremented); ! 7992: ! 7993: /* Compute the operands as RTX. ! 7994: Note whether OP0 is the actual lvalue or a copy of it: ! 7995: I believe it is a copy iff it is a register or subreg ! 7996: and insns were generated in computing it. */ ! 7997: ! 7998: temp = get_last_insn (); ! 7999: op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0); ! 8000: ! 8001: /* If OP0 is a SUBREG made for a promoted variable, we cannot increment ! 8002: in place but intead must do sign- or zero-extension during assignment, ! 8003: so we copy it into a new register and let the code below use it as ! 8004: a copy. ! 8005: ! 8006: Note that we can safely modify this SUBREG since it is know not to be ! 8007: shared (it was made by the expand_expr call above). */ ! 8008: ! 8009: if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0)) ! 8010: SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0)); ! 8011: else if (GET_CODE (op0) == SUBREG ! 8012: && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD) ! 8013: bad_subreg = 1; ! 8014: ! 8015: op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) ! 8016: && temp != get_last_insn ()); ! 8017: op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 8018: ! 8019: /* Decide whether incrementing or decrementing. */ ! 8020: if (TREE_CODE (exp) == POSTDECREMENT_EXPR ! 8021: || TREE_CODE (exp) == PREDECREMENT_EXPR) ! 8022: this_optab = sub_optab; ! 8023: ! 8024: /* Convert decrement by a constant into a negative increment. */ ! 8025: if (this_optab == sub_optab ! 8026: && GET_CODE (op1) == CONST_INT) ! 8027: { ! 8028: op1 = GEN_INT (- INTVAL (op1)); ! 8029: this_optab = add_optab; ! 8030: } ! 8031: ! 8032: /* For a preincrement, see if we can do this with a single instruction. */ ! 8033: if (!post) ! 8034: { ! 8035: icode = (int) this_optab->handlers[(int) mode].insn_code; ! 8036: if (icode != (int) CODE_FOR_nothing ! 8037: /* Make sure that OP0 is valid for operands 0 and 1 ! 8038: of the insn we want to queue. */ ! 8039: && (*insn_operand_predicate[icode][0]) (op0, mode) ! 8040: && (*insn_operand_predicate[icode][1]) (op0, mode) ! 8041: && (*insn_operand_predicate[icode][2]) (op1, mode)) ! 8042: single_insn = 1; ! 8043: } ! 8044: ! 8045: /* If OP0 is not the actual lvalue, but rather a copy in a register, ! 8046: then we cannot just increment OP0. We must therefore contrive to ! 8047: increment the original value. Then, for postincrement, we can return ! 8048: OP0 since it is a copy of the old value. For preincrement, expand here ! 8049: unless we can do it with a single insn. ! 8050: ! 8051: Likewise if storing directly into OP0 would clobber high bits ! 8052: we need to preserve (bad_subreg). */ ! 8053: if (op0_is_copy || (!post && !single_insn) || bad_subreg) ! 8054: { ! 8055: /* This is the easiest way to increment the value wherever it is. ! 8056: Problems with multiple evaluation of INCREMENTED are prevented ! 8057: because either (1) it is a component_ref or preincrement, ! 8058: in which case it was stabilized above, or (2) it is an array_ref ! 8059: with constant index in an array in a register, which is ! 8060: safe to reevaluate. */ ! 8061: tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR ! 8062: || TREE_CODE (exp) == PREDECREMENT_EXPR) ! 8063: ? MINUS_EXPR : PLUS_EXPR), ! 8064: TREE_TYPE (exp), ! 8065: incremented, ! 8066: TREE_OPERAND (exp, 1)); ! 8067: temp = expand_assignment (incremented, newexp, ! post, 0); ! 8068: return post ? op0 : temp; ! 8069: } ! 8070: ! 8071: if (post) ! 8072: { ! 8073: /* We have a true reference to the value in OP0. ! 8074: If there is an insn to add or subtract in this mode, queue it. ! 8075: Queueing the increment insn avoids the register shuffling ! 8076: that often results if we must increment now and first save ! 8077: the old value for subsequent use. */ ! 8078: ! 8079: #if 0 /* Turned off to avoid making extra insn for indexed memref. */ ! 8080: op0 = stabilize (op0); ! 8081: #endif ! 8082: ! 8083: icode = (int) this_optab->handlers[(int) mode].insn_code; ! 8084: if (icode != (int) CODE_FOR_nothing ! 8085: /* Make sure that OP0 is valid for operands 0 and 1 ! 8086: of the insn we want to queue. */ ! 8087: && (*insn_operand_predicate[icode][0]) (op0, mode) ! 8088: && (*insn_operand_predicate[icode][1]) (op0, mode)) ! 8089: { ! 8090: if (! (*insn_operand_predicate[icode][2]) (op1, mode)) ! 8091: op1 = force_reg (mode, op1); ! 8092: ! 8093: return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1)); ! 8094: } ! 8095: } ! 8096: ! 8097: /* Preincrement, or we can't increment with one simple insn. */ ! 8098: if (post) ! 8099: /* Save a copy of the value before inc or dec, to return it later. */ ! 8100: temp = value = copy_to_reg (op0); ! 8101: else ! 8102: /* Arrange to return the incremented value. */ ! 8103: /* Copy the rtx because expand_binop will protect from the queue, ! 8104: and the results of that would be invalid for us to return ! 8105: if our caller does emit_queue before using our result. */ ! 8106: temp = copy_rtx (value = op0); ! 8107: ! 8108: /* Increment however we can. */ ! 8109: op1 = expand_binop (mode, this_optab, value, op1, op0, ! 8110: TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); ! 8111: /* Make sure the value is stored into OP0. */ ! 8112: if (op1 != op0) ! 8113: emit_move_insn (op0, op1); ! 8114: ! 8115: return temp; ! 8116: } ! 8117: ! 8118: /* Expand all function calls contained within EXP, innermost ones first. ! 8119: But don't look within expressions that have sequence points. ! 8120: For each CALL_EXPR, record the rtx for its value ! 8121: in the CALL_EXPR_RTL field. */ ! 8122: ! 8123: static void ! 8124: preexpand_calls (exp) ! 8125: tree exp; ! 8126: { ! 8127: register int nops, i; ! 8128: int type = TREE_CODE_CLASS (TREE_CODE (exp)); ! 8129: ! 8130: if (! do_preexpand_calls) ! 8131: return; ! 8132: ! 8133: /* Only expressions and references can contain calls. */ ! 8134: ! 8135: if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r') ! 8136: return; ! 8137: ! 8138: switch (TREE_CODE (exp)) ! 8139: { ! 8140: case CALL_EXPR: ! 8141: /* Do nothing if already expanded. */ ! 8142: if (CALL_EXPR_RTL (exp) != 0) ! 8143: return; ! 8144: ! 8145: /* Do nothing to built-in functions. */ ! 8146: if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR ! 8147: || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL ! 8148: || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! 8149: CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0); ! 8150: return; ! 8151: ! 8152: case COMPOUND_EXPR: ! 8153: case COND_EXPR: ! 8154: case TRUTH_ANDIF_EXPR: ! 8155: case TRUTH_ORIF_EXPR: ! 8156: /* If we find one of these, then we can be sure ! 8157: the adjust will be done for it (since it makes jumps). ! 8158: Do it now, so that if this is inside an argument ! 8159: of a function, we don't get the stack adjustment ! 8160: after some other args have already been pushed. */ ! 8161: do_pending_stack_adjust (); ! 8162: return; ! 8163: ! 8164: case BLOCK: ! 8165: case RTL_EXPR: ! 8166: case WITH_CLEANUP_EXPR: ! 8167: return; ! 8168: ! 8169: case SAVE_EXPR: ! 8170: if (SAVE_EXPR_RTL (exp) != 0) ! 8171: return; ! 8172: } ! 8173: ! 8174: nops = tree_code_length[(int) TREE_CODE (exp)]; ! 8175: for (i = 0; i < nops; i++) ! 8176: if (TREE_OPERAND (exp, i) != 0) ! 8177: { ! 8178: type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i))); ! 8179: if (type == 'e' || type == '<' || type == '1' || type == '2' ! 8180: || type == 'r') ! 8181: preexpand_calls (TREE_OPERAND (exp, i)); ! 8182: } ! 8183: } ! 8184: ! 8185: /* At the start of a function, record that we have no previously-pushed ! 8186: arguments waiting to be popped. */ ! 8187: ! 8188: void ! 8189: init_pending_stack_adjust () ! 8190: { ! 8191: pending_stack_adjust = 0; ! 8192: } ! 8193: ! 8194: /* When exiting from function, if safe, clear out any pending stack adjust ! 8195: so the adjustment won't get done. */ ! 8196: ! 8197: void ! 8198: clear_pending_stack_adjust () ! 8199: { ! 8200: #ifdef EXIT_IGNORE_STACK ! 8201: if (! flag_omit_frame_pointer && EXIT_IGNORE_STACK ! 8202: && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline) ! 8203: && ! flag_inline_functions) ! 8204: pending_stack_adjust = 0; ! 8205: #endif ! 8206: } ! 8207: ! 8208: /* Pop any previously-pushed arguments that have not been popped yet. */ ! 8209: ! 8210: void ! 8211: do_pending_stack_adjust () ! 8212: { ! 8213: if (inhibit_defer_pop == 0) ! 8214: { ! 8215: if (pending_stack_adjust != 0) ! 8216: adjust_stack (GEN_INT (pending_stack_adjust)); ! 8217: pending_stack_adjust = 0; ! 8218: } ! 8219: } ! 8220: ! 8221: /* Expand all cleanups up to OLD_CLEANUPS. ! 8222: Needed here, and also for language-dependent calls. */ ! 8223: ! 8224: void ! 8225: expand_cleanups_to (old_cleanups) ! 8226: tree old_cleanups; ! 8227: { ! 8228: while (cleanups_this_call != old_cleanups) ! 8229: { ! 8230: expand_expr (TREE_VALUE (cleanups_this_call), NULL_RTX, VOIDmode, 0); ! 8231: cleanups_this_call = TREE_CHAIN (cleanups_this_call); ! 8232: } ! 8233: } ! 8234: ! 8235: /* Expand conditional expressions. */ ! 8236: ! 8237: /* Generate code to evaluate EXP and jump to LABEL if the value is zero. ! 8238: LABEL is an rtx of code CODE_LABEL, in this function and all the ! 8239: functions here. */ ! 8240: ! 8241: void ! 8242: jumpifnot (exp, label) ! 8243: tree exp; ! 8244: rtx label; ! 8245: { ! 8246: do_jump (exp, label, NULL_RTX); ! 8247: } ! 8248: ! 8249: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */ ! 8250: ! 8251: void ! 8252: jumpif (exp, label) ! 8253: tree exp; ! 8254: rtx label; ! 8255: { ! 8256: do_jump (exp, NULL_RTX, label); ! 8257: } ! 8258: ! 8259: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if ! 8260: the result is zero, or IF_TRUE_LABEL if the result is one. ! 8261: Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero, ! 8262: meaning fall through in that case. ! 8263: ! 8264: do_jump always does any pending stack adjust except when it does not ! 8265: actually perform a jump. An example where there is no jump ! 8266: is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null. ! 8267: ! 8268: This function is responsible for optimizing cases such as ! 8269: &&, || and comparison operators in EXP. */ ! 8270: ! 8271: void ! 8272: do_jump (exp, if_false_label, if_true_label) ! 8273: tree exp; ! 8274: rtx if_false_label, if_true_label; ! 8275: { ! 8276: register enum tree_code code = TREE_CODE (exp); ! 8277: /* Some cases need to create a label to jump to ! 8278: in order to properly fall through. ! 8279: These cases set DROP_THROUGH_LABEL nonzero. */ ! 8280: rtx drop_through_label = 0; ! 8281: rtx temp; ! 8282: rtx comparison = 0; ! 8283: int i; ! 8284: tree type; ! 8285: ! 8286: emit_queue (); ! 8287: ! 8288: switch (code) ! 8289: { ! 8290: case ERROR_MARK: ! 8291: break; ! 8292: ! 8293: case INTEGER_CST: ! 8294: temp = integer_zerop (exp) ? if_false_label : if_true_label; ! 8295: if (temp) ! 8296: emit_jump (temp); ! 8297: break; ! 8298: ! 8299: #if 0 ! 8300: /* This is not true with #pragma weak */ ! 8301: case ADDR_EXPR: ! 8302: /* The address of something can never be zero. */ ! 8303: if (if_true_label) ! 8304: emit_jump (if_true_label); ! 8305: break; ! 8306: #endif ! 8307: ! 8308: case NOP_EXPR: ! 8309: if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF ! 8310: || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF ! 8311: || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF) ! 8312: goto normal; ! 8313: case CONVERT_EXPR: ! 8314: /* If we are narrowing the operand, we have to do the compare in the ! 8315: narrower mode. */ ! 8316: if ((TYPE_PRECISION (TREE_TYPE (exp)) ! 8317: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8318: goto normal; ! 8319: case NON_LVALUE_EXPR: ! 8320: case REFERENCE_EXPR: ! 8321: case ABS_EXPR: ! 8322: case NEGATE_EXPR: ! 8323: case LROTATE_EXPR: ! 8324: case RROTATE_EXPR: ! 8325: /* These cannot change zero->non-zero or vice versa. */ ! 8326: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 8327: break; ! 8328: ! 8329: #if 0 ! 8330: /* This is never less insns than evaluating the PLUS_EXPR followed by ! 8331: a test and can be longer if the test is eliminated. */ ! 8332: case PLUS_EXPR: ! 8333: /* Reduce to minus. */ ! 8334: exp = build (MINUS_EXPR, TREE_TYPE (exp), ! 8335: TREE_OPERAND (exp, 0), ! 8336: fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)), ! 8337: TREE_OPERAND (exp, 1)))); ! 8338: /* Process as MINUS. */ ! 8339: #endif ! 8340: ! 8341: case MINUS_EXPR: ! 8342: /* Non-zero iff operands of minus differ. */ ! 8343: comparison = compare (build (NE_EXPR, TREE_TYPE (exp), ! 8344: TREE_OPERAND (exp, 0), ! 8345: TREE_OPERAND (exp, 1)), ! 8346: NE, NE); ! 8347: break; ! 8348: ! 8349: case BIT_AND_EXPR: ! 8350: /* If we are AND'ing with a small constant, do this comparison in the ! 8351: smallest type that fits. If the machine doesn't have comparisons ! 8352: that small, it will be converted back to the wider comparison. ! 8353: This helps if we are testing the sign bit of a narrower object. ! 8354: combine can't do this for us because it can't know whether a ! 8355: ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */ ! 8356: ! 8357: if (! SLOW_BYTE_ACCESS ! 8358: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! 8359: && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT ! 8360: && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0 ! 8361: && (type = type_for_size (i + 1, 1)) != 0 ! 8362: && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) ! 8363: && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code ! 8364: != CODE_FOR_nothing)) ! 8365: { ! 8366: do_jump (convert (type, exp), if_false_label, if_true_label); ! 8367: break; ! 8368: } ! 8369: goto normal; ! 8370: ! 8371: case TRUTH_NOT_EXPR: ! 8372: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 8373: break; ! 8374: ! 8375: case TRUTH_ANDIF_EXPR: ! 8376: if (if_false_label == 0) ! 8377: if_false_label = drop_through_label = gen_label_rtx (); ! 8378: do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX); ! 8379: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 8380: break; ! 8381: ! 8382: case TRUTH_ORIF_EXPR: ! 8383: if (if_true_label == 0) ! 8384: if_true_label = drop_through_label = gen_label_rtx (); ! 8385: do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label); ! 8386: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 8387: break; ! 8388: ! 8389: case COMPOUND_EXPR: ! 8390: push_temp_slots (); ! 8391: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); ! 8392: free_temp_slots (); ! 8393: pop_temp_slots (); ! 8394: emit_queue (); ! 8395: do_pending_stack_adjust (); ! 8396: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); ! 8397: break; ! 8398: ! 8399: case COMPONENT_REF: ! 8400: case BIT_FIELD_REF: ! 8401: case ARRAY_REF: ! 8402: { ! 8403: int bitsize, bitpos, unsignedp; ! 8404: enum machine_mode mode; ! 8405: tree type; ! 8406: tree offset; ! 8407: int volatilep = 0; ! 8408: ! 8409: /* Get description of this reference. We don't actually care ! 8410: about the underlying object here. */ ! 8411: get_inner_reference (exp, &bitsize, &bitpos, &offset, ! 8412: &mode, &unsignedp, &volatilep); ! 8413: ! 8414: type = type_for_size (bitsize, unsignedp); ! 8415: if (! SLOW_BYTE_ACCESS ! 8416: && type != 0 && bitsize >= 0 ! 8417: && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) ! 8418: && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code ! 8419: != CODE_FOR_nothing)) ! 8420: { ! 8421: do_jump (convert (type, exp), if_false_label, if_true_label); ! 8422: break; ! 8423: } ! 8424: goto normal; ! 8425: } ! 8426: ! 8427: case COND_EXPR: ! 8428: /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases. */ ! 8429: if (integer_onep (TREE_OPERAND (exp, 1)) ! 8430: && integer_zerop (TREE_OPERAND (exp, 2))) ! 8431: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 8432: ! 8433: else if (integer_zerop (TREE_OPERAND (exp, 1)) ! 8434: && integer_onep (TREE_OPERAND (exp, 2))) ! 8435: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 8436: ! 8437: else ! 8438: { ! 8439: register rtx label1 = gen_label_rtx (); ! 8440: drop_through_label = gen_label_rtx (); ! 8441: do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX); ! 8442: /* Now the THEN-expression. */ ! 8443: do_jump (TREE_OPERAND (exp, 1), ! 8444: if_false_label ? if_false_label : drop_through_label, ! 8445: if_true_label ? if_true_label : drop_through_label); ! 8446: /* In case the do_jump just above never jumps. */ ! 8447: do_pending_stack_adjust (); ! 8448: emit_label (label1); ! 8449: /* Now the ELSE-expression. */ ! 8450: do_jump (TREE_OPERAND (exp, 2), ! 8451: if_false_label ? if_false_label : drop_through_label, ! 8452: if_true_label ? if_true_label : drop_through_label); ! 8453: } ! 8454: break; ! 8455: ! 8456: case EQ_EXPR: ! 8457: if (integer_zerop (TREE_OPERAND (exp, 1))) ! 8458: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); ! 8459: else if (((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8460: == MODE_INT) ! 8461: && ! 8462: !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8463: || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_FLOAT ! 8464: || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_INT) ! 8465: do_jump_by_parts_equality (exp, if_false_label, if_true_label); ! 8466: else ! 8467: comparison = compare (exp, EQ, EQ); ! 8468: break; ! 8469: ! 8470: case NE_EXPR: ! 8471: if (integer_zerop (TREE_OPERAND (exp, 1))) ! 8472: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); ! 8473: else if (((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8474: == MODE_INT) ! 8475: && ! 8476: !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8477: || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_FLOAT ! 8478: || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) == MODE_COMPLEX_INT) ! 8479: do_jump_by_parts_equality (exp, if_true_label, if_false_label); ! 8480: else ! 8481: comparison = compare (exp, NE, NE); ! 8482: break; ! 8483: ! 8484: case LT_EXPR: ! 8485: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8486: == MODE_INT) ! 8487: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8488: do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label); ! 8489: else ! 8490: comparison = compare (exp, LT, LTU); ! 8491: break; ! 8492: ! 8493: case LE_EXPR: ! 8494: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8495: == MODE_INT) ! 8496: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8497: do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label); ! 8498: else ! 8499: comparison = compare (exp, LE, LEU); ! 8500: break; ! 8501: ! 8502: case GT_EXPR: ! 8503: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8504: == MODE_INT) ! 8505: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8506: do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label); ! 8507: else ! 8508: comparison = compare (exp, GT, GTU); ! 8509: break; ! 8510: ! 8511: case GE_EXPR: ! 8512: if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) ! 8513: == MODE_INT) ! 8514: && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) ! 8515: do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label); ! 8516: else ! 8517: comparison = compare (exp, GE, GEU); ! 8518: break; ! 8519: ! 8520: default: ! 8521: normal: ! 8522: temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); ! 8523: #if 0 ! 8524: /* This is not needed any more and causes poor code since it causes ! 8525: comparisons and tests from non-SI objects to have different code ! 8526: sequences. */ ! 8527: /* Copy to register to avoid generating bad insns by cse ! 8528: from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */ ! 8529: if (!cse_not_expected && GET_CODE (temp) == MEM) ! 8530: temp = copy_to_reg (temp); ! 8531: #endif ! 8532: do_pending_stack_adjust (); ! 8533: if (GET_CODE (temp) == CONST_INT) ! 8534: comparison = (temp == const0_rtx ? const0_rtx : const_true_rtx); ! 8535: else if (GET_CODE (temp) == LABEL_REF) ! 8536: comparison = const_true_rtx; ! 8537: else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT ! 8538: && !can_compare_p (GET_MODE (temp))) ! 8539: /* Note swapping the labels gives us not-equal. */ ! 8540: do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label); ! 8541: else if (GET_MODE (temp) != VOIDmode) ! 8542: comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)), ! 8543: NE, TREE_UNSIGNED (TREE_TYPE (exp)), ! 8544: GET_MODE (temp), NULL_RTX, 0); ! 8545: else ! 8546: abort (); ! 8547: } ! 8548: ! 8549: /* Do any postincrements in the expression that was tested. */ ! 8550: emit_queue (); ! 8551: ! 8552: /* If COMPARISON is nonzero here, it is an rtx that can be substituted ! 8553: straight into a conditional jump instruction as the jump condition. ! 8554: Otherwise, all the work has been done already. */ ! 8555: ! 8556: if (comparison == const_true_rtx) ! 8557: { ! 8558: if (if_true_label) ! 8559: emit_jump (if_true_label); ! 8560: } ! 8561: else if (comparison == const0_rtx) ! 8562: { ! 8563: if (if_false_label) ! 8564: emit_jump (if_false_label); ! 8565: } ! 8566: else if (comparison) ! 8567: do_jump_for_compare (comparison, if_false_label, if_true_label); ! 8568: ! 8569: if (drop_through_label) ! 8570: { ! 8571: /* If do_jump produces code that might be jumped around, ! 8572: do any stack adjusts from that code, before the place ! 8573: where control merges in. */ ! 8574: do_pending_stack_adjust (); ! 8575: emit_label (drop_through_label); ! 8576: } ! 8577: } ! 8578: ! 8579: /* Given a comparison expression EXP for values too wide to be compared ! 8580: with one insn, test the comparison and jump to the appropriate label. ! 8581: The code of EXP is ignored; we always test GT if SWAP is 0, ! 8582: and LT if SWAP is 1. */ ! 8583: ! 8584: static void ! 8585: do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label) ! 8586: tree exp; ! 8587: int swap; ! 8588: rtx if_false_label, if_true_label; ! 8589: { ! 8590: rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0); ! 8591: rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0); ! 8592: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 8593: int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); ! 8594: rtx drop_through_label = 0; ! 8595: int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 8596: int i; ! 8597: ! 8598: if (! if_true_label || ! if_false_label) ! 8599: drop_through_label = gen_label_rtx (); ! 8600: if (! if_true_label) ! 8601: if_true_label = drop_through_label; ! 8602: if (! if_false_label) ! 8603: if_false_label = drop_through_label; ! 8604: ! 8605: /* Compare a word at a time, high order first. */ ! 8606: for (i = 0; i < nwords; i++) ! 8607: { ! 8608: rtx comp; ! 8609: rtx op0_word, op1_word; ! 8610: ! 8611: if (WORDS_BIG_ENDIAN) ! 8612: { ! 8613: op0_word = operand_subword_force (op0, i, mode); ! 8614: op1_word = operand_subword_force (op1, i, mode); ! 8615: } ! 8616: else ! 8617: { ! 8618: op0_word = operand_subword_force (op0, nwords - 1 - i, mode); ! 8619: op1_word = operand_subword_force (op1, nwords - 1 - i, mode); ! 8620: } ! 8621: ! 8622: /* All but high-order word must be compared as unsigned. */ ! 8623: comp = compare_from_rtx (op0_word, op1_word, ! 8624: (unsignedp || i > 0) ? GTU : GT, ! 8625: unsignedp, word_mode, NULL_RTX, 0); ! 8626: if (comp == const_true_rtx) ! 8627: emit_jump (if_true_label); ! 8628: else if (comp != const0_rtx) ! 8629: do_jump_for_compare (comp, NULL_RTX, if_true_label); ! 8630: ! 8631: /* Consider lower words only if these are equal. */ ! 8632: comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode, ! 8633: NULL_RTX, 0); ! 8634: if (comp == const_true_rtx) ! 8635: emit_jump (if_false_label); ! 8636: else if (comp != const0_rtx) ! 8637: do_jump_for_compare (comp, NULL_RTX, if_false_label); ! 8638: } ! 8639: ! 8640: if (if_false_label) ! 8641: emit_jump (if_false_label); ! 8642: if (drop_through_label) ! 8643: emit_label (drop_through_label); ! 8644: } ! 8645: ! 8646: /* Compare OP0 with OP1, word at a time, in mode MODE. ! 8647: UNSIGNEDP says to do unsigned comparison. ! 8648: Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise. */ ! 8649: ! 8650: static void ! 8651: do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label) ! 8652: enum machine_mode mode; ! 8653: int unsignedp; ! 8654: rtx op0, op1; ! 8655: rtx if_false_label, if_true_label; ! 8656: { ! 8657: int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); ! 8658: rtx drop_through_label = 0; ! 8659: int i; ! 8660: ! 8661: if (! if_true_label || ! if_false_label) ! 8662: drop_through_label = gen_label_rtx (); ! 8663: if (! if_true_label) ! 8664: if_true_label = drop_through_label; ! 8665: if (! if_false_label) ! 8666: if_false_label = drop_through_label; ! 8667: ! 8668: /* Compare a word at a time, high order first. */ ! 8669: for (i = 0; i < nwords; i++) ! 8670: { ! 8671: rtx comp; ! 8672: rtx op0_word, op1_word; ! 8673: ! 8674: if (WORDS_BIG_ENDIAN) ! 8675: { ! 8676: op0_word = operand_subword_force (op0, i, mode); ! 8677: op1_word = operand_subword_force (op1, i, mode); ! 8678: } ! 8679: else ! 8680: { ! 8681: op0_word = operand_subword_force (op0, nwords - 1 - i, mode); ! 8682: op1_word = operand_subword_force (op1, nwords - 1 - i, mode); ! 8683: } ! 8684: ! 8685: /* All but high-order word must be compared as unsigned. */ ! 8686: comp = compare_from_rtx (op0_word, op1_word, ! 8687: (unsignedp || i > 0) ? GTU : GT, ! 8688: unsignedp, word_mode, NULL_RTX, 0); ! 8689: if (comp == const_true_rtx) ! 8690: emit_jump (if_true_label); ! 8691: else if (comp != const0_rtx) ! 8692: do_jump_for_compare (comp, NULL_RTX, if_true_label); ! 8693: ! 8694: /* Consider lower words only if these are equal. */ ! 8695: comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode, ! 8696: NULL_RTX, 0); ! 8697: if (comp == const_true_rtx) ! 8698: emit_jump (if_false_label); ! 8699: else if (comp != const0_rtx) ! 8700: do_jump_for_compare (comp, NULL_RTX, if_false_label); ! 8701: } ! 8702: ! 8703: if (if_false_label) ! 8704: emit_jump (if_false_label); ! 8705: if (drop_through_label) ! 8706: emit_label (drop_through_label); ! 8707: } ! 8708: ! 8709: /* Given an EQ_EXPR expression EXP for values too wide to be compared ! 8710: with one insn, test the comparison and jump to the appropriate label. */ ! 8711: ! 8712: static void ! 8713: do_jump_by_parts_equality (exp, if_false_label, if_true_label) ! 8714: tree exp; ! 8715: rtx if_false_label, if_true_label; ! 8716: { ! 8717: rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! 8718: rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 8719: enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); ! 8720: int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); ! 8721: int i; ! 8722: rtx drop_through_label = 0; ! 8723: ! 8724: if (! if_false_label) ! 8725: drop_through_label = if_false_label = gen_label_rtx (); ! 8726: ! 8727: for (i = 0; i < nwords; i++) ! 8728: { ! 8729: rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode), ! 8730: operand_subword_force (op1, i, mode), ! 8731: EQ, TREE_UNSIGNED (TREE_TYPE (exp)), ! 8732: word_mode, NULL_RTX, 0); ! 8733: if (comp == const_true_rtx) ! 8734: emit_jump (if_false_label); ! 8735: else if (comp != const0_rtx) ! 8736: do_jump_for_compare (comp, if_false_label, NULL_RTX); ! 8737: } ! 8738: ! 8739: if (if_true_label) ! 8740: emit_jump (if_true_label); ! 8741: if (drop_through_label) ! 8742: emit_label (drop_through_label); ! 8743: } ! 8744: ! 8745: /* Jump according to whether OP0 is 0. ! 8746: We assume that OP0 has an integer mode that is too wide ! 8747: for the available compare insns. */ ! 8748: ! 8749: static void ! 8750: do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label) ! 8751: rtx op0; ! 8752: rtx if_false_label, if_true_label; ! 8753: { ! 8754: int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD; ! 8755: int i; ! 8756: rtx drop_through_label = 0; ! 8757: ! 8758: if (! if_false_label) ! 8759: drop_through_label = if_false_label = gen_label_rtx (); ! 8760: ! 8761: for (i = 0; i < nwords; i++) ! 8762: { ! 8763: rtx comp = compare_from_rtx (operand_subword_force (op0, i, ! 8764: GET_MODE (op0)), ! 8765: const0_rtx, EQ, 1, word_mode, NULL_RTX, 0); ! 8766: if (comp == const_true_rtx) ! 8767: emit_jump (if_false_label); ! 8768: else if (comp != const0_rtx) ! 8769: do_jump_for_compare (comp, if_false_label, NULL_RTX); ! 8770: } ! 8771: ! 8772: if (if_true_label) ! 8773: emit_jump (if_true_label); ! 8774: if (drop_through_label) ! 8775: emit_label (drop_through_label); ! 8776: } ! 8777: ! 8778: /* Given a comparison expression in rtl form, output conditional branches to ! 8779: IF_TRUE_LABEL, IF_FALSE_LABEL, or both. */ ! 8780: ! 8781: static void ! 8782: do_jump_for_compare (comparison, if_false_label, if_true_label) ! 8783: rtx comparison, if_false_label, if_true_label; ! 8784: { ! 8785: if (if_true_label) ! 8786: { ! 8787: if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) ! 8788: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label)); ! 8789: else ! 8790: abort (); ! 8791: ! 8792: if (if_false_label) ! 8793: emit_jump (if_false_label); ! 8794: } ! 8795: else if (if_false_label) ! 8796: { ! 8797: rtx insn; ! 8798: rtx prev = get_last_insn (); ! 8799: rtx branch = 0; ! 8800: ! 8801: if (prev != 0) ! 8802: prev = PREV_INSN (prev); ! 8803: ! 8804: /* Output the branch with the opposite condition. Then try to invert ! 8805: what is generated. If more than one insn is a branch, or if the ! 8806: branch is not the last insn written, abort. If we can't invert ! 8807: the branch, emit make a true label, redirect this jump to that, ! 8808: emit a jump to the false label and define the true label. */ ! 8809: ! 8810: if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0) ! 8811: emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_false_label)); ! 8812: else ! 8813: abort (); ! 8814: ! 8815: /* Here we get the insn before what was just emitted. ! 8816: On some machines, emitting the branch can discard ! 8817: the previous compare insn and emit a replacement. */ ! 8818: if (prev == 0) ! 8819: /* If there's only one preceding insn... */ ! 8820: insn = get_insns (); ! 8821: else ! 8822: insn = NEXT_INSN (prev); ! 8823: ! 8824: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) ! 8825: if (GET_CODE (insn) == JUMP_INSN) ! 8826: { ! 8827: if (branch) ! 8828: abort (); ! 8829: branch = insn; ! 8830: } ! 8831: ! 8832: if (branch != get_last_insn ()) ! 8833: abort (); ! 8834: ! 8835: if (! invert_jump (branch, if_false_label)) ! 8836: { ! 8837: if_true_label = gen_label_rtx (); ! 8838: redirect_jump (branch, if_true_label); ! 8839: emit_jump (if_false_label); ! 8840: emit_label (if_true_label); ! 8841: } ! 8842: } ! 8843: } ! 8844: ! 8845: /* Generate code for a comparison expression EXP ! 8846: (including code to compute the values to be compared) ! 8847: and set (CC0) according to the result. ! 8848: SIGNED_CODE should be the rtx operation for this comparison for ! 8849: signed data; UNSIGNED_CODE, likewise for use if data is unsigned. ! 8850: ! 8851: We force a stack adjustment unless there are currently ! 8852: things pushed on the stack that aren't yet used. */ ! 8853: ! 8854: static rtx ! 8855: compare (exp, signed_code, unsigned_code) ! 8856: register tree exp; ! 8857: enum rtx_code signed_code, unsigned_code; ! 8858: { ! 8859: register rtx op0 ! 8860: = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! 8861: register rtx op1 ! 8862: = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); ! 8863: register tree type = TREE_TYPE (TREE_OPERAND (exp, 0)); ! 8864: register enum machine_mode mode = TYPE_MODE (type); ! 8865: int unsignedp = TREE_UNSIGNED (type); ! 8866: enum rtx_code code = unsignedp ? unsigned_code : signed_code; ! 8867: ! 8868: return compare_from_rtx (op0, op1, code, unsignedp, mode, ! 8869: ((mode == BLKmode) ! 8870: ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX), ! 8871: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); ! 8872: } ! 8873: ! 8874: /* Like compare but expects the values to compare as two rtx's. ! 8875: The decision as to signed or unsigned comparison must be made by the caller. ! 8876: ! 8877: If MODE is BLKmode, SIZE is an RTX giving the size of the objects being ! 8878: compared. ! 8879: ! 8880: If ALIGN is non-zero, it is the alignment of this type; if zero, the ! 8881: size of MODE should be used. */ ! 8882: ! 8883: rtx ! 8884: compare_from_rtx (op0, op1, code, unsignedp, mode, size, align) ! 8885: register rtx op0, op1; ! 8886: enum rtx_code code; ! 8887: int unsignedp; ! 8888: enum machine_mode mode; ! 8889: rtx size; ! 8890: int align; ! 8891: { ! 8892: rtx tem; ! 8893: ! 8894: /* If one operand is constant, make it the second one. Only do this ! 8895: if the other operand is not constant as well. */ ! 8896: ! 8897: if ((CONSTANT_P (op0) && ! CONSTANT_P (op1)) ! 8898: || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT)) ! 8899: { ! 8900: tem = op0; ! 8901: op0 = op1; ! 8902: op1 = tem; ! 8903: code = swap_condition (code); ! 8904: } ! 8905: ! 8906: if (flag_force_mem) ! 8907: { ! 8908: op0 = force_not_mem (op0); ! 8909: op1 = force_not_mem (op1); ! 8910: } ! 8911: ! 8912: do_pending_stack_adjust (); ! 8913: ! 8914: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT ! 8915: && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0) ! 8916: return tem; ! 8917: ! 8918: #if 0 ! 8919: /* There's no need to do this now that combine.c can eliminate lots of ! 8920: sign extensions. This can be less efficient in certain cases on other ! 8921: machines. */ ! 8922: ! 8923: /* If this is a signed equality comparison, we can do it as an ! 8924: unsigned comparison since zero-extension is cheaper than sign ! 8925: extension and comparisons with zero are done as unsigned. This is ! 8926: the case even on machines that can do fast sign extension, since ! 8927: zero-extension is easier to combine with other operations than ! 8928: sign-extension is. If we are comparing against a constant, we must ! 8929: convert it to what it would look like unsigned. */ ! 8930: if ((code == EQ || code == NE) && ! unsignedp ! 8931: && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) ! 8932: { ! 8933: if (GET_CODE (op1) == CONST_INT ! 8934: && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) ! 8935: op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); ! 8936: unsignedp = 1; ! 8937: } ! 8938: #endif ! 8939: ! 8940: emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align); ! 8941: ! 8942: return gen_rtx (code, VOIDmode, cc0_rtx, const0_rtx); ! 8943: } ! 8944: ! 8945: /* Generate code to calculate EXP using a store-flag instruction ! 8946: and return an rtx for the result. EXP is either a comparison ! 8947: or a TRUTH_NOT_EXPR whose operand is a comparison. ! 8948: ! 8949: If TARGET is nonzero, store the result there if convenient. ! 8950: ! 8951: If ONLY_CHEAP is non-zero, only do this if it is likely to be very ! 8952: cheap. ! 8953: ! 8954: Return zero if there is no suitable set-flag instruction ! 8955: available on this machine. ! 8956: ! 8957: Once expand_expr has been called on the arguments of the comparison, ! 8958: we are committed to doing the store flag, since it is not safe to ! 8959: re-evaluate the expression. We emit the store-flag insn by calling ! 8960: emit_store_flag, but only expand the arguments if we have a reason ! 8961: to believe that emit_store_flag will be successful. If we think that ! 8962: it will, but it isn't, we have to simulate the store-flag with a ! 8963: set/jump/set sequence. */ ! 8964: ! 8965: static rtx ! 8966: do_store_flag (exp, target, mode, only_cheap) ! 8967: tree exp; ! 8968: rtx target; ! 8969: enum machine_mode mode; ! 8970: int only_cheap; ! 8971: { ! 8972: enum rtx_code code; ! 8973: tree arg0, arg1, type; ! 8974: tree tem; ! 8975: enum machine_mode operand_mode; ! 8976: int invert = 0; ! 8977: int unsignedp; ! 8978: rtx op0, op1; ! 8979: enum insn_code icode; ! 8980: rtx subtarget = target; ! 8981: rtx result, label, pattern, jump_pat; ! 8982: ! 8983: /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the ! 8984: result at the end. We can't simply invert the test since it would ! 8985: have already been inverted if it were valid. This case occurs for ! 8986: some floating-point comparisons. */ ! 8987: ! 8988: if (TREE_CODE (exp) == TRUTH_NOT_EXPR) ! 8989: invert = 1, exp = TREE_OPERAND (exp, 0); ! 8990: ! 8991: arg0 = TREE_OPERAND (exp, 0); ! 8992: arg1 = TREE_OPERAND (exp, 1); ! 8993: type = TREE_TYPE (arg0); ! 8994: operand_mode = TYPE_MODE (type); ! 8995: unsignedp = TREE_UNSIGNED (type); ! 8996: ! 8997: /* We won't bother with BLKmode store-flag operations because it would mean ! 8998: passing a lot of information to emit_store_flag. */ ! 8999: if (operand_mode == BLKmode) ! 9000: return 0; ! 9001: ! 9002: STRIP_NOPS (arg0); ! 9003: STRIP_NOPS (arg1); ! 9004: ! 9005: /* Get the rtx comparison code to use. We know that EXP is a comparison ! 9006: operation of some type. Some comparisons against 1 and -1 can be ! 9007: converted to comparisons with zero. Do so here so that the tests ! 9008: below will be aware that we have a comparison with zero. These ! 9009: tests will not catch constants in the first operand, but constants ! 9010: are rarely passed as the first operand. */ ! 9011: ! 9012: switch (TREE_CODE (exp)) ! 9013: { ! 9014: case EQ_EXPR: ! 9015: code = EQ; ! 9016: break; ! 9017: case NE_EXPR: ! 9018: code = NE; ! 9019: break; ! 9020: case LT_EXPR: ! 9021: if (integer_onep (arg1)) ! 9022: arg1 = integer_zero_node, code = unsignedp ? LEU : LE; ! 9023: else ! 9024: code = unsignedp ? LTU : LT; ! 9025: break; ! 9026: case LE_EXPR: ! 9027: if (! unsignedp && integer_all_onesp (arg1)) ! 9028: arg1 = integer_zero_node, code = LT; ! 9029: else ! 9030: code = unsignedp ? LEU : LE; ! 9031: break; ! 9032: case GT_EXPR: ! 9033: if (! unsignedp && integer_all_onesp (arg1)) ! 9034: arg1 = integer_zero_node, code = GE; ! 9035: else ! 9036: code = unsignedp ? GTU : GT; ! 9037: break; ! 9038: case GE_EXPR: ! 9039: if (integer_onep (arg1)) ! 9040: arg1 = integer_zero_node, code = unsignedp ? GTU : GT; ! 9041: else ! 9042: code = unsignedp ? GEU : GE; ! 9043: break; ! 9044: default: ! 9045: abort (); ! 9046: } ! 9047: ! 9048: /* Put a constant second. */ ! 9049: if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST) ! 9050: { ! 9051: tem = arg0; arg0 = arg1; arg1 = tem; ! 9052: code = swap_condition (code); ! 9053: } ! 9054: ! 9055: /* If this is an equality or inequality test of a single bit, we can ! 9056: do this by shifting the bit being tested to the low-order bit and ! 9057: masking the result with the constant 1. If the condition was EQ, ! 9058: we xor it with 1. This does not require an scc insn and is faster ! 9059: than an scc insn even if we have it. */ ! 9060: ! 9061: if ((code == NE || code == EQ) ! 9062: && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) ! 9063: && integer_pow2p (TREE_OPERAND (arg0, 1)) ! 9064: && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT) ! 9065: { ! 9066: tree inner = TREE_OPERAND (arg0, 0); ! 9067: int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1), ! 9068: NULL_RTX, VOIDmode, 0))); ! 9069: int ops_unsignedp; ! 9070: ! 9071: /* If INNER is a right shift of a constant and it plus BITNUM does ! 9072: not overflow, adjust BITNUM and INNER. */ ! 9073: ! 9074: if (TREE_CODE (inner) == RSHIFT_EXPR ! 9075: && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST ! 9076: && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0 ! 9077: && (bitnum + TREE_INT_CST_LOW (TREE_OPERAND (inner, 1)) ! 9078: < TYPE_PRECISION (type))) ! 9079: { ! 9080: bitnum +=TREE_INT_CST_LOW (TREE_OPERAND (inner, 1)); ! 9081: inner = TREE_OPERAND (inner, 0); ! 9082: } ! 9083: ! 9084: /* If we are going to be able to omit the AND below, we must do our ! 9085: operations as unsigned. If we must use the AND, we have a choice. ! 9086: Normally unsigned is faster, but for some machines signed is. */ ! 9087: ops_unsignedp = (bitnum == TYPE_PRECISION (type) - 1 ? 1 ! 9088: #ifdef LOAD_EXTEND_OP ! 9089: : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1) ! 9090: #else ! 9091: : 1 ! 9092: #endif ! 9093: ); ! 9094: ! 9095: if (subtarget == 0 || GET_CODE (subtarget) != REG ! 9096: || GET_MODE (subtarget) != operand_mode ! 9097: || ! safe_from_p (subtarget, inner)) ! 9098: subtarget = 0; ! 9099: ! 9100: op0 = expand_expr (inner, subtarget, VOIDmode, 0); ! 9101: ! 9102: if (bitnum != 0) ! 9103: op0 = expand_shift (RSHIFT_EXPR, GET_MODE (op0), op0, ! 9104: size_int (bitnum), subtarget, ops_unsignedp); ! 9105: ! 9106: if (GET_MODE (op0) != mode) ! 9107: op0 = convert_to_mode (mode, op0, ops_unsignedp); ! 9108: ! 9109: if ((code == EQ && ! invert) || (code == NE && invert)) ! 9110: op0 = expand_binop (mode, xor_optab, op0, const1_rtx, subtarget, ! 9111: ops_unsignedp, OPTAB_LIB_WIDEN); ! 9112: ! 9113: /* Put the AND last so it can combine with more things. */ ! 9114: if (bitnum != TYPE_PRECISION (type) - 1) ! 9115: op0 = expand_and (op0, const1_rtx, subtarget); ! 9116: ! 9117: return op0; ! 9118: } ! 9119: ! 9120: /* Now see if we are likely to be able to do this. Return if not. */ ! 9121: if (! can_compare_p (operand_mode)) ! 9122: return 0; ! 9123: icode = setcc_gen_code[(int) code]; ! 9124: if (icode == CODE_FOR_nothing ! 9125: || (only_cheap && insn_operand_mode[(int) icode][0] != mode)) ! 9126: { ! 9127: /* We can only do this if it is one of the special cases that ! 9128: can be handled without an scc insn. */ ! 9129: if ((code == LT && integer_zerop (arg1)) ! 9130: || (! only_cheap && code == GE && integer_zerop (arg1))) ! 9131: ; ! 9132: else if (BRANCH_COST >= 0 ! 9133: && ! only_cheap && (code == NE || code == EQ) ! 9134: && TREE_CODE (type) != REAL_TYPE ! 9135: && ((abs_optab->handlers[(int) operand_mode].insn_code ! 9136: != CODE_FOR_nothing) ! 9137: || (ffs_optab->handlers[(int) operand_mode].insn_code ! 9138: != CODE_FOR_nothing))) ! 9139: ; ! 9140: else ! 9141: return 0; ! 9142: } ! 9143: ! 9144: preexpand_calls (exp); ! 9145: if (subtarget == 0 || GET_CODE (subtarget) != REG ! 9146: || GET_MODE (subtarget) != operand_mode ! 9147: || ! safe_from_p (subtarget, arg1)) ! 9148: subtarget = 0; ! 9149: ! 9150: op0 = expand_expr (arg0, subtarget, VOIDmode, 0); ! 9151: op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); ! 9152: ! 9153: if (target == 0) ! 9154: target = gen_reg_rtx (mode); ! 9155: ! 9156: /* Pass copies of OP0 and OP1 in case they contain a QUEUED. This is safe ! 9157: because, if the emit_store_flag does anything it will succeed and ! 9158: OP0 and OP1 will not be used subsequently. */ ! 9159: ! 9160: result = emit_store_flag (target, code, ! 9161: queued_subexp_p (op0) ? copy_rtx (op0) : op0, ! 9162: queued_subexp_p (op1) ? copy_rtx (op1) : op1, ! 9163: operand_mode, unsignedp, 1); ! 9164: ! 9165: if (result) ! 9166: { ! 9167: if (invert) ! 9168: result = expand_binop (mode, xor_optab, result, const1_rtx, ! 9169: result, 0, OPTAB_LIB_WIDEN); ! 9170: return result; ! 9171: } ! 9172: ! 9173: /* If this failed, we have to do this with set/compare/jump/set code. */ ! 9174: if (target == 0 || GET_CODE (target) != REG ! 9175: || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1)) ! 9176: target = gen_reg_rtx (GET_MODE (target)); ! 9177: ! 9178: emit_move_insn (target, invert ? const0_rtx : const1_rtx); ! 9179: result = compare_from_rtx (op0, op1, code, unsignedp, ! 9180: operand_mode, NULL_RTX, 0); ! 9181: if (GET_CODE (result) == CONST_INT) ! 9182: return (((result == const0_rtx && ! invert) ! 9183: || (result != const0_rtx && invert)) ! 9184: ? const0_rtx : const1_rtx); ! 9185: ! 9186: label = gen_label_rtx (); ! 9187: if (bcc_gen_fctn[(int) code] == 0) ! 9188: abort (); ! 9189: ! 9190: emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label)); ! 9191: emit_move_insn (target, invert ? const1_rtx : const0_rtx); ! 9192: emit_label (label); ! 9193: ! 9194: return target; ! 9195: } ! 9196: ! 9197: /* Generate a tablejump instruction (used for switch statements). */ ! 9198: ! 9199: #ifdef HAVE_tablejump ! 9200: ! 9201: /* INDEX is the value being switched on, with the lowest value ! 9202: in the table already subtracted. ! 9203: MODE is its expected mode (needed if INDEX is constant). ! 9204: RANGE is the length of the jump table. ! 9205: TABLE_LABEL is a CODE_LABEL rtx for the table itself. ! 9206: ! 9207: DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the ! 9208: index value is out of range. */ ! 9209: ! 9210: void ! 9211: do_tablejump (index, mode, range, table_label, default_label) ! 9212: rtx index, range, table_label, default_label; ! 9213: enum machine_mode mode; ! 9214: { ! 9215: register rtx temp, vector; ! 9216: ! 9217: /* Do an unsigned comparison (in the proper mode) between the index ! 9218: expression and the value which represents the length of the range. ! 9219: Since we just finished subtracting the lower bound of the range ! 9220: from the index expression, this comparison allows us to simultaneously ! 9221: check that the original index expression value is both greater than ! 9222: or equal to the minimum value of the range and less than or equal to ! 9223: the maximum value of the range. */ ! 9224: ! 9225: emit_cmp_insn (range, index, LTU, NULL_RTX, mode, 1, 0); ! 9226: emit_jump_insn (gen_bltu (default_label)); ! 9227: ! 9228: /* If index is in range, it must fit in Pmode. ! 9229: Convert to Pmode so we can index with it. */ ! 9230: if (mode != Pmode) ! 9231: index = convert_to_mode (Pmode, index, 1); ! 9232: ! 9233: /* Don't let a MEM slip thru, because then INDEX that comes ! 9234: out of PIC_CASE_VECTOR_ADDRESS won't be a valid address, ! 9235: and break_out_memory_refs will go to work on it and mess it up. */ ! 9236: #ifdef PIC_CASE_VECTOR_ADDRESS ! 9237: if (flag_pic && GET_CODE (index) != REG) ! 9238: index = copy_to_mode_reg (Pmode, index); ! 9239: #endif ! 9240: ! 9241: /* If flag_force_addr were to affect this address ! 9242: it could interfere with the tricky assumptions made ! 9243: about addresses that contain label-refs, ! 9244: which may be valid only very near the tablejump itself. */ ! 9245: /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the ! 9246: GET_MODE_SIZE, because this indicates how large insns are. The other ! 9247: uses should all be Pmode, because they are addresses. This code ! 9248: could fail if addresses and insns are not the same size. */ ! 9249: index = gen_rtx (PLUS, Pmode, ! 9250: gen_rtx (MULT, Pmode, index, ! 9251: GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))), ! 9252: gen_rtx (LABEL_REF, Pmode, table_label)); ! 9253: #ifdef PIC_CASE_VECTOR_ADDRESS ! 9254: if (flag_pic) ! 9255: index = PIC_CASE_VECTOR_ADDRESS (index); ! 9256: else ! 9257: #endif ! 9258: index = memory_address_noforce (CASE_VECTOR_MODE, index); ! 9259: temp = gen_reg_rtx (CASE_VECTOR_MODE); ! 9260: vector = gen_rtx (MEM, CASE_VECTOR_MODE, index); ! 9261: RTX_UNCHANGING_P (vector) = 1; ! 9262: convert_move (temp, vector, 0); ! 9263: ! 9264: emit_jump_insn (gen_tablejump (temp, table_label)); ! 9265: ! 9266: #ifndef CASE_VECTOR_PC_RELATIVE ! 9267: /* If we are generating PIC code or if the table is PC-relative, the ! 9268: table and JUMP_INSN must be adjacent, so don't output a BARRIER. */ ! 9269: if (! flag_pic) ! 9270: emit_barrier (); ! 9271: #endif ! 9272: } ! 9273: ! 9274: #endif /* HAVE_tablejump */ ! 9275: ! 9276: ! 9277: /* Emit a suitable bytecode to load a value from memory, assuming a pointer ! 9278: to that value is on the top of the stack. The resulting type is TYPE, and ! 9279: the source declaration is DECL. */ ! 9280: ! 9281: void ! 9282: bc_load_memory (type, decl) ! 9283: tree type, decl; ! 9284: { ! 9285: enum bytecode_opcode opcode; ! 9286: ! 9287: ! 9288: /* Bit fields are special. We only know about signed and ! 9289: unsigned ints, and enums. The latter are treated as ! 9290: signed integers. */ ! 9291: ! 9292: if (DECL_BIT_FIELD (decl)) ! 9293: if (TREE_CODE (type) == ENUMERAL_TYPE ! 9294: || TREE_CODE (type) == INTEGER_TYPE) ! 9295: opcode = TREE_UNSIGNED (type) ? zxloadBI : sxloadBI; ! 9296: else ! 9297: abort (); ! 9298: else ! 9299: /* See corresponding comment in bc_store_memory(). */ ! 9300: if (TYPE_MODE (type) == BLKmode ! 9301: || TYPE_MODE (type) == VOIDmode) ! 9302: return; ! 9303: else ! 9304: opcode = mode_to_load_map [(int) TYPE_MODE (type)]; ! 9305: ! 9306: if (opcode == neverneverland) ! 9307: abort (); ! 9308: ! 9309: bc_emit_bytecode (opcode); ! 9310: ! 9311: #ifdef DEBUG_PRINT_CODE ! 9312: fputc ('\n', stderr); ! 9313: #endif ! 9314: } ! 9315: ! 9316: ! 9317: /* Store the contents of the second stack slot to the address in the ! 9318: top stack slot. DECL is the declaration of the destination and is used ! 9319: to determine whether we're dealing with a bitfield. */ ! 9320: ! 9321: void ! 9322: bc_store_memory (type, decl) ! 9323: tree type, decl; ! 9324: { ! 9325: enum bytecode_opcode opcode; ! 9326: ! 9327: ! 9328: if (DECL_BIT_FIELD (decl)) ! 9329: { ! 9330: if (TREE_CODE (type) == ENUMERAL_TYPE ! 9331: || TREE_CODE (type) == INTEGER_TYPE) ! 9332: opcode = sstoreBI; ! 9333: else ! 9334: abort (); ! 9335: } ! 9336: else ! 9337: if (TYPE_MODE (type) == BLKmode) ! 9338: { ! 9339: /* Copy structure. This expands to a block copy instruction, storeBLK. ! 9340: In addition to the arguments expected by the other store instructions, ! 9341: it also expects a type size (SImode) on top of the stack, which is the ! 9342: structure size in size units (usually bytes). The two first arguments ! 9343: are already on the stack; so we just put the size on level 1. For some ! 9344: other languages, the size may be variable, this is why we don't encode ! 9345: it as a storeBLK literal, but rather treat it as a full-fledged expression. */ ! 9346: ! 9347: bc_expand_expr (TYPE_SIZE (type)); ! 9348: opcode = storeBLK; ! 9349: } ! 9350: else ! 9351: opcode = mode_to_store_map [(int) TYPE_MODE (type)]; ! 9352: ! 9353: if (opcode == neverneverland) ! 9354: abort (); ! 9355: ! 9356: bc_emit_bytecode (opcode); ! 9357: ! 9358: #ifdef DEBUG_PRINT_CODE ! 9359: fputc ('\n', stderr); ! 9360: #endif ! 9361: } ! 9362: ! 9363: ! 9364: /* Allocate local stack space sufficient to hold a value of the given ! 9365: SIZE at alignment boundary ALIGNMENT bits. ALIGNMENT must be an ! 9366: integral power of 2. A special case is locals of type VOID, which ! 9367: have size 0 and alignment 1 - any "voidish" SIZE or ALIGNMENT is ! 9368: remapped into the corresponding attribute of SI. */ ! 9369: ! 9370: rtx ! 9371: bc_allocate_local (size, alignment) ! 9372: int size, alignment; ! 9373: { ! 9374: rtx retval; ! 9375: int byte_alignment; ! 9376: ! 9377: if (size < 0) ! 9378: abort (); ! 9379: ! 9380: /* Normalize size and alignment */ ! 9381: if (!size) ! 9382: size = UNITS_PER_WORD; ! 9383: ! 9384: if (alignment < BITS_PER_UNIT) ! 9385: byte_alignment = 1 << (INT_ALIGN - 1); ! 9386: else ! 9387: /* Align */ ! 9388: byte_alignment = alignment / BITS_PER_UNIT; ! 9389: ! 9390: if (local_vars_size & (byte_alignment - 1)) ! 9391: local_vars_size += byte_alignment - (local_vars_size & (byte_alignment - 1)); ! 9392: ! 9393: retval = bc_gen_rtx ((char *) 0, local_vars_size, (struct bc_label *) 0); ! 9394: local_vars_size += size; ! 9395: ! 9396: return retval; ! 9397: } ! 9398: ! 9399: ! 9400: /* Allocate variable-sized local array. Variable-sized arrays are ! 9401: actually pointers to the address in memory where they are stored. */ ! 9402: ! 9403: rtx ! 9404: bc_allocate_variable_array (size) ! 9405: tree size; ! 9406: { ! 9407: rtx retval; ! 9408: const int ptralign = (1 << (PTR_ALIGN - 1)); ! 9409: ! 9410: /* Align pointer */ ! 9411: if (local_vars_size & ptralign) ! 9412: local_vars_size += ptralign - (local_vars_size & ptralign); ! 9413: ! 9414: /* Note down local space needed: pointer to block; also return ! 9415: dummy rtx */ ! 9416: ! 9417: retval = bc_gen_rtx ((char *) 0, local_vars_size, (struct bc_label *) 0); ! 9418: local_vars_size += POINTER_SIZE / BITS_PER_UNIT; ! 9419: return retval; ! 9420: } ! 9421: ! 9422: ! 9423: /* Push the machine address for the given external variable offset. */ ! 9424: void ! 9425: bc_load_externaddr (externaddr) ! 9426: rtx externaddr; ! 9427: { ! 9428: bc_emit_bytecode (constP); ! 9429: bc_emit_code_labelref (BYTECODE_LABEL (externaddr), ! 9430: BYTECODE_BC_LABEL (externaddr)->offset); ! 9431: ! 9432: #ifdef DEBUG_PRINT_CODE ! 9433: fputc ('\n', stderr); ! 9434: #endif ! 9435: } ! 9436: ! 9437: ! 9438: static char * ! 9439: bc_strdup (s) ! 9440: char *s; ! 9441: { ! 9442: char *new = (char *) xmalloc ((strlen (s) + 1) * sizeof *s); ! 9443: strcpy (new, s); ! 9444: return new; ! 9445: } ! 9446: ! 9447: ! 9448: /* Like above, but expects an IDENTIFIER. */ ! 9449: void ! 9450: bc_load_externaddr_id (id, offset) ! 9451: tree id; ! 9452: int offset; ! 9453: { ! 9454: if (!IDENTIFIER_POINTER (id)) ! 9455: abort (); ! 9456: ! 9457: bc_emit_bytecode (constP); ! 9458: bc_emit_code_labelref (bc_xstrdup (IDENTIFIER_POINTER (id)), offset); ! 9459: ! 9460: #ifdef DEBUG_PRINT_CODE ! 9461: fputc ('\n', stderr); ! 9462: #endif ! 9463: } ! 9464: ! 9465: ! 9466: /* Push the machine address for the given local variable offset. */ ! 9467: void ! 9468: bc_load_localaddr (localaddr) ! 9469: rtx localaddr; ! 9470: { ! 9471: bc_emit_instruction (localP, (HOST_WIDE_INT) BYTECODE_BC_LABEL (localaddr)->offset); ! 9472: } ! 9473: ! 9474: ! 9475: /* Push the machine address for the given parameter offset. ! 9476: NOTE: offset is in bits. */ ! 9477: void ! 9478: bc_load_parmaddr (parmaddr) ! 9479: rtx parmaddr; ! 9480: { ! 9481: bc_emit_instruction (argP, ((HOST_WIDE_INT) BYTECODE_BC_LABEL (parmaddr)->offset ! 9482: / BITS_PER_UNIT)); ! 9483: } ! 9484: ! 9485: ! 9486: /* Convert a[i] into *(a + i). */ ! 9487: tree ! 9488: bc_canonicalize_array_ref (exp) ! 9489: tree exp; ! 9490: { ! 9491: tree type = TREE_TYPE (exp); ! 9492: tree array_adr = build1 (ADDR_EXPR, TYPE_POINTER_TO (type), ! 9493: TREE_OPERAND (exp, 0)); ! 9494: tree index = TREE_OPERAND (exp, 1); ! 9495: ! 9496: ! 9497: /* Convert the integer argument to a type the same size as a pointer ! 9498: so the multiply won't overflow spuriously. */ ! 9499: ! 9500: if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE) ! 9501: index = convert (type_for_size (POINTER_SIZE, 0), index); ! 9502: ! 9503: /* The array address isn't volatile even if the array is. ! 9504: (Of course this isn't terribly relevant since the bytecode ! 9505: translator treats nearly everything as volatile anyway.) */ ! 9506: TREE_THIS_VOLATILE (array_adr) = 0; ! 9507: ! 9508: return build1 (INDIRECT_REF, type, ! 9509: fold (build (PLUS_EXPR, ! 9510: TYPE_POINTER_TO (type), ! 9511: array_adr, ! 9512: fold (build (MULT_EXPR, ! 9513: TYPE_POINTER_TO (type), ! 9514: index, ! 9515: size_in_bytes (type)))))); ! 9516: } ! 9517: ! 9518: ! 9519: /* Load the address of the component referenced by the given ! 9520: COMPONENT_REF expression. ! 9521: ! 9522: Returns innermost lvalue. */ ! 9523: ! 9524: tree ! 9525: bc_expand_component_address (exp) ! 9526: tree exp; ! 9527: { ! 9528: tree tem, chain; ! 9529: enum machine_mode mode; ! 9530: int bitpos = 0; ! 9531: HOST_WIDE_INT SIval; ! 9532: ! 9533: ! 9534: tem = TREE_OPERAND (exp, 1); ! 9535: mode = DECL_MODE (tem); ! 9536: ! 9537: ! 9538: /* Compute cumulative bit offset for nested component refs ! 9539: and array refs, and find the ultimate containing object. */ ! 9540: ! 9541: for (tem = exp;; tem = TREE_OPERAND (tem, 0)) ! 9542: { ! 9543: if (TREE_CODE (tem) == COMPONENT_REF) ! 9544: bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (tem, 1))); ! 9545: else ! 9546: if (TREE_CODE (tem) == ARRAY_REF ! 9547: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST ! 9548: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST) ! 9549: ! 9550: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)) ! 9551: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem))) ! 9552: /* * TYPE_SIZE_UNIT (TREE_TYPE (tem)) */); ! 9553: else ! 9554: break; ! 9555: } ! 9556: ! 9557: bc_expand_expr (tem); ! 9558: ! 9559: ! 9560: /* For bitfields also push their offset and size */ ! 9561: if (DECL_BIT_FIELD (TREE_OPERAND (exp, 1))) ! 9562: bc_push_offset_and_size (bitpos, /* DECL_SIZE_UNIT */ (TREE_OPERAND (exp, 1))); ! 9563: else ! 9564: if (SIval = bitpos / BITS_PER_UNIT) ! 9565: bc_emit_instruction (addconstPSI, SIval); ! 9566: ! 9567: return (TREE_OPERAND (exp, 1)); ! 9568: } ! 9569: ! 9570: ! 9571: /* Emit code to push two SI constants */ ! 9572: void ! 9573: bc_push_offset_and_size (offset, size) ! 9574: HOST_WIDE_INT offset, size; ! 9575: { ! 9576: bc_emit_instruction (constSI, offset); ! 9577: bc_emit_instruction (constSI, size); ! 9578: } ! 9579: ! 9580: ! 9581: /* Emit byte code to push the address of the given lvalue expression to ! 9582: the stack. If it's a bit field, we also push offset and size info. ! 9583: ! 9584: Returns innermost component, which allows us to determine not only ! 9585: its type, but also whether it's a bitfield. */ ! 9586: ! 9587: tree ! 9588: bc_expand_address (exp) ! 9589: tree exp; ! 9590: { ! 9591: /* Safeguard */ ! 9592: if (!exp || TREE_CODE (exp) == ERROR_MARK) ! 9593: return (exp); ! 9594: ! 9595: ! 9596: switch (TREE_CODE (exp)) ! 9597: { ! 9598: case ARRAY_REF: ! 9599: ! 9600: return (bc_expand_address (bc_canonicalize_array_ref (exp))); ! 9601: ! 9602: case COMPONENT_REF: ! 9603: ! 9604: return (bc_expand_component_address (exp)); ! 9605: ! 9606: case INDIRECT_REF: ! 9607: ! 9608: bc_expand_expr (TREE_OPERAND (exp, 0)); ! 9609: ! 9610: /* For variable-sized types: retrieve pointer. Sometimes the ! 9611: TYPE_SIZE tree is NULL. Is this a bug or a feature? Let's ! 9612: also make sure we have an operand, just in case... */ ! 9613: ! 9614: if (TREE_OPERAND (exp, 0) ! 9615: && TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0))) ! 9616: && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)))) != INTEGER_CST) ! 9617: bc_emit_instruction (loadP); ! 9618: ! 9619: /* If packed, also return offset and size */ ! 9620: if (DECL_BIT_FIELD (TREE_OPERAND (exp, 0))) ! 9621: ! 9622: bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (exp, 0))), ! 9623: TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (exp, 0)))); ! 9624: ! 9625: return (TREE_OPERAND (exp, 0)); ! 9626: ! 9627: case FUNCTION_DECL: ! 9628: ! 9629: bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp), ! 9630: BYTECODE_BC_LABEL (DECL_RTL (exp))->offset); ! 9631: break; ! 9632: ! 9633: case PARM_DECL: ! 9634: ! 9635: bc_load_parmaddr (DECL_RTL (exp)); ! 9636: ! 9637: /* For variable-sized types: retrieve pointer */ ! 9638: if (TYPE_SIZE (TREE_TYPE (exp)) ! 9639: && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST) ! 9640: bc_emit_instruction (loadP); ! 9641: ! 9642: /* If packed, also return offset and size */ ! 9643: if (DECL_BIT_FIELD (exp)) ! 9644: bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (exp)), ! 9645: TREE_INT_CST_LOW (DECL_SIZE (exp))); ! 9646: ! 9647: break; ! 9648: ! 9649: case RESULT_DECL: ! 9650: ! 9651: bc_emit_instruction (returnP); ! 9652: break; ! 9653: ! 9654: case VAR_DECL: ! 9655: ! 9656: #if 0 ! 9657: if (BYTECODE_LABEL (DECL_RTL (exp))) ! 9658: bc_load_externaddr (DECL_RTL (exp)); ! 9659: #endif ! 9660: ! 9661: if (DECL_EXTERNAL (exp)) ! 9662: bc_load_externaddr_id (DECL_ASSEMBLER_NAME (exp), ! 9663: (BYTECODE_BC_LABEL (DECL_RTL (exp)))->offset); ! 9664: else ! 9665: bc_load_localaddr (DECL_RTL (exp)); ! 9666: ! 9667: /* For variable-sized types: retrieve pointer */ ! 9668: if (TYPE_SIZE (TREE_TYPE (exp)) ! 9669: && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST) ! 9670: bc_emit_instruction (loadP); ! 9671: ! 9672: /* If packed, also return offset and size */ ! 9673: if (DECL_BIT_FIELD (exp)) ! 9674: bc_push_offset_and_size (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (exp)), ! 9675: TREE_INT_CST_LOW (DECL_SIZE (exp))); ! 9676: ! 9677: break; ! 9678: ! 9679: case STRING_CST: ! 9680: { ! 9681: rtx r; ! 9682: ! 9683: bc_emit_bytecode (constP); ! 9684: r = output_constant_def (exp); ! 9685: bc_emit_code_labelref (BYTECODE_LABEL (r), BYTECODE_BC_LABEL (r)->offset); ! 9686: ! 9687: #ifdef DEBUG_PRINT_CODE ! 9688: fputc ('\n', stderr); ! 9689: #endif ! 9690: } ! 9691: break; ! 9692: ! 9693: default: ! 9694: ! 9695: abort(); ! 9696: break; ! 9697: } ! 9698: ! 9699: /* Most lvalues don't have components. */ ! 9700: return (exp); ! 9701: } ! 9702: ! 9703: ! 9704: /* Emit a type code to be used by the runtime support in handling ! 9705: parameter passing. The type code consists of the machine mode ! 9706: plus the minimal alignment shifted left 8 bits. */ ! 9707: ! 9708: tree ! 9709: bc_runtime_type_code (type) ! 9710: tree type; ! 9711: { ! 9712: int val; ! 9713: ! 9714: switch (TREE_CODE (type)) ! 9715: { ! 9716: case VOID_TYPE: ! 9717: case INTEGER_TYPE: ! 9718: case REAL_TYPE: ! 9719: case COMPLEX_TYPE: ! 9720: case ENUMERAL_TYPE: ! 9721: case POINTER_TYPE: ! 9722: case RECORD_TYPE: ! 9723: ! 9724: val = (int) TYPE_MODE (type) | TYPE_ALIGN (type) << 8; ! 9725: break; ! 9726: ! 9727: case ERROR_MARK: ! 9728: ! 9729: val = 0; ! 9730: break; ! 9731: ! 9732: default: ! 9733: ! 9734: abort (); ! 9735: } ! 9736: return build_int_2 (val, 0); ! 9737: } ! 9738: ! 9739: ! 9740: /* Generate constructor label */ ! 9741: char * ! 9742: bc_gen_constr_label () ! 9743: { ! 9744: static int label_counter; ! 9745: static char label[20]; ! 9746: ! 9747: sprintf (label, "*LR%d", label_counter++); ! 9748: ! 9749: return (obstack_copy0 (&permanent_obstack, label, strlen (label))); ! 9750: } ! 9751: ! 9752: ! 9753: /* Evaluate constructor CONSTR and return pointer to it on level one. We ! 9754: expand the constructor data as static data, and push a pointer to it. ! 9755: The pointer is put in the pointer table and is retrieved by a constP ! 9756: bytecode instruction. We then loop and store each constructor member in ! 9757: the corresponding component. Finally, we return the original pointer on ! 9758: the stack. */ ! 9759: ! 9760: void ! 9761: bc_expand_constructor (constr) ! 9762: tree constr; ! 9763: { ! 9764: char *l; ! 9765: HOST_WIDE_INT ptroffs; ! 9766: rtx constr_rtx; ! 9767: ! 9768: ! 9769: /* Literal constructors are handled as constants, whereas ! 9770: non-literals are evaluated and stored element by element ! 9771: into the data segment. */ ! 9772: ! 9773: /* Allocate space in proper segment and push pointer to space on stack. ! 9774: */ ! 9775: ! 9776: l = bc_gen_constr_label (); ! 9777: ! 9778: if (TREE_CONSTANT (constr)) ! 9779: { ! 9780: text_section (); ! 9781: ! 9782: bc_emit_const_labeldef (l); ! 9783: bc_output_constructor (constr, int_size_in_bytes (TREE_TYPE (constr))); ! 9784: } ! 9785: else ! 9786: { ! 9787: data_section (); ! 9788: ! 9789: bc_emit_data_labeldef (l); ! 9790: bc_output_data_constructor (constr); ! 9791: } ! 9792: ! 9793: ! 9794: /* Add reference to pointer table and recall pointer to stack; ! 9795: this code is common for both types of constructors: literals ! 9796: and non-literals. */ ! 9797: ! 9798: ptroffs = bc_define_pointer (l); ! 9799: bc_emit_instruction (constP, ptroffs); ! 9800: ! 9801: /* This is all that has to be done if it's a literal. */ ! 9802: if (TREE_CONSTANT (constr)) ! 9803: return; ! 9804: ! 9805: ! 9806: /* At this point, we have the pointer to the structure on top of the stack. ! 9807: Generate sequences of store_memory calls for the constructor. */ ! 9808: ! 9809: /* constructor type is structure */ ! 9810: if (TREE_CODE (TREE_TYPE (constr)) == RECORD_TYPE) ! 9811: { ! 9812: register tree elt; ! 9813: ! 9814: /* If the constructor has fewer fields than the structure, ! 9815: clear the whole structure first. */ ! 9816: ! 9817: if (list_length (CONSTRUCTOR_ELTS (constr)) ! 9818: != list_length (TYPE_FIELDS (TREE_TYPE (constr)))) ! 9819: { ! 9820: bc_emit_instruction (duplicate); ! 9821: bc_emit_instruction (constSI, (HOST_WIDE_INT) int_size_in_bytes (TREE_TYPE (constr))); ! 9822: bc_emit_instruction (clearBLK); ! 9823: } ! 9824: ! 9825: /* Store each element of the constructor into the corresponding ! 9826: field of TARGET. */ ! 9827: ! 9828: for (elt = CONSTRUCTOR_ELTS (constr); elt; elt = TREE_CHAIN (elt)) ! 9829: { ! 9830: register tree field = TREE_PURPOSE (elt); ! 9831: register enum machine_mode mode; ! 9832: int bitsize; ! 9833: int bitpos; ! 9834: int unsignedp; ! 9835: ! 9836: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) /* * DECL_SIZE_UNIT (field) */; ! 9837: mode = DECL_MODE (field); ! 9838: unsignedp = TREE_UNSIGNED (field); ! 9839: ! 9840: bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); ! 9841: ! 9842: bc_store_field (elt, bitsize, bitpos, mode, TREE_VALUE (elt), TREE_TYPE (TREE_VALUE (elt)), ! 9843: /* The alignment of TARGET is ! 9844: at least what its type requires. */ ! 9845: VOIDmode, 0, ! 9846: TYPE_ALIGN (TREE_TYPE (constr)) / BITS_PER_UNIT, ! 9847: int_size_in_bytes (TREE_TYPE (constr))); ! 9848: } ! 9849: } ! 9850: else ! 9851: ! 9852: /* Constructor type is array */ ! 9853: if (TREE_CODE (TREE_TYPE (constr)) == ARRAY_TYPE) ! 9854: { ! 9855: register tree elt; ! 9856: register int i; ! 9857: tree domain = TYPE_DOMAIN (TREE_TYPE (constr)); ! 9858: int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! 9859: int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); ! 9860: tree elttype = TREE_TYPE (TREE_TYPE (constr)); ! 9861: ! 9862: /* If the constructor has fewer fields than the structure, ! 9863: clear the whole structure first. */ ! 9864: ! 9865: if (list_length (CONSTRUCTOR_ELTS (constr)) < maxelt - minelt + 1) ! 9866: { ! 9867: bc_emit_instruction (duplicate); ! 9868: bc_emit_instruction (constSI, (HOST_WIDE_INT) int_size_in_bytes (TREE_TYPE (constr))); ! 9869: bc_emit_instruction (clearBLK); ! 9870: } ! 9871: ! 9872: ! 9873: /* Store each element of the constructor into the corresponding ! 9874: element of TARGET, determined by counting the elements. */ ! 9875: ! 9876: for (elt = CONSTRUCTOR_ELTS (constr), i = 0; ! 9877: elt; ! 9878: elt = TREE_CHAIN (elt), i++) ! 9879: { ! 9880: register enum machine_mode mode; ! 9881: int bitsize; ! 9882: int bitpos; ! 9883: int unsignedp; ! 9884: ! 9885: mode = TYPE_MODE (elttype); ! 9886: bitsize = GET_MODE_BITSIZE (mode); ! 9887: unsignedp = TREE_UNSIGNED (elttype); ! 9888: ! 9889: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)) ! 9890: /* * TYPE_SIZE_UNIT (elttype) */ ); ! 9891: ! 9892: bc_store_field (elt, bitsize, bitpos, mode, ! 9893: TREE_VALUE (elt), TREE_TYPE (TREE_VALUE (elt)), ! 9894: /* The alignment of TARGET is ! 9895: at least what its type requires. */ ! 9896: VOIDmode, 0, ! 9897: TYPE_ALIGN (TREE_TYPE (constr)) / BITS_PER_UNIT, ! 9898: int_size_in_bytes (TREE_TYPE (constr))); ! 9899: } ! 9900: ! 9901: } ! 9902: } ! 9903: ! 9904: ! 9905: /* Store the value of EXP (an expression tree) into member FIELD of ! 9906: structure at address on stack, which has type TYPE, mode MODE and ! 9907: occupies BITSIZE bits, starting BITPOS bits from the beginning of the ! 9908: structure. ! 9909: ! 9910: ALIGN is the alignment that TARGET is known to have, measured in bytes. ! 9911: TOTAL_SIZE is its size in bytes, or -1 if variable. */ ! 9912: ! 9913: void ! 9914: bc_store_field (field, bitsize, bitpos, mode, exp, type, ! 9915: value_mode, unsignedp, align, total_size) ! 9916: int bitsize, bitpos; ! 9917: enum machine_mode mode; ! 9918: tree field, exp, type; ! 9919: enum machine_mode value_mode; ! 9920: int unsignedp; ! 9921: int align; ! 9922: int total_size; ! 9923: { ! 9924: ! 9925: /* Expand expression and copy pointer */ ! 9926: bc_expand_expr (exp); ! 9927: bc_emit_instruction (over); ! 9928: ! 9929: ! 9930: /* If the component is a bit field, we cannot use addressing to access ! 9931: it. Use bit-field techniques to store in it. */ ! 9932: ! 9933: if (DECL_BIT_FIELD (field)) ! 9934: { ! 9935: bc_store_bit_field (bitpos, bitsize, unsignedp); ! 9936: return; ! 9937: } ! 9938: else ! 9939: /* Not bit field */ ! 9940: { ! 9941: HOST_WIDE_INT offset = bitpos / BITS_PER_UNIT; ! 9942: ! 9943: /* Advance pointer to the desired member */ ! 9944: if (offset) ! 9945: bc_emit_instruction (addconstPSI, offset); ! 9946: ! 9947: /* Store */ ! 9948: bc_store_memory (type, field); ! 9949: } ! 9950: } ! 9951: ! 9952: ! 9953: /* Store SI/SU in bitfield */ ! 9954: void ! 9955: bc_store_bit_field (offset, size, unsignedp) ! 9956: int offset, size, unsignedp; ! 9957: { ! 9958: /* Push bitfield offset and size */ ! 9959: bc_push_offset_and_size (offset, size); ! 9960: ! 9961: /* Store */ ! 9962: bc_emit_instruction (sstoreBI); ! 9963: } ! 9964: ! 9965: ! 9966: /* Load SI/SU from bitfield */ ! 9967: void ! 9968: bc_load_bit_field (offset, size, unsignedp) ! 9969: int offset, size, unsignedp; ! 9970: { ! 9971: /* Push bitfield offset and size */ ! 9972: bc_push_offset_and_size (offset, size); ! 9973: ! 9974: /* Load: sign-extend if signed, else zero-extend */ ! 9975: bc_emit_instruction (unsignedp ? zxloadBI : sxloadBI); ! 9976: } ! 9977: ! 9978: ! 9979: /* Adjust interpreter stack by NLEVELS. Positive means drop NLEVELS ! 9980: (adjust stack pointer upwards), negative means add that number of ! 9981: levels (adjust the stack pointer downwards). Only positive values ! 9982: normally make sense. */ ! 9983: ! 9984: void ! 9985: bc_adjust_stack (nlevels) ! 9986: int nlevels; ! 9987: { ! 9988: switch (nlevels) ! 9989: { ! 9990: case 0: ! 9991: break; ! 9992: ! 9993: case 2: ! 9994: bc_emit_instruction (drop); ! 9995: ! 9996: case 1: ! 9997: bc_emit_instruction (drop); ! 9998: break; ! 9999: ! 10000: default: ! 10001: ! 10002: bc_emit_instruction (adjstackSI, (HOST_WIDE_INT) nlevels); ! 10003: stack_depth -= nlevels; ! 10004: } ! 10005: ! 10006: #if defined (VALIDATE_STACK_FOR_BC) ! 10007: VALIDATE_STACK_FOR_BC (); ! 10008: #endif ! 10009: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.