diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-13 19:14:33 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-13 19:14:33 +0000 |
commit | 0dd8cf9cc8350069e94a624959d1ad4487c46a8c (patch) | |
tree | 63472a8da3b4d5a6c33190c256b60a5710d30a18 /gcc/expr.c | |
parent | fe644b69d013e77c7fc2db2a9863969d4f564561 (diff) | |
parent | 69888cc76b4873822f5e48b66f69e9d20d19fc50 (diff) | |
download | gcc-0dd8cf9cc8350069e94a624959d1ad4487c46a8c.tar.gz |
Merge in trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@206584 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 152 |
1 files changed, 86 insertions, 66 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index 28d84b46bec..756edbe9236 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5294,7 +5294,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) temp = expand_expr_real (exp, tmp_target, GET_MODE (target), (call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL), - &alt_rtl); + &alt_rtl, false); } /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not @@ -7882,11 +7882,21 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier, address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on - recursively. */ + recursively. + + If INNER_REFERENCE_P is true, we are expanding an inner reference. + In this case, we don't adjust a returned MEM rtx that wouldn't be + sufficiently aligned for its mode; instead, it's up to the caller + to deal with it afterwards. This is used to make sure that unaligned + base objects for which out-of-bounds accesses are supported, for + example record types with trailing arrays, aren't realigned behind + the back of the caller. + The normal operating mode is to pass FALSE for this parameter. */ rtx expand_expr_real (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool inner_reference_p) { rtx ret; @@ -7898,7 +7908,8 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, return ret ? ret : const0_rtx; } - ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl, + inner_reference_p); return ret; } @@ -9209,7 +9220,8 @@ stmt_is_replaceable_p (gimple stmt) rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool inner_reference_p) { rtx op0, op1, temp, decl_rtl; tree type; @@ -9355,7 +9367,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, set_curr_insn_location (gimple_location (g)); r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, - tmode, modifier, NULL); + tmode, modifier, NULL, inner_reference_p); set_curr_insn_location (saved_loc); if (REG_P (r) && !REG_EXPR (r)) set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); @@ -9580,7 +9592,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case SAVE_EXPR: { tree val = treeop0; - rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl); + rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl, + inner_reference_p); if (!SAVE_EXPR_RESOLVED_P (exp)) { @@ -9717,6 +9730,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !inner_reference_p && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9942,15 +9956,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, computation, since it will need a temporary and TARGET is known to have to do. This occurs in unchecked conversion in Ada. */ orig_op0 = op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && COMPLETE_TYPE_P (TREE_TYPE (tem)) - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && COMPLETE_TYPE_P (TREE_TYPE (tem)) + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); /* If the field has a mode, we want to access it in the field's mode, not the computed mode. @@ -10307,14 +10322,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, { /* See the normal_inner_ref case for the rationale. */ orig_op0 - = expand_expr (tem, - (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_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (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_SUM ? EXPAND_NORMAL : modifier, + NULL, true); if (MEM_P (orig_op0)) { @@ -10341,7 +10357,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, } if (!op0) - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, + NULL, inner_reference_p); /* If the input and output modes are both the same, we are done. */ if (mode == GET_MODE (op0)) @@ -10408,50 +10425,53 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode - && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) - /* If the target does have special handling for unaligned - loads of mode then use them. */ - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) - { - rtx reg, insn; - - op0 = adjust_address (op0, mode, 0); - /* We've already validated the memory, and we're creating a - new pseudo destination. The predicates really can't - fail. */ - reg = gen_reg_rtx (mode); - - /* Nor can the insn generator. */ - insn = GEN_FCN (icode) (reg, op0); - emit_insn (insn); - return reg; - } - else if (STRICT_ALIGNMENT + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !inner_reference_p && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { - tree inner_type = TREE_TYPE (treeop0); - HOST_WIDE_INT temp_size - = MAX (int_size_in_bytes (inner_type), - (HOST_WIDE_INT) GET_MODE_SIZE (mode)); - rtx new_rtx - = assign_stack_temp_for_type (mode, temp_size, type); - rtx new_with_op0_mode - = adjust_address (new_rtx, GET_MODE (op0), 0); - - gcc_assert (!TREE_ADDRESSABLE (exp)); - - if (GET_MODE (op0) == BLKmode) - emit_block_move (new_with_op0_mode, op0, - GEN_INT (GET_MODE_SIZE (mode)), - (modifier == EXPAND_STACK_PARM - ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); - else - emit_move_insn (new_with_op0_mode, op0); + /* If the target does have special handling for unaligned + loads of mode then use them. */ + if ((icode = optab_handler (movmisalign_optab, mode)) + != CODE_FOR_nothing) + { + rtx reg, insn; + + op0 = adjust_address (op0, mode, 0); + /* We've already validated the memory, and we're creating a + new pseudo destination. The predicates really can't + fail. */ + reg = gen_reg_rtx (mode); + + /* Nor can the insn generator. */ + insn = GEN_FCN (icode) (reg, op0); + emit_insn (insn); + return reg; + } + else if (STRICT_ALIGNMENT) + { + tree inner_type = TREE_TYPE (treeop0); + HOST_WIDE_INT temp_size + = MAX (int_size_in_bytes (inner_type), + (HOST_WIDE_INT) GET_MODE_SIZE (mode)); + rtx new_rtx + = assign_stack_temp_for_type (mode, temp_size, type); + rtx new_with_op0_mode + = adjust_address (new_rtx, GET_MODE (op0), 0); + + gcc_assert (!TREE_ADDRESSABLE (exp)); + + if (GET_MODE (op0) == BLKmode) + emit_block_move (new_with_op0_mode, op0, + GEN_INT (GET_MODE_SIZE (mode)), + (modifier == EXPAND_STACK_PARM + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); + else + emit_move_insn (new_with_op0_mode, op0); - op0 = new_rtx; + op0 = new_rtx; + } } op0 = adjust_address (op0, mode, 0); @@ -10551,7 +10571,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* WITH_SIZE_EXPR expands to its first argument. The caller should have pulled out the size to use in whatever context it needed. */ return expand_expr_real (treeop0, original_target, tmode, - modifier, alt_rtl); + modifier, alt_rtl, inner_reference_p); default: return expand_expr_real_2 (&ops, target, tmode, modifier); |