aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>2000-03-26 12:05:34 -0500
committerRichard Kenner <kenner@gcc.gnu.org>2000-03-26 12:05:34 -0500
commita69beca121baeb70efa57d7f381cf7376778d21a (patch)
treea4b08daab16d206b224e9368ad326ed434f256e5 /gcc/expr.c
parent751312371e66c05a8d3b1cda949ec26aa9f1e548 (diff)
downloadgcc-a69beca121baeb70efa57d7f381cf7376778d21a.zip
gcc-a69beca121baeb70efa57d7f381cf7376778d21a.tar.gz
gcc-a69beca121baeb70efa57d7f381cf7376778d21a.tar.bz2
expr.c (expand_assignment): Add code to handle variable-sized BLKmode case.
* expr.c (expand_assignment): Add code to handle variable-sized BLKmode case. From-SVN: r32749
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 4d7007e..3e0085d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3447,27 +3447,49 @@ expand_assignment (to, from, want_value, suggest_reg)
TYPE_MODE (integer_type_node));
}
- result = store_field (to_rtx, bitsize, bitpos, mode1, from,
- (want_value
- /* Spurious cast makes HPUX compiler happy. */
- ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to))
- : VOIDmode),
- unsignedp,
- /* Required alignment of containing datum. */
- alignment,
- int_size_in_bytes (TREE_TYPE (tem)),
- get_alias_set (to));
- preserve_temp_slots (result);
- free_temp_slots ();
- pop_temp_slots ();
-
- /* If the value is meaningful, convert RESULT to the proper mode.
- Otherwise, return nothing. */
- return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
- TYPE_MODE (TREE_TYPE (from)),
- result,
- TREE_UNSIGNED (TREE_TYPE (to)))
- : NULL_RTX);
+ /* If this is a varying-length object, we must get the address of
+ the source and do an explicit block move. */
+ if (bitsize < 0)
+ {
+ unsigned int from_align;
+ rtx from_rtx = expand_expr_unaligned (from, &from_align);
+ rtx inner_to_rtx
+ = change_address (to_rtx, VOIDmode,
+ plus_constant (XEXP (to_rtx, 0),
+ bitpos / BITS_PER_UNIT));
+
+ emit_block_move (inner_to_rtx, from_rtx, expr_size (from),
+ MIN (alignment, from_align) / BITS_PER_UNIT);
+ free_temp_slots ();
+ pop_temp_slots ();
+ return to_rtx;
+ }
+ else
+ {
+ result = store_field (to_rtx, bitsize, bitpos, mode1, from,
+ (want_value
+ /* Spurious cast for HPUX compiler. */
+ ? ((enum machine_mode)
+ TYPE_MODE (TREE_TYPE (to)))
+ : VOIDmode),
+ unsignedp,
+ /* Required alignment of containing datum. */
+ alignment,
+ int_size_in_bytes (TREE_TYPE (tem)),
+ get_alias_set (to));
+
+ preserve_temp_slots (result);
+ free_temp_slots ();
+ pop_temp_slots ();
+
+ /* If the value is meaningful, convert RESULT to the proper mode.
+ Otherwise, return nothing. */
+ return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
+ TYPE_MODE (TREE_TYPE (from)),
+ result,
+ TREE_UNSIGNED (TREE_TYPE (to)))
+ : NULL_RTX);
+ }
}
/* If the rhs is a function call and its value is not an aggregate,