aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 96cab626f7b..5db2c280038 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6088,7 +6088,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
case CONST_DECL:
/* Recurse and make the output_constant_def clause above handle this. */
return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
- tmode, modifier);
+ tmode, modifier);
case REALPART_EXPR:
/* The real part of the complex number is always first, therefore
@@ -6126,7 +6126,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
result = XEXP (result, 0);
/* ??? Is this needed anymore? */
- if (!TREE_USED (exp) == 0)
+ if (DECL_P (exp) && !TREE_USED (exp) == 0)
{
assemble_external (exp);
TREE_USED (exp) = 1;
@@ -6149,13 +6149,6 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
subtarget = offset || bitpos ? NULL_RTX : target;
result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier);
- if (tmode == VOIDmode)
- {
- tmode = GET_MODE (result);
- if (tmode == VOIDmode)
- tmode = Pmode;
- }
-
if (offset)
{
rtx tmp;
@@ -6164,6 +6157,9 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
result = force_operand (result, NULL);
tmp = expand_expr (offset, NULL, tmode, EXPAND_NORMAL);
+ result = convert_memory_address (tmode, result);
+ tmp = convert_memory_address (tmode, tmp);
+
if (modifier == EXPAND_SUM)
result = gen_rtx_PLUS (tmode, result, tmp);
else
@@ -6178,7 +6174,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
{
/* Someone beforehand should have rejected taking the address
of such an object. */
- gcc_assert (!(bitpos % BITS_PER_UNIT));
+ gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
result = plus_constant (result, bitpos / BITS_PER_UNIT);
if (modifier < EXPAND_SUM)
@@ -6198,19 +6194,28 @@ expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
enum machine_mode rmode;
rtx result;
+ /* Target mode of VOIDmode says "whatever's natural". */
+ if (tmode == VOIDmode)
+ tmode = TYPE_MODE (TREE_TYPE (exp));
+
+ /* We can get called with some Weird Things if the user does silliness
+ like "(short) &a". In that case, convert_memory_address won't do
+ the right thing, so ignore the given target mode. */
+ if (!targetm.valid_pointer_mode (tmode))
+ tmode = Pmode;
+
result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
tmode, modifier);
/* Despite expand_expr claims concerning ignoring TMODE when not
- strictly convenient, stuff breaks if we don't honor it. */
- if (tmode == VOIDmode)
- tmode = TYPE_MODE (TREE_TYPE (exp));
+ strictly convenient, stuff breaks if we don't honor it. Note
+ that combined with the above, we only do this for pointer modes. */
rmode = GET_MODE (result);
if (rmode == VOIDmode)
rmode = tmode;
if (rmode != tmode)
result = convert_memory_address (tmode, result);
-
+
return result;
}
@@ -8053,6 +8058,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
OK_DEFER_POP;
return temp;
+ case VEC_COND_EXPR:
+ target = expand_vec_cond_expr (exp, target);
+ return target;
+
case MODIFY_EXPR:
{
/* If lhs is complex, expand calls in rhs before computing it.