aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-09 22:17:17 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-09 22:17:17 +0000
commit082b91b6dcc77a8ae60cc77ba64da716cea90ed7 (patch)
tree8d71726144d66445d4f0544fc2a11951811121ba /gcc/expr.c
parent206d28833241b95fde6e785b3bfef85bb34dafde (diff)
* expr.c (store_field): In the bitfield case, if the value comes from
a function call and is of an aggregate type returned in registers, do not modify the field mode; extract the value in all cases if the mode is BLKmode and the size is not larger than a word. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244249 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c43
1 files changed, 20 insertions, 23 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index a7692157a5f..e1d70c3b189 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6888,33 +6888,30 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (GET_CODE (temp) == PARALLEL)
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
- rtx temp_target;
- if (mode == BLKmode || mode == VOIDmode)
- mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
- temp_target = gen_reg_rtx (mode);
+ machine_mode temp_mode
+ = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+ rtx temp_target = gen_reg_rtx (temp_mode);
emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
temp = temp_target;
}
- else if (mode == BLKmode)
+
+ /* Handle calls that return BLKmode values in registers. */
+ else if (mode == BLKmode && REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
{
- /* Handle calls that return BLKmode values in registers. */
- if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
- {
- rtx temp_target = gen_reg_rtx (GET_MODE (temp));
- copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
- temp = temp_target;
- }
- else
- {
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
- rtx temp_target;
- mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
- temp_target = gen_reg_rtx (mode);
- temp_target
- = extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
- temp_target, mode, mode, false);
- temp = temp_target;
- }
+ rtx temp_target = gen_reg_rtx (GET_MODE (temp));
+ copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
+ temp = temp_target;
+ }
+
+ /* The behavior of store_bit_field is awkward when mode is BLKmode:
+ it always takes its value from the lsb up to the word size but
+ expects it left justified beyond it. At this point TEMP is left
+ justified so extract the value in the former case. */
+ if (mode == BLKmode && bitsize <= BITS_PER_WORD)
+ {
+ machine_mode temp_mode = smallest_mode_for_size (bitsize, MODE_INT);
+ temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,
+ temp_mode, false);
}
/* Store the value in the bitfield. */