diff options
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 33 |
1 files changed, 19 insertions, 14 deletions
@@ -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; } |