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