> > The type has BLKmode and size 32. DECL_SIZE of the FIELD_DECL is however 24 > > (see it printed as Ada size). > > Yes, no wonder since it's a bitfield, i.e. DECL_BIT_FIELD is set. > > > The DECL_MODE of the FIELD_DECL is VOIDmode (not printed), while the > > TYPE_MODE of type contained is BLKmode. > > No, the DECL_MODE of a FIELD_DECL cannot be VOIDmode, it's SImode (printed).
Hmm you are right. The reason is... > > > Because > > get_inner_reference compute mode based on DECL_MODE: > > if (TREE_CODE (exp) == COMPONENT_REF) > > { > > tree field = TREE_OPERAND (exp, 1); > > size_tree = DECL_SIZE (field); > > if (flag_strict_volatile_bitfields > 0 > > && TREE_THIS_VOLATILE (exp) > > && DECL_BIT_FIELD_TYPE (field) > > && DECL_MODE (field) != BLKmode) > > /* Volatile bitfields should be accessed in the mode of the > > field's type, not the mode computed based on the bit > > size. */ > > mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field)); > > else if (!DECL_BIT_FIELD (field)) > > mode = DECL_MODE (field); ... we initialize mode to be non-VOIDmode only if the field is not bitfield. I missed the flag while looking at the dump. Indeed the DECL_MODE if FIELD_DECL is SImode, but it is ignored. > > Index: expr.c > > =================================================================== > > --- expr.c (revision 228604) > > +++ expr.c (working copy) > > @@ -6703,7 +6704,7 @@ store_field (rtx target, HOST_WIDE_INT b > > emit_group_store (temp_target, temp, TREE_TYPE (exp), size); > > temp = temp_target; > > } > > - else if (mode == BLKmode) > > + else if (GET_MODE (temp) == BLKmode) > > { > > /* Handle calls that return BLKmode values in registers. */ > > if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR) > > This cannot be right, you're short-circuiting the REG_P (temp) test below. Hmm, it seems that for CALL_EXPR the register is supposed to be non-BLKmode already. So I guess only what we need to do is to consider bifields when TEMP is blk mode and then we want to convert? what about this? Honza Index: expr.c =================================================================== --- expr.c (revision 228604) +++ expr.c (working copy) @@ -6703,26 +6703,23 @@ store_field (rtx target, HOST_WIDE_INT b 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); - 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; + } + else if (GET_MODE (temp) == BLKmode) + { + 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); + temp = temp_target; } /* Store the value in the bitfield. */ > > -- > Eric Botcazou