aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c287
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