> 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).

> 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);
>       else if (DECL_MODE (field) == BLKmode)
>         blkmode_bitfield = true;
> 
>       *punsignedp = DECL_UNSIGNED (field);
>     }
> We miss the check
>   else if (mode == BLKmode)
> and fail to convert the register and die in horrible death.
> 
> What is the reason behind this construct? Is that Ada bug?

No, it's a BLKmode bitfield and we have had it for a couple of decades.

> Anyway, the following patch fixes the issue by caring about mode of the
> temporary (which is controled by the type) instead of the mode of the field.
> I am testing it on x86_64-linux now.
> 
> Honza
> 
> 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.

-- 
Eric Botcazou

Reply via email to