===================================================================
@@ -1589,11 +1589,18 @@ extern void protected_set_expr_location
get one debug info record for them. */
#define TYPE_STUB_DECL(NODE) (TREE_CHAIN (TYPE_CHECK (NODE)))
-/* In a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ARRAY_TYPE, it means
- the type has BLKmode only because it lacks the alignment required for
- its size. */
-#define TYPE_NO_FORCE_BLK(NODE) \
- (TYPE_CHECK (NODE)->type_common.no_force_blk_flag)
+/* In a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ARRAY_TYPE with BLKmode,
+ it means the type has BLKmode only because it lacks the alignment required
+ for its size. In a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ARRAY_TYPE
+ with non-BLKmode, it means the type should have had BLKmode because out of
+ bounds access (but didn't because of backwards compatibility reasons). */
+#define TYPE_BLKMODE_FLAG(NODE) (TYPE_CHECK (NODE)->type_common.blkmode_flag)
+#define TYPE_NO_FORCE_BLKMODE(NODE) \
+ (TYPE_MODE (TYPE_CHECK (NODE)) == BLKmode && TYPE_BLKMODE_FLAG (NODE))
+#define SET_TYPE_NO_FORCE_BLKMODE(NODE, X) (TYPE_BLKMODE_FLAG (NODE) = (X))
+#define TYPE_BLKMODE_FOR_ACCESS(NODE) \
+ (TYPE_MODE (TYPE_CHECK (NODE)) != BLKmode && TYPE_BLKMODE_FLAG (NODE))
+#define SET_TYPE_BLKMODE_FOR_ACCESS(NODE, X) (TYPE_BLKMODE_FLAG (NODE) = (X))
/* Nonzero in a type considered volatile as a whole. */
#define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag)
===================================================================
@@ -868,7 +868,7 @@ hash_tree (struct streamer_tree_cache_d
{
v = iterative_hash_host_wide_int (TYPE_MODE (t), v);
v = iterative_hash_host_wide_int (TYPE_STRING_FLAG (t)
- | (TYPE_NO_FORCE_BLK (t) << 1)
+ | (TYPE_BLKMODE_FLAG (t) << 1)
| (TYPE_NEEDS_CONSTRUCTING (t) << 2)
| (TYPE_PACKED (t) << 3)
| (TYPE_RESTRICT (t) << 4)
===================================================================
@@ -9656,6 +9656,7 @@ expand_expr_real_1 (tree exp, rtx target
if (modifier != EXPAND_WRITE
&& modifier != EXPAND_MEMORY
&& mode != BLKmode
+ && !TYPE_BLKMODE_FOR_ACCESS (type)
&& align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
@@ -9736,6 +9737,7 @@ expand_expr_real_1 (tree exp, rtx target
if (modifier != EXPAND_WRITE
&& modifier != EXPAND_MEMORY
&& mode != BLKmode
+ && !TYPE_BLKMODE_FOR_ACCESS (type)
&& align < GET_MODE_ALIGNMENT (mode))
{
if ((icode = optab_handler (movmisalign_optab, mode))
@@ -10426,50 +10428,53 @@ expand_expr_real_1 (tree exp, rtx target
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
&& mode != BLKmode
+ && !TYPE_BLKMODE_FOR_ACCESS (type)
&& 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 = new_rtx;
+ 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 = adjust_address (op0, mode, 0);
===================================================================
@@ -41,7 +41,8 @@ along with GCC; see the file COPYING3.
is a constant that is not a legitimate address.
EXPAND_WRITE means we are only going to write to the resulting rtx.
EXPAND_MEMORY means we are interested in a memory result, even if
- the memory is constant and we could have propagated a constant value. */
+ the memory is constant and we could have propagated a constant value,
+ or the memory is unaligned on a STRICT_ALIGNMENT target. */
enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
EXPAND_MEMORY};
===================================================================
@@ -1575,8 +1575,9 @@ finalize_record_size (record_layout_info
void
compute_record_mode (tree type)
{
- tree field;
enum machine_mode mode = VOIDmode;
+ bool blkmode_for_access = false;
+ tree field;
/* Most RECORD_TYPEs have BLKmode, so we start off assuming that.
However, if possible, we use a mode that fits in a register
@@ -1597,9 +1598,7 @@ compute_record_mode (tree type)
if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK
|| (TYPE_MODE (TREE_TYPE (field)) == BLKmode
- && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))
- && !(TYPE_SIZE (TREE_TYPE (field)) != 0
- && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
+ && ! TYPE_NO_FORCE_BLKMODE (TREE_TYPE (field)))
|| ! tree_fits_uhwi_p (bit_position (field))
|| DECL_SIZE (field) == 0
|| ! tree_fits_uhwi_p (DECL_SIZE (field)))
@@ -1615,6 +1614,15 @@ compute_record_mode (tree type)
BLKmode structure as a scalar. */
if (targetm.member_type_forces_blk (field, mode))
return;
+
+ /* As an extension, we support out-of-bounds access for trailing arrays.
+ In this case, if the element type has non-zero size, then the record
+ type effectively has variable size so it needs to have BLKmode. */
+ blkmode_for_access
+ = (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && !integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_TYPE (field)))))
+ || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
+ && TYPE_BLKMODE_FOR_ACCESS (TREE_TYPE (field)));
}
/* If we only have one real field; use its mode if that mode's size
@@ -1636,9 +1644,14 @@ compute_record_mode (tree type)
{
/* If this is the only reason this type is BLKmode, then
don't force containing types to be BLKmode. */
- TYPE_NO_FORCE_BLK (type) = 1;
+ SET_TYPE_NO_FORCE_BLKMODE (type, 1);
SET_TYPE_MODE (type, BLKmode);
}
+
+ /* If the record type needs BLKmode for access but didn't get it through
+ the standard layout algorithm, record it for later. */
+ if (TYPE_MODE (type) != BLKmode && blkmode_for_access)
+ SET_TYPE_BLKMODE_FOR_ACCESS (type, 1);
}
/* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
@@ -2245,7 +2258,7 @@ layout_type (tree type)
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
- || TYPE_NO_FORCE_BLK (TREE_TYPE (type))))
+ || TYPE_NO_FORCE_BLKMODE (TREE_TYPE (type))))
{
SET_TYPE_MODE (type, mode_for_array (TREE_TYPE (type),
TYPE_SIZE (type)));
@@ -2253,7 +2266,7 @@ layout_type (tree type)
&& STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT
&& TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
{
- TYPE_NO_FORCE_BLK (type) = 1;
+ SET_TYPE_NO_FORCE_BLKMODE (type, 1);
SET_TYPE_MODE (type, BLKmode);
}
}
===================================================================
@@ -2253,7 +2253,7 @@ expand_call_stmt (gimple stmt)
if (lhs)
expand_assignment (lhs, exp, false);
else
- expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
+ expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
mark_transaction_restart_calls (stmt);
}
===================================================================
@@ -1349,7 +1349,7 @@ compare_tree_sccs_1 (tree t1, tree t2, t
{
compare_values (TYPE_MODE);
compare_values (TYPE_STRING_FLAG);
- compare_values (TYPE_NO_FORCE_BLK);
+ compare_values (TYPE_BLKMODE_FLAG);
compare_values (TYPE_NEEDS_CONSTRUCTING);
if (RECORD_OR_UNION_TYPE_P (t1))
{
===================================================================
@@ -302,7 +302,7 @@ pack_ts_type_common_value_fields (struct
{
bp_pack_enum (bp, machine_mode, MAX_MACHINE_MODE, TYPE_MODE (expr));
bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
- bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1);
+ bp_pack_value (bp, TYPE_BLKMODE_FLAG (expr), 1);
bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
if (RECORD_OR_UNION_TYPE_P (expr))
{
===================================================================
@@ -583,8 +583,10 @@ print_node (FILE *file, const char *pref
if (TYPE_UNSIGNED (node))
fputs (" unsigned", file);
- if (TYPE_NO_FORCE_BLK (node))
- fputs (" no-force-blk", file);
+ if (TYPE_NO_FORCE_BLKMODE (node))
+ fputs (" no-force-blkmode", file);
+ else if (TYPE_BLKMODE_FOR_ACCESS (node))
+ fputs (" blkmode-for-access", file);
if (TYPE_STRING_FLAG (node))
fputs (" string-flag", file);
===================================================================
@@ -352,7 +352,7 @@ unpack_ts_type_common_value_fields (stru
mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
SET_TYPE_MODE (expr, mode);
TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
- TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1);
+ TYPE_BLKMODE_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
if (RECORD_OR_UNION_TYPE_P (expr))
{
===================================================================
@@ -1239,7 +1239,7 @@ struct GTY(()) tree_type_common {
unsigned int uid;
unsigned int precision : 10;
- unsigned no_force_blk_flag : 1;
+ unsigned blkmode_flag : 1;
unsigned needs_constructing_flag : 1;
unsigned transparent_aggr_flag : 1;
unsigned restrict_flag : 1;