diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 287 |
1 files changed, 207 insertions, 80 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index e5f7ae51783..8df851869f8 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1,6 +1,6 @@ /* Convert tree expression to rtl instructions, for GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -1397,6 +1397,8 @@ convert_modes (mode, oldmode, x, unsignedp) && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x) && direct_load[(int) mode]) || (GET_CODE (x) == REG + && (! HARD_REGISTER_P (x) + || HARD_REGNO_MODE_OK (REGNO (x), mode)) && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), GET_MODE_BITSIZE (GET_MODE (x))))))))) { @@ -2436,7 +2438,7 @@ emit_group_store (orig_dst, src, ssize) { dst = gen_reg_rtx (GET_MODE (orig_dst)); /* Make life a bit easier for combine. */ - emit_move_insn (dst, const0_rtx); + emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst))); } /* Process the pieces. */ @@ -2468,6 +2470,15 @@ emit_group_store (orig_dst, src, ssize) bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))); dest = XEXP (dst, 1); } + else if (bytepos == 0 && XVECLEN (src, 0)) + { + dest = assign_stack_temp (GET_MODE (dest), + GET_MODE_SIZE (GET_MODE (dest)), 0); + emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos), + tmps[i]); + dst = dest; + break; + } else abort (); } @@ -2486,7 +2497,7 @@ emit_group_store (orig_dst, src, ssize) emit_queue (); /* Copy from the pseudo into the (probable) hard reg. */ - if (GET_CODE (dst) == REG) + if (orig_dst != dst) emit_move_insn (orig_dst, dst); } @@ -4020,7 +4031,8 @@ expand_assignment (to, from, want_value, suggest_reg) problem. */ if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF - || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF) + || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF + || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE) { enum machine_mode mode1; HOST_WIDE_INT bitsize, bitpos; @@ -4248,7 +4260,7 @@ expand_assignment (to, from, want_value, suggest_reg) and storing the value into TARGET. TARGET may contain a QUEUED rtx. - If WANT_VALUE is nonzero, return a copy of the value + If WANT_VALUE & 1 is nonzero, return a copy of the value not in TARGET, so that we can be sure to use the proper value in a containing expression even if TARGET has something else stored in it. If possible, we copy the value through a pseudo @@ -4263,9 +4275,12 @@ expand_assignment (to, from, want_value, suggest_reg) with no sequence point. Will other languages need this to be more thorough? - If WANT_VALUE is 0, we return NULL, to make sure + If WANT_VALUE & 1 is 0, we return NULL, to make sure to catch quickly any cases where the caller uses the value - and fails to set WANT_VALUE. */ + and fails to set WANT_VALUE. + + If WANT_VALUE & 2 is set, this is a store into a call param on the + stack, and block moves may need to be treated specially. */ rtx store_expr (exp, target, want_value) @@ -4277,11 +4292,22 @@ store_expr (exp, target, want_value) int dont_return_target = 0; int dont_store_target = 0; + if (VOID_TYPE_P (TREE_TYPE (exp))) + { + /* C++ can generate ?: expressions with a throw expression in one + branch and an rvalue in the other. Here, we resolve attempts to + store the throw expression's nonexistant result. */ + if (want_value) + abort (); + expand_expr (exp, const0_rtx, VOIDmode, 0); + return NULL_RTX; + } if (TREE_CODE (exp) == COMPOUND_EXPR) { /* Perform first part of compound expression, then assign from second part. */ - expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); + expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, + want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL); emit_queue (); return store_expr (TREE_OPERAND (exp, 1), target, want_value); } @@ -4301,20 +4327,20 @@ store_expr (exp, target, want_value) NO_DEFER_POP; jumpifnot (TREE_OPERAND (exp, 0), lab1); start_cleanup_deferral (); - store_expr (TREE_OPERAND (exp, 1), target, 0); + store_expr (TREE_OPERAND (exp, 1), target, want_value & 2); end_cleanup_deferral (); emit_queue (); emit_jump_insn (gen_jump (lab2)); emit_barrier (); emit_label (lab1); start_cleanup_deferral (); - store_expr (TREE_OPERAND (exp, 2), target, 0); + store_expr (TREE_OPERAND (exp, 2), target, want_value & 2); end_cleanup_deferral (); emit_queue (); emit_label (lab2); OK_DEFER_POP; - return want_value ? target : NULL_RTX; + return want_value & 1 ? target : NULL_RTX; } else if (queued_subexp_p (target)) /* If target contains a postincrement, let's not risk @@ -4324,18 +4350,24 @@ store_expr (exp, target, want_value) { /* Expand EXP into a new pseudo. */ temp = gen_reg_rtx (GET_MODE (target)); - temp = expand_expr (exp, temp, GET_MODE (target), 0); + temp = expand_expr (exp, temp, GET_MODE (target), + (want_value & 2 + ? EXPAND_STACK_PARM : EXPAND_NORMAL)); } else - temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0); + temp = expand_expr (exp, NULL_RTX, GET_MODE (target), + (want_value & 2 + ? EXPAND_STACK_PARM : EXPAND_NORMAL)); /* If target is volatile, ANSI requires accessing the value *from* the target, if it is accessed. So make that happen. In no case return the target itself. */ - if (! MEM_VOLATILE_P (target) && want_value) + if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0) dont_return_target = 1; } - else if (want_value && GET_CODE (target) == MEM && ! MEM_VOLATILE_P (target) + else if ((want_value & 1) != 0 + && GET_CODE (target) == MEM + && ! MEM_VOLATILE_P (target) && GET_MODE (target) != BLKmode) /* If target is in memory and caller wants value in a register instead, arrange that. Pass TARGET as target for expand_expr so that, @@ -4344,7 +4376,8 @@ store_expr (exp, target, want_value) Don't do this if TARGET is volatile because we are supposed to write it and then read it. */ { - temp = expand_expr (exp, target, GET_MODE (target), 0); + temp = expand_expr (exp, target, GET_MODE (target), + want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL); if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) { /* If TEMP is already in the desired TARGET, only copy it from @@ -4371,7 +4404,8 @@ store_expr (exp, target, want_value) the extend. But don't do this if the type of EXP is a subtype of something else since then the conversion might involve more than just converting modes. */ - if (! want_value && INTEGRAL_TYPE_P (TREE_TYPE (exp)) + if ((want_value & 1) == 0 + && INTEGRAL_TYPE_P (TREE_TYPE (exp)) && TREE_TYPE (TREE_TYPE (exp)) == 0) { if (TREE_UNSIGNED (TREE_TYPE (exp)) @@ -4388,12 +4422,13 @@ store_expr (exp, target, want_value) inner_target = SUBREG_REG (target); } - temp = expand_expr (exp, inner_target, VOIDmode, 0); + temp = expand_expr (exp, inner_target, VOIDmode, + want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL); /* If TEMP is a volatile MEM and we want a result value, make the access now so it gets done only once. Likewise if it contains TARGET. */ - if (GET_CODE (temp) == MEM && want_value + if (GET_CODE (temp) == MEM && (want_value & 1) != 0 && (MEM_VOLATILE_P (temp) || reg_mentioned_p (SUBREG_REG (target), XEXP (temp, 0)))) temp = copy_to_reg (temp); @@ -4416,7 +4451,7 @@ store_expr (exp, target, want_value) target. Otherwise, the caller might get confused by a result whose mode is larger than expected. */ - if (want_value && GET_MODE (temp) != GET_MODE (target)) + if ((want_value & 1) != 0 && GET_MODE (temp) != GET_MODE (target)) { if (GET_MODE (temp) != VOIDmode) { @@ -4431,11 +4466,12 @@ store_expr (exp, target, want_value) temp, SUBREG_PROMOTED_UNSIGNED_P (target)); } - return want_value ? temp : NULL_RTX; + return want_value & 1 ? temp : NULL_RTX; } else { - temp = expand_expr (exp, target, GET_MODE (target), 0); + temp = expand_expr (exp, target, GET_MODE (target), + want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL); /* Return TARGET if it's a specified hardware register. If TARGET is a volatile mem ref, either return TARGET or return a reg copied *from* TARGET; ANSI requires this. @@ -4447,7 +4483,7 @@ store_expr (exp, target, want_value) && REGNO (target) < FIRST_PSEUDO_REGISTER) && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) && ! rtx_equal_p (temp, target) - && (CONSTANT_P (temp) || want_value)) + && (CONSTANT_P (temp) || (want_value & 1) != 0)) dont_return_target = 1; } @@ -4518,7 +4554,9 @@ store_expr (exp, target, want_value) if (GET_CODE (size) == CONST_INT && INTVAL (size) < TREE_STRING_LENGTH (exp)) - emit_block_move (target, temp, size, BLOCK_OP_NORMAL); + emit_block_move (target, temp, size, + (want_value & 2 + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); else { /* Compute the size of the data to copy from the string. */ @@ -4526,13 +4564,17 @@ store_expr (exp, target, want_value) = size_binop (MIN_EXPR, make_tree (sizetype, size), size_int (TREE_STRING_LENGTH (exp))); - rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX, - VOIDmode, 0); + rtx copy_size_rtx + = expand_expr (copy_size, NULL_RTX, VOIDmode, + (want_value & 2 + ? EXPAND_STACK_PARM : EXPAND_NORMAL)); rtx label = 0; /* Copy that much. */ copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, 0); - emit_block_move (target, temp, copy_size_rtx, BLOCK_OP_NORMAL); + emit_block_move (target, temp, copy_size_rtx, + (want_value & 2 + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); /* Figure out how much is left in TARGET that we have to clear. Do all calculations in ptr_mode. */ @@ -4573,13 +4615,15 @@ store_expr (exp, target, want_value) else if (GET_CODE (target) == PARALLEL) emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp))); else if (GET_MODE (temp) == BLKmode) - emit_block_move (target, temp, expr_size (exp), BLOCK_OP_NORMAL); + emit_block_move (target, temp, expr_size (exp), + (want_value & 2 + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); else emit_move_insn (target, temp); } /* If we don't want a value, return NULL_RTX. */ - if (! want_value) + if ((want_value & 1) == 0) return NULL_RTX; /* If we are supposed to return TEMP, do so as long as it isn't a MEM. @@ -4588,7 +4632,8 @@ store_expr (exp, target, want_value) return temp; /* Return TARGET itself if it is a hard register. */ - else if (want_value && GET_MODE (target) != BLKmode + else if ((want_value & 1) != 0 + && GET_MODE (target) != BLKmode && ! (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)) return copy_to_reg (target); @@ -6405,7 +6450,14 @@ find_placeholder (exp, plist) EXPAND_CONST_ADDRESS says that it is okay to return a MEM with a constant address even if that address is not normally legitimate. - EXPAND_INITIALIZER and EXPAND_SUM also have this effect. */ + EXPAND_INITIALIZER and EXPAND_SUM also have this effect. + + EXPAND_STACK_PARM is used when expanding to a TARGET on the stack for + a call parameter. Such targets require special care as we haven't yet + marked TARGET so that it's safe from being trashed by libcalls. We + don't want to use TARGET for anything but the final result; + Intermediate values must go elsewhere. Additionally, calls to + emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */ rtx expand_expr (exp, target, tmode, modifier) @@ -6548,7 +6600,7 @@ expand_expr (exp, target, tmode, modifier) if (! cse_not_expected && mode != BLKmode && target && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER) && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD)) - target = subtarget; + target = 0; switch (code) { @@ -6734,7 +6786,7 @@ expand_expr (exp, target, tmode, modifier) return temp; case CONST_DECL: - return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); + return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier); case REAL_CST: /* If optimized, generate immediate CONST_DOUBLE @@ -6810,7 +6862,7 @@ expand_expr (exp, target, tmode, modifier) temp = SAVE_EXPR_RTL (exp); if (temp && GET_CODE (temp) == REG) { - put_var_into_stack (exp); + put_var_into_stack (exp, /*rescan=*/true); temp = SAVE_EXPR_RTL (exp); } if (temp == 0 || GET_CODE (temp) != MEM) @@ -6837,12 +6889,12 @@ expand_expr (exp, target, tmode, modifier) /* If the mode of TEMP does not match that of the expression, it must be a promoted value. We pass store_expr a SUBREG of the wanted mode but mark it so that we know that it was already - extended. Note that `unsignedp' was modified above in - this case. */ + extended. */ if (GET_CODE (temp) == REG && GET_MODE (temp) != mode) { temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp)); + promote_mode (type, mode, &unsignedp, 0); SUBREG_PROMOTED_VAR_P (temp) = 1; SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); } @@ -6850,7 +6902,8 @@ expand_expr (exp, target, tmode, modifier) if (temp == const0_rtx) expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); else - store_expr (TREE_OPERAND (exp, 0), temp, 0); + store_expr (TREE_OPERAND (exp, 0), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); TREE_USED (exp) = 1; } @@ -7039,7 +7092,8 @@ expand_expr (exp, target, tmode, modifier) /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (target == 0 || ! safe_from_p (target, exp, 1) - || GET_CODE (target) == PARALLEL) + || GET_CODE (target) == PARALLEL + || modifier == EXPAND_STACK_PARM) target = assign_temp (build_qualified_type (type, (TYPE_QUALS (type) @@ -7213,6 +7267,9 @@ expand_expr (exp, target, tmode, modifier) && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt))) <= HOST_BITS_PER_WIDE_INT)))) { + if (DECL_BIT_FIELD (TREE_PURPOSE (elt)) + && modifier == EXPAND_STACK_PARM) + target = 0; op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier); if (DECL_BIT_FIELD (TREE_PURPOSE (elt))) { @@ -7267,10 +7324,12 @@ expand_expr (exp, target, tmode, modifier) (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) != INTEGER_CST) + && modifier != EXPAND_STACK_PARM ? target : NULL_RTX), VOIDmode, (modifier == EXPAND_INITIALIZER - || modifier == EXPAND_CONST_ADDRESS) + || modifier == EXPAND_CONST_ADDRESS + || modifier == EXPAND_STACK_PARM) ? modifier : EXPAND_NORMAL); /* If this is a constant, put it into a register if it is a @@ -7287,7 +7346,8 @@ expand_expr (exp, target, tmode, modifier) if (offset != 0) { - rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); + rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, + EXPAND_SUM); /* If this object is in a register, put it into memory. This case can't occur in C, but can in Ada if we have @@ -7300,7 +7360,8 @@ expand_expr (exp, target, tmode, modifier) forcing the SAVE_EXPR into memory. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR) { - put_var_into_stack (TREE_OPERAND (exp, 0)); + put_var_into_stack (TREE_OPERAND (exp, 0), + /*rescan=*/true); op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0)); } else @@ -7423,7 +7484,8 @@ expand_expr (exp, target, tmode, modifier) emit_block_move (target, op0, GEN_INT ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT), - BLOCK_OP_NORMAL); + (modifier == EXPAND_STACK_PARM + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); return target; } @@ -7433,8 +7495,10 @@ expand_expr (exp, target, tmode, modifier) if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG) mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); - op0 = extract_bit_field (op0, bitsize, bitpos, - unsignedp, target, ext_mode, ext_mode, + op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, + (modifier == EXPAND_STACK_PARM + ? NULL_RTX : target), + ext_mode, ext_mode, int_size_in_bytes (TREE_TYPE (tem))); /* If the result is a record type and BITSIZE is narrower than @@ -7678,8 +7742,8 @@ expand_expr (exp, target, tmode, modifier) { if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == BUILT_IN_FRONTEND) - return (*lang_hooks.expand_expr) - (exp, original_target, tmode, modifier); + return (*lang_hooks.expand_expr) (exp, original_target, + tmode, modifier); else return expand_builtin (exp, target, subtarget, tmode, ignore); } @@ -7715,7 +7779,8 @@ expand_expr (exp, target, tmode, modifier) if (GET_CODE (target) == MEM) /* Store data into beginning of memory target. */ store_expr (TREE_OPERAND (exp, 0), - adjust_address (target, TYPE_MODE (valtype), 0), 0); + adjust_address (target, TYPE_MODE (valtype), 0), + modifier == EXPAND_STACK_PARM ? 2 : 0); else if (GET_CODE (target) == REG) /* Store this field into a union of the proper type. */ @@ -7840,7 +7905,8 @@ expand_expr (exp, target, tmode, modifier) if (GET_MODE (op0) == BLKmode) emit_block_move (new_with_op0_mode, op0, GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))), - BLOCK_OP_NORMAL); + (modifier == EXPAND_STACK_PARM + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); else emit_move_insn (new_with_op0_mode, op0); @@ -7892,6 +7958,8 @@ expand_expr (exp, target, tmode, modifier) if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER || (mode == ptr_mode && (unsignedp || ! flag_trapv))) { + if (modifier == EXPAND_STACK_PARM) + target = 0; if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && TREE_CONSTANT (TREE_OPERAND (exp, 1))) @@ -8086,6 +8154,8 @@ expand_expr (exp, target, tmode, modifier) if (modifier == EXPAND_SUM && mode == ptr_mode && host_integerp (TREE_OPERAND (exp, 1), 0)) { + tree exp1 = TREE_OPERAND (exp, 1); + op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); @@ -8104,14 +8174,17 @@ expand_expr (exp, target, tmode, modifier) if (GET_CODE (op0) != REG) op0 = copy_to_mode_reg (mode, op0); - return - gen_rtx_MULT (mode, op0, - GEN_INT (tree_low_cst (TREE_OPERAND (exp, 1), 0))); + return gen_rtx_MULT (mode, op0, + gen_int_mode (tree_low_cst (exp1, 0), + TYPE_MODE (TREE_TYPE (exp1)))); } if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) subtarget = 0; + if (modifier == EXPAND_STACK_PARM) + target = 0; + /* Check for multiplying things that have been extended from a narrower type. If this machine supports multiplying in that narrower type with a result in the desired type, @@ -8195,6 +8268,8 @@ expand_expr (exp, target, tmode, modifier) case EXACT_DIV_EXPR: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) subtarget = 0; + if (modifier == EXPAND_STACK_PARM) + target = 0; /* Possible optimization: compute the dividend with EXPAND_SUM then if the divisor is constant can optimize the case where some terms of the dividend have coeffs divisible by it. */ @@ -8213,7 +8288,7 @@ expand_expr (exp, target, tmode, modifier) build (RDIV_EXPR, type, build_real (type, dconst1), TREE_OPERAND (exp, 1))), - target, tmode, unsignedp); + target, tmode, modifier); this_optab = sdiv_optab; goto binop; @@ -8223,6 +8298,8 @@ expand_expr (exp, target, tmode, modifier) case ROUND_MOD_EXPR: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) subtarget = 0; + if (modifier == EXPAND_STACK_PARM) + target = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); return expand_divmod (1, code, mode, op0, op1, target, unsignedp); @@ -8234,14 +8311,14 @@ expand_expr (exp, target, tmode, modifier) case FIX_TRUNC_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); - if (target == 0) + if (target == 0 || modifier == EXPAND_STACK_PARM) target = gen_reg_rtx (mode); expand_fix (target, op0, unsignedp); return target; case FLOAT_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); - if (target == 0) + if (target == 0 || modifier == EXPAND_STACK_PARM) target = gen_reg_rtx (mode); /* expand_float can't figure out what to do if FROM has VOIDmode. So give it the correct mode. With -O, cse will optimize this. */ @@ -8254,6 +8331,8 @@ expand_expr (exp, target, tmode, modifier) case NEGATE_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + if (modifier == EXPAND_STACK_PARM) + target = 0; temp = expand_unop (mode, ! unsignedp && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT) @@ -8264,6 +8343,8 @@ expand_expr (exp, target, tmode, modifier) case ABS_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + if (modifier == EXPAND_STACK_PARM) + target = 0; /* Handle complex values specially. */ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT @@ -8281,7 +8362,9 @@ expand_expr (exp, target, tmode, modifier) case MAX_EXPR: case MIN_EXPR: target = original_target; - if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1) + if (target == 0 + || modifier == EXPAND_STACK_PARM + || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1) || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)) || GET_MODE (target) != mode || (GET_CODE (target) == REG @@ -8338,6 +8421,8 @@ expand_expr (exp, target, tmode, modifier) case BIT_NOT_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + if (modifier == EXPAND_STACK_PARM) + target = 0; temp = expand_unop (mode, one_cmpl_optab, op0, target, 1); if (temp == 0) abort (); @@ -8345,6 +8430,8 @@ expand_expr (exp, target, tmode, modifier) case FFS_EXPR: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + if (modifier == EXPAND_STACK_PARM) + target = 0; temp = expand_unop (mode, ffs_optab, op0, target, 1); if (temp == 0) abort (); @@ -8384,6 +8471,8 @@ expand_expr (exp, target, tmode, modifier) case RROTATE_EXPR: if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1)) subtarget = 0; + if (modifier == EXPAND_STACK_PARM) + target = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, unsignedp); @@ -8403,7 +8492,9 @@ expand_expr (exp, target, tmode, modifier) case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: - temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0); + temp = do_store_flag (exp, + modifier != EXPAND_STACK_PARM ? target : NULL_RTX, + tmode != VOIDmode ? tmode : mode, 0); if (temp != 0) return temp; @@ -8452,7 +8543,9 @@ expand_expr (exp, target, tmode, modifier) case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: if (! ignore - && (target == 0 || ! safe_from_p (target, exp, 1) + && (target == 0 + || modifier == EXPAND_STACK_PARM + || ! safe_from_p (target, exp, 1) /* Make sure we don't have a hard reg (such as function's return value) live across basic blocks, if not optimizing. */ || (!optimize && GET_CODE (target) == REG @@ -8472,6 +8565,8 @@ expand_expr (exp, target, tmode, modifier) return ignore ? const0_rtx : target; case TRUTH_NOT_EXPR: + if (modifier == EXPAND_STACK_PARM) + target = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); /* The parser is careful to generate TRUTH_NOT_EXPR only with operands that are always zero or one. */ @@ -8486,7 +8581,7 @@ expand_expr (exp, target, tmode, modifier) emit_queue (); return expand_expr (TREE_OPERAND (exp, 1), (ignore ? const0_rtx : target), - VOIDmode, 0); + VOIDmode, modifier); case COND_EXPR: /* If we would have a "singleton" (see below) were it not for a @@ -8539,6 +8634,8 @@ expand_expr (exp, target, tmode, modifier) return const0_rtx; } + if (modifier == EXPAND_STACK_PARM) + target = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier); if (GET_MODE (op0) == mode) return op0; @@ -8579,6 +8676,8 @@ expand_expr (exp, target, tmode, modifier) if (ignore) temp = 0; + else if (modifier == EXPAND_STACK_PARM) + temp = assign_temp (type, 0, 0, 1); else if (original_target && (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1) || (singleton && GET_CODE (original_target) == REG @@ -8666,7 +8765,8 @@ expand_expr (exp, target, tmode, modifier) || (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)) temp = gen_reg_rtx (mode); - store_expr (singleton, temp, 0); + store_expr (singleton, temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); } else expand_expr (singleton, @@ -8685,11 +8785,11 @@ expand_expr (exp, target, tmode, modifier) store_expr (build (TREE_CODE (binary_op), type, make_tree (type, temp), TREE_OPERAND (binary_op, 1)), - temp, 0); + temp, modifier == EXPAND_STACK_PARM ? 2 : 0); else store_expr (build1 (TREE_CODE (unary_op), type, make_tree (type, temp)), - temp, 0); + temp, modifier == EXPAND_STACK_PARM ? 2 : 0); op1 = op0; } /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any @@ -8708,11 +8808,13 @@ expand_expr (exp, target, tmode, modifier) if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) temp = gen_reg_rtx (mode); - store_expr (TREE_OPERAND (exp, 1), temp, 0); + store_expr (TREE_OPERAND (exp, 1), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); jumpif (TREE_OPERAND (exp, 0), op0); start_cleanup_deferral (); - store_expr (TREE_OPERAND (exp, 2), temp, 0); + store_expr (TREE_OPERAND (exp, 2), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); op1 = op0; } else if (temp @@ -8727,11 +8829,13 @@ expand_expr (exp, target, tmode, modifier) if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER) temp = gen_reg_rtx (mode); - store_expr (TREE_OPERAND (exp, 2), temp, 0); + store_expr (TREE_OPERAND (exp, 2), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); jumpifnot (TREE_OPERAND (exp, 0), op0); start_cleanup_deferral (); - store_expr (TREE_OPERAND (exp, 1), temp, 0); + store_expr (TREE_OPERAND (exp, 1), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); op1 = op0; } else @@ -8745,7 +8849,8 @@ expand_expr (exp, target, tmode, modifier) example A ? throw : E */ if (temp != 0 && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node) - store_expr (TREE_OPERAND (exp, 1), temp, 0); + store_expr (TREE_OPERAND (exp, 1), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); else expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); @@ -8757,7 +8862,8 @@ expand_expr (exp, target, tmode, modifier) start_cleanup_deferral (); if (temp != 0 && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node) - store_expr (TREE_OPERAND (exp, 2), temp, 0); + store_expr (TREE_OPERAND (exp, 2), temp, + modifier == EXPAND_STACK_PARM ? 2 : 0); else expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); @@ -8815,7 +8921,7 @@ expand_expr (exp, target, tmode, modifier) preserve_temp_slots (target); SET_DECL_RTL (slot, target); if (TREE_ADDRESSABLE (slot)) - put_var_into_stack (slot); + put_var_into_stack (slot, /*rescan=*/false); /* Since SLOT is not known to the called function to belong to its stack frame, we must build an explicit @@ -8854,7 +8960,7 @@ expand_expr (exp, target, tmode, modifier) /* If we must have an addressable slot, then make sure that the RTL that we just stored in slot is OK. */ if (TREE_ADDRESSABLE (slot)) - put_var_into_stack (slot); + put_var_into_stack (slot, /*rescan=*/true); } } @@ -8862,7 +8968,7 @@ expand_expr (exp, target, tmode, modifier) /* Mark it as expanded. */ TREE_OPERAND (exp, 1) = NULL_TREE; - store_expr (exp1, target, 0); + store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0); expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp)); @@ -8947,6 +9053,8 @@ expand_expr (exp, target, tmode, modifier) return expand_increment (exp, ! ignore, ignore); case ADDR_EXPR: + if (modifier == EXPAND_STACK_PARM) + target = 0; /* Are we taking the address of a nested function? */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL && decl_function_context (TREE_OPERAND (exp, 0)) != 0 @@ -9002,7 +9110,8 @@ expand_expr (exp, target, tmode, modifier) forcing the SAVE_EXPR into memory. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR) { - put_var_into_stack (TREE_OPERAND (exp, 0)); + put_var_into_stack (TREE_OPERAND (exp, 0), + /*rescan=*/true); op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0)); } else @@ -9055,20 +9164,30 @@ expand_expr (exp, target, tmode, modifier) && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT) { tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0)); - rtx new - = assign_stack_temp_for_type - (TYPE_MODE (inner_type), - MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0)) - : int_size_in_bytes (inner_type), - 1, build_qualified_type (inner_type, - (TYPE_QUALS (inner_type) - | TYPE_QUAL_CONST))); + rtx new; if (TYPE_ALIGN_OK (inner_type)) abort (); + if (TREE_ADDRESSABLE (inner_type)) + { + /* We can't make a bitwise copy of this object, so fail. */ + error ("cannot take the address of an unaligned member"); + return const0_rtx; + } + + new = assign_stack_temp_for_type + (TYPE_MODE (inner_type), + MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0)) + : int_size_in_bytes (inner_type), + 1, build_qualified_type (inner_type, + (TYPE_QUALS (inner_type) + | TYPE_QUAL_CONST))); + emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)), - BLOCK_OP_NORMAL); + (modifier == EXPAND_STACK_PARM + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); + op0 = new; } @@ -9284,6 +9403,8 @@ expand_expr (exp, target, tmode, modifier) op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); binop2: + if (modifier == EXPAND_STACK_PARM) + target = 0; temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); if (temp == 0) @@ -9710,6 +9831,12 @@ do_jump (exp, if_false_label, if_true_label) break; #endif + case UNSAVE_EXPR: + do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); + TREE_OPERAND (exp, 0) + = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0)); + break; + case NOP_EXPR: if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF |