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