On Mon, May 16, 2016 at 01:09:28PM +0200, Eric Botcazou wrote:
> This patch cleans up the implementation of packed array types, which is shared
> between the front-end proper and gigi (because the middle-end doesn't support
> bit packing for array types, unlike for record types through bit fields).
> 
> The two main changes are the reduced usage of bit packing (not necessary for
> composite types whose size is multiple of a byte) and the reduced usage of
> the internal implementation type built by the front-end (not necessary when
> the packing is entirely done in gigi).  For example, on the package:
> 
> with Interfaces; use Interfaces;
> 
> package Q is
> 
>   type Rec is record
>     S : Unsigned_16;
>     B : Unsigned_8;
>   end record;
> 
>   type Arr1 is array (1 .. 8) of Rec;
>   pragma Pack (Arr1);
> 
>   type Arr2 is array (1 .. 8) of Rec;
>   for Arr2'Component_Size use 24;
> 
> end Q;
> 
> the packing for both array types is now done entirely in gigi and implemented
> more efficiently, i.e. there is no call to the runtime.
> 
> As a side effect, this also fixes an issue with misalignment clauses applied
> to unconstrained byte-packed array types, which were silently ignored in some
> cases.  For example, the following package must now compile silently:
> 
> with Interfaces; use Interfaces;
> 
> package P is
> 
>   type Rec is record
>     I : Unsigned_32;
>     S : Unsigned_16;
>   end record;
> 
>   type Arr is array (Positive range <>) of Rec;
>   pragma Pack (Arr);
>   for Arr'Alignment use 1;
> 
>   type CArr is array (1 .. 4) of Rec;
>   pragma Pack (CArr);
>   for CArr'Alignment use 1;
> 
>   A : Arr (1 .. 4);
>   for A'Alignment use 1;
> 
> end P;
> 
> 
> Tested on x86_64-suse-linux, applied on the mainline.
> 
> 
> 2016-05-16  Eric Botcazou  <ebotca...@adacore.com>
> 
>       * doc/gnat_rm/implementation_defined_attributes.rst
>       (Scalar_Storage_Order): Adjust restriction for packed array types.
>       * einfo.ads (Is_Bit_Packed_Array): Adjust description.
>       (Is_Packed): Likewise.
>       (Is_Packed_Array_Impl_Type): Likewise.
>       (Packed_Array_Impl_Type): Likewise.
>       * exp_ch4.adb (Expand_N_Indexed_Component): Don't do anything special
>       if the prefix is not a packed array implemented specially.
>       * exp_ch6.adb (Expand_Actuals): Expand indexed components only for
>       bit-packed array types.
>       * exp_pakd.adb (Install_PAT): Set Is_Packed_Array_Impl_Type flag on
>       the PAT before analyzing its declaration.
>       (Create_Packed_Array_Impl_Type): Remove redundant statements.
>       * freeze.adb (Check_Component_Storage_Order): Reject packed array
>       components only if they are bit packed.
>       (Freeze_Array_Type): Fix logic detecting bit packing and do not bit
>       pack for composite types whose size is multiple of a byte.
>       Create the implementation type for packed array types only when it is
>       needed, i.e. bit packing or packing because of holes in index types.
>       Make sure the Has_Non_Standard_Rep and Is_Packed flags agree.
>       * gcc-interface/gigi.h (make_packable_type): Add MAX_ALIGN parameter.
>       * gcc-interface/decl.c (gnat_to_gnu_entity)<E_Signed_Integer_Subtype>
>       Call maybe_pad_type instead of building the padding type manually.
>       (gnat_to_gnu_entity) <E_Array_Subtype>: Do not assert that
>       Packed_Array_Impl_Type is present for packed arrays.
>       (gnat_to_gnu_component_type): Also handle known alignment for packed
>       types by passing it to make_packable_type.
>       * gcc-interface/utils.c (make_packable_type): Add MAX_ALIGN parameter
>       and deal with it in the array case.  Adjust recursive call.  Simplify
>       computation of new size and cap the alignment to BIGGEST_ALIGNMENT.

This patch makes gnat.dg/pack9.adb FAIL on s390x.  See
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79441


> 
> -- 
> Eric Botcazou

> Index: doc/gnat_rm/implementation_defined_attributes.rst
> ===================================================================
> --- doc/gnat_rm/implementation_defined_attributes.rst (revision 236264)
> +++ doc/gnat_rm/implementation_defined_attributes.rst (working copy)
> @@ -969,7 +969,7 @@ must have the same scalar storage order
>  If a component of `T` is of a record or array type, then that type must
>  also have a `Scalar_Storage_Order` attribute definition clause.
>  
> -A component of a record or array type that is a packed array, or that
> +A component of a record or array type that is a bit-packed array, or that
>  does not start on a byte boundary, must have the same scalar storage order
>  as the enclosing record or array type.
>  
> Index: einfo.ads
> ===================================================================
> --- einfo.ads (revision 236264)
> +++ einfo.ads (working copy)
> @@ -2268,9 +2268,9 @@ package Einfo is
>  --       is bit packed (i.e. the component size is known by the front end and
>  --       is in the range 1-7, 9-15, 17-31, or 33-63). Is_Packed is always set
>  --       if Is_Bit_Packed_Array is set, but it is possible for Is_Packed to 
> be
> ---       set without Is_Bit_Packed_Array for the case of an array having one 
> or
> ---       more index types that are enumeration types with non-standard
> ---       enumeration representations.
> +--       set without Is_Bit_Packed_Array if the component size is not known 
> by
> +--       the front-end or for the case of an array having one or more index
> +--       types that are enumeration types with non-standard representation.
>  
>  --    Is_Boolean_Type (synthesized)
>  --       Applies to all entities, true for boolean types and subtypes,
> @@ -2852,49 +2852,49 @@ package Einfo is
>  
>  --    Is_Packed (Flag51) [implementation base type only]
>  --       Defined in all type entities. This flag is set only for record and
> ---       array types which have a packed representation. There are three
> ---       cases which cause packing:
> ---
> ---         1. Explicit use of pragma Pack for an array of package components
> ---         2. Explicit use of pragma Pack to pack a record
> ---         4. Setting Component_Size of an array to a bit-packable value
> ---         3. Indexing an array with a non-standard enumeration type.
> ---
> ---       For records, Is_Packed is always set if Has_Pragma_Pack is set,
> ---       and can also be set on its own in a derived type which inherited
> ---       its packed status.
> ---
> ---       For arrays, Is_Packed is set if an array is bit packed (i.e. the
> ---       component size is known at compile time and is 1-7, 9-15 or 17-31),
> ---       or if the array has one or more index types that are enumeration
> ---       types with non-standard representations (in GNAT, we store such
> ---       arrays compactly, using the Pos of the enumeration type value).
> ---
> ---       As for the case of records, Is_Packed can be set on its own for a
> ---       derived type, with the same dual before/after freeze meaning.
> ---       Is_Packed can also be set as the result of an explicit component
> ---       size clause that specifies an appropriate component size.
> ---
> ---       In the bit packed array case, Is_Bit_Packed_Array will be set in
> ---       the bit packed case once the array type is frozen.
> +--       array types which have a packed representation. There are four cases
> +--       which cause packing:
>  --
> +--         1. Explicit use of pragma Pack to pack a record.
> +--         2. Explicit use of pragma Pack to pack an array.
> +--         3. Setting Component_Size of an array to a packable value.
> +--         4. Indexing an array with a non-standard enumeration type.
> +--
> +--       For records, Is_Packed is always set if Has_Pragma_Pack is set, and
> +--       can also be set on its own in a derived type which inherited its
> +--       packed status.
> +--
> +--       For arrays, Is_Packed is set if either Has_Pragma_Pack is set and 
> the
> +--       component size is either not known at compile time or known but not
> +--       8/16/32/64 bits, or a Component_Size clause exists and the specified
> +--       value is smaller than 64 bits but not 8/16/32, or if the array has 
> one
> +--       or more index types that are enumeration types with a non-standard
> +--       representation (in GNAT, we store such arrays compactly, using the 
> Pos
> +--       of the enumeration type value). As for the case of records, 
> Is_Packed
> +--       can be set on its own for a derived type.
> +
>  --       Before an array type is frozen, Is_Packed will always be set if
>  --       Has_Pragma_Pack is set. Before the freeze point, it is not possible
>  --       to know the component size, since the component type is not frozen
>  --       until the array type is frozen. Thus Is_Packed for an array type
>  --       before it is frozen means that packed is required. Then if it turns
> ---       out that the component size is not suitable for bit packing, the
> ---       Is_Packed flag gets turned off.
> +--       out that the component size doesn't require packing, the Is_Packed
> +--       flag gets turned off.
>  
> +--       In the bit packed array case (i.e. component size is known at 
> compile
> +--       time and is 1-7, 9-15, 17-31 or 33-63), Is_Bit_Packed_Array will be
> +--       set once the array type is frozen.
> +--
>  --    Is_Packed_Array (synth)
>  --       Applies to all entities, true if entity is for a packed array.
>  
>  --    Is_Packed_Array_Impl_Type (Flag138)
>  --       Defined in all entities. This flag is set on the entity for the type
> ---       used to implement a packed array (either a modular type, or a 
> subtype
> ---       of Packed_Bytes{1,2,4} as appropriate). The flag is set if and only
> +--       used to implement a packed array (either a modular type or a subtype
> +--       of Packed_Bytes{1,2,4} in the bit packed array case, a regular array
> +--       in the non-standard enumeration index case). It is set if and only
>  --       if the type appears in the Packed_Array_Impl_Type field of some 
> other
> ---       entity. It is used by the backend to activate the special processing
> +--       entity. It is used by the back end to activate the special 
> processing
>  --       for such types (unchecked conversions that would not otherwise be
>  --       allowed are allowed for such types). If Is_Packed_Array_Impl_Type is
>  --       set in an entity, then the Original_Array_Type field of this entity
> @@ -3698,16 +3698,17 @@ package Einfo is
>  --       with formal packages. ???
>  
>  --    Packed_Array_Impl_Type (Node23)
> ---       Defined in array types and subtypes, including the string literal
> ---       subtype case, if the corresponding type is packed (either bit packed
> ---       or packed to eliminate holes in non-contiguous enumeration type 
> index
> ---       types). References the type used to represent the packed array, 
> which
> ---       is either a modular type for short static arrays, or an array of
> ---       System.Unsigned. Note that in some situations (internal types, and
> ---       references to fields of variant records), it is not always possible
> ---       to construct this type in advance of its use. If this field is 
> empty,
> ---       then the necessary type is declared on the fly for each reference to
> ---       the array.
> +--       Defined in array types and subtypes, except for the string literal
> +--       subtype case, if the corresponding type is packed and implemented
> +--       specially (either bit packed or packed to eliminate holes in the
> +--       non-contiguous enumeration index types). References the type used to
> +--       represent the packed array, which is either a modular type for short
> +--       static arrays or an array of System.Unsigned in the bit packed case,
> +--       or a regular array in the non-standard enumeration index case). Note
> +--       that in some situations (internal types and references to fields of
> +--       variant records), it is not always possible to construct this type 
> in
> +--       advance of its use. If this field is empty, then the necessary type
> +--       is declared on the fly for each reference to the array.
>  
>  --    Parameter_Mode (synthesized)
>  --       Applies to formal parameter entities. This is a synonym for Ekind,
> Index: exp_ch4.adb
> ===================================================================
> --- exp_ch4.adb       (revision 236264)
> +++ exp_ch4.adb       (working copy)
> @@ -6216,9 +6216,11 @@ package body Exp_Ch4 is
>           Activate_Atomic_Synchronization (N);
>        end if;
>  
> -      --  All done for the non-packed case
> +      --  All done if the prefix is not a packed array implemented specially
>  
> -      if not Is_Packed (Etype (Prefix (N))) then
> +      if not (Is_Packed (Etype (Prefix (N)))
> +               and then Present (Packed_Array_Impl_Type (Etype (Prefix 
> (N)))))
> +      then
>           return;
>        end if;
>  
> Index: exp_ch6.adb
> ===================================================================
> --- exp_ch6.adb       (revision 236264)
> +++ exp_ch6.adb       (working copy)
> @@ -2038,7 +2038,7 @@ package body Exp_Ch6 is
>           --  Processing for IN parameters
>  
>           else
> -            --  For IN parameters is in the packed array case, we expand an
> +            --  For IN parameters in the bit packed array case, we expand an
>              --  indexed component (the circuit in Exp_Ch4 deliberately left
>              --  indexed components appearing as actuals untouched, so that
>              --  the special processing above for the OUT and IN OUT cases
> @@ -2047,7 +2047,7 @@ package body Exp_Ch6 is
>              --  easier simply to handle all cases here.)
>  
>              if Nkind (Actual) = N_Indexed_Component
> -              and then Is_Packed (Etype (Prefix (Actual)))
> +              and then Is_Bit_Packed_Array (Etype (Prefix (Actual)))
>              then
>                 Reset_Packed_Prefix;
>                 Expand_Packed_Element_Reference (Actual);
> Index: exp_pakd.adb
> ===================================================================
> --- exp_pakd.adb      (revision 236264)
> +++ exp_pakd.adb      (working copy)
> @@ -543,6 +543,7 @@ package body Exp_Pakd is
>           end if;
>  
>           Set_Is_Itype (PAT, True);
> +         Set_Is_Packed_Array_Impl_Type (PAT, True);
>           Set_Packed_Array_Impl_Type (Typ, PAT);
>           Analyze (Decl, Suppress => All_Checks);
>  
> @@ -569,7 +570,6 @@ package body Exp_Pakd is
>           Init_Alignment                (PAT);
>           Set_Parent                    (PAT, Empty);
>           Set_Associated_Node_For_Itype (PAT, Typ);
> -         Set_Is_Packed_Array_Impl_Type (PAT, True);
>           Set_Original_Array_Type       (PAT, Typ);
>  
>           --  Propagate representation aspects
> @@ -701,8 +701,6 @@ package body Exp_Pakd is
>             Make_Defining_Identifier (Loc,
>               Chars => New_External_Name (Chars (Typ), 'P'));
>  
> -         Set_Packed_Array_Impl_Type (Typ, PAT);
> -
>           declare
>              Indexes   : constant List_Id := New_List;
>              Indx      : Node_Id;
> @@ -798,9 +796,6 @@ package body Exp_Pakd is
>                  Type_Definition     => Typedef);
>           end;
>  
> -         --  Set type as packed array type and install it
> -
> -         Set_Is_Packed_Array_Impl_Type (PAT);
>           Install_PAT;
>           return;
>  
> @@ -819,13 +814,13 @@ package body Exp_Pakd is
>             Make_Defining_Identifier (Loc,
>               Chars => Make_Packed_Array_Impl_Type_Name (Typ, Csize));
>  
> -         Set_Packed_Array_Impl_Type (Typ, PAT);
>           Set_PB_Type;
>  
>           Decl :=
>             Make_Subtype_Declaration (Loc,
>               Defining_Identifier => PAT,
>                 Subtype_Indication => New_Occurrence_Of (PB_Type, Loc));
> +
>           Install_PAT;
>           return;
>  
> @@ -843,8 +838,6 @@ package body Exp_Pakd is
>             Make_Defining_Identifier (Loc,
>               Chars => Make_Packed_Array_Impl_Type_Name (Typ, Csize));
>  
> -         Set_Packed_Array_Impl_Type (Typ, PAT);
> -
>           --  Build an expression for the length of the array in bits.
>           --  This is the product of the length of each of the dimensions
>  
> Index: freeze.adb
> ===================================================================
> --- freeze.adb        (revision 236277)
> +++ freeze.adb        (working copy)
> @@ -1254,24 +1254,24 @@ package body Freeze is
>              end if;
>  
>           --  If component and composite SSO differs, check that component
> -         --  falls on byte boundaries and isn't packed.
> +         --  falls on byte boundaries and isn't bit packed.
>  
>           elsif Comp_SSO_Differs then
>  
>              --  Component SSO differs from enclosing composite:
>  
> -            --  Reject if component is a packed array, as it may be 
> represented
> +            --  Reject if component is a bit-packed array, as it is 
> represented
>              --  as a scalar internally.
>  
> -            if Is_Packed_Array (Comp_Base) then
> +            if Is_Bit_Packed_Array (Comp_Base) then
>                 Error_Msg_N
>                   ("type of packed component must have same scalar storage "
>                    & "order as enclosing composite", Err_Node);
>  
> -            --  Reject if composite is a packed array, as it may be rewritten
> +            --  Reject if composite is a bit-packed array, as it is rewritten
>              --  into an array of scalars.
>  
> -            elsif Is_Packed_Array (Encl_Base) then
> +            elsif Is_Bit_Packed_Array (Encl_Base) then
>                 Error_Msg_N
>                   ("type of packed array must have same scalar storage order "
>                    & "as component", Err_Node);
> @@ -2386,7 +2386,7 @@ package body Freeze is
>                    end if;
>                 end if;
>  
> -               --  Case of component size that may result in packing
> +               --  Case of component size that may result in bit packing
>  
>                 if 1 <= Csiz and then Csiz <= 64 then
>                    declare
> @@ -2451,44 +2451,58 @@ package body Freeze is
>                          end if;
>                       end if;
>  
> -                     --  Actual packing is not needed for 8, 16, 32, 64. Also
> -                     --  not needed for multiples of 8 if alignment is 1, and
> -                     --  for multiples of 16 (i.e. only 48) if alignment is 
> 2.
> +                     --  Bit packing is never needed for 8, 16, 32, 64
>  
>                       if        Csiz = 8
>                         or else Csiz = 16
>                         or else Csiz = 32
>                         or else Csiz = 64
> -                       or else (Csiz mod 8 = 0 and then Alignment (Ctyp) = 1)
> -                       or else (Csiz = 48 and then Alignment (Ctyp) = 2)
>                       then
> -                        --  Here the array was requested to be packed, but
> -                        --  the packing request had no effect, so Is_Packed
> -                        --  is reset.
> -
> -                        --  Note: semantically this means that we lose track
> -                        --  of the fact that a derived type inherited a 
> pragma
> -                        --  Pack that was non- effective, but that seems 
> fine.
> -
> -                        --  We regard a Pack pragma as a request to set a
> -                        --  representation characteristic, and this request
> -                        --  may be ignored.
> -
> -                        Set_Is_Packed           (Base_Type (Arr), False);
> -                        Set_Is_Bit_Packed_Array (Base_Type (Arr), False);
> +                        --  If the Esize of the component is known and equal 
> to
> +                        --  the component size then even packing is not 
> needed.
>  
>                          if Known_Static_Esize (Component_Type (Arr))
>                            and then Esize (Component_Type (Arr)) = Csiz
>                          then
> +                           --  Here the array was requested to be packed, but
> +                           --  the packing request had no effect whatsoever,
> +                           --  so flag Is_Packed is reset.
> +
> +                           --  Note: semantically this means that we lose 
> track
> +                           --  of the fact that a derived type inherited 
> pragma
> +                           --  Pack that was non-effective, but that is fine.
> +
> +                           --  We regard a Pack pragma as a request to set a
> +                           --  representation characteristic, and this 
> request
> +                           --  may be ignored.
> +
> +                           Set_Is_Packed            (Base_Type (Arr), False);
>                             Set_Has_Non_Standard_Rep (Base_Type (Arr), False);
> +                        else
> +                           Set_Is_Packed            (Base_Type (Arr), True);
> +                           Set_Has_Non_Standard_Rep (Base_Type (Arr), True);
>                          end if;
>  
> -                        --  In all other cases, packing is indeed needed
> +                        Set_Is_Bit_Packed_Array (Base_Type (Arr), False);
> +
> +                     --  Bit packing is not needed for multiples of the 
> storage
> +                     --  unit if the type is composite because the back end 
> can
> +                     --  byte pack composite types.
> +
> +                     elsif Csiz mod System_Storage_Unit = 0
> +                       and then Is_Composite_Type (Ctyp)
> +                     then
> +
> +                        Set_Is_Packed            (Base_Type (Arr), True);
> +                        Set_Has_Non_Standard_Rep (Base_Type (Arr), True);
> +                        Set_Is_Bit_Packed_Array  (Base_Type (Arr), False);
> +
> +                     --  In all other cases, bit packing is needed
>  
>                       else
> +                        Set_Is_Packed            (Base_Type (Arr), True);
>                          Set_Has_Non_Standard_Rep (Base_Type (Arr), True);
>                          Set_Is_Bit_Packed_Array  (Base_Type (Arr), True);
> -                        Set_Is_Packed            (Base_Type (Arr), True);
>                       end if;
>                    end;
>                 end if;
> @@ -2780,12 +2794,14 @@ package body Freeze is
>  
>           Set_Component_Alignment_If_Not_Set (Arr);
>  
> -         --  If the array is packed, we must create the packed array type to 
> be
> -         --  used to actually implement the type. This is only needed for 
> real
> -         --  array types (not for string literal types, since they are 
> present
> -         --  only for the front end).
> +         --  If the array is packed and bit packed or packed to eliminate 
> holes
> +         --  in the non-contiguous enumeration index types, we must create 
> the
> +         --  packed array type to be used to actually implement the type. 
> This
> +         --  is only needed for real array types (not for string literal 
> types,
> +         --  since they are present only for the front end).
>  
>           if Is_Packed (Arr)
> +           and then (Is_Bit_Packed_Array (Arr) or else Non_Standard_Enum)
>             and then Ekind (Arr) /= E_String_Literal_Subtype
>           then
>              Create_Packed_Array_Impl_Type (Arr);
> Index: gcc-interface/decl.c
> ===================================================================
> --- gcc-interface/decl.c      (revision 236264)
> +++ gcc-interface/decl.c      (working copy)
> @@ -1961,47 +1961,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
>  
>        /* If the type we are dealing with has got a smaller alignment than the
>        natural one, we need to wrap it up in a record type and misalign the
> -      latter; we reuse the padding machinery for this purpose.  Note that,
> -      even if the record type is marked as packed because of misalignment,
> -      we don't pack the field so as to give it the size of the type.  */
> +      latter; we reuse the padding machinery for this purpose.  */
>        else if (align > 0)
>       {
> -       tree gnu_field_type, gnu_field;
> +       tree gnu_size = UI_To_gnu (RM_Size (gnat_entity), bitsizetype);
>  
> -       /* Set the RM size before wrapping up the type.  */
> -       SET_TYPE_RM_SIZE (gnu_type,
> -                         UI_To_gnu (RM_Size (gnat_entity), bitsizetype));
> -
> -       /* Create a stripped-down declaration, mainly for debugging.  */
> -       create_type_decl (gnu_entity_name, gnu_type, true, debug_info_p,
> -                         gnat_entity);
> -
> -       /* Now save it and build the enclosing record type.  */
> -       gnu_field_type = gnu_type;
> -
> -       gnu_type = make_node (RECORD_TYPE);
> -       TYPE_PADDING_P (gnu_type) = 1;
> -       TYPE_NAME (gnu_type) = create_concat_name (gnat_entity, "PAD");
> -       TYPE_PACKED (gnu_type) = 1;
> -       TYPE_SIZE (gnu_type) = TYPE_SIZE (gnu_field_type);
> -       TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_field_type);
> -       SET_TYPE_ADA_SIZE (gnu_type, TYPE_RM_SIZE (gnu_field_type));
> -       SET_TYPE_ALIGN (gnu_type, align);
> -       relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY);
> -
> -       /* Don't declare the field as addressable since we won't be taking
> -          its address and this would prevent create_field_decl from making
> -          a bitfield.  */
> -       gnu_field
> -         = create_field_decl (get_identifier ("F"), gnu_field_type,
> -                              gnu_type, TYPE_SIZE (gnu_field_type),
> -                              bitsize_zero_node, 0, 0);
> +       /* Set the RM size before wrapping the type.  */
> +       SET_TYPE_RM_SIZE (gnu_type, gnu_size);
>  
> -       finish_record_type (gnu_type, gnu_field, 2, false);
> -       compute_record_mode (gnu_type);
> +       gnu_type
> +         = maybe_pad_type (gnu_type, TYPE_SIZE (gnu_type), align,
> +                           gnat_entity, false, true, definition, false);
>  
> -       if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
> -         SET_TYPE_DEBUG_TYPE (gnu_type, gnu_field_type);
> +       TYPE_PACKED (gnu_type) = 1;
> +       SET_TYPE_ADA_SIZE (gnu_type, gnu_size);
>       }
>  
>        break;
> @@ -2909,10 +2882,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
>                   TREE_TYPE (TYPE_FIELDS (gnu_type)) = gnu_inner;
>               }
>           }
> -
> -       else
> -         /* Abort if packed array with no Packed_Array_Impl_Type.  */
> -         gcc_assert (!Is_Packed (gnat_entity));
>       }
>        break;
>  
> @@ -5234,6 +5203,16 @@ gnat_to_gnu_component_type (Entity_Id gn
>    const Entity_Id gnat_type = Component_Type (gnat_array);
>    tree gnu_type = gnat_to_gnu_type (gnat_type);
>    tree gnu_comp_size;
> +  unsigned int max_align;
> +
> +  /* If an alignment is specified, use it as a cap on the component type
> +     so that it can be honored for the whole type.  But ignore it for the
> +     original type of packed array types.  */
> +  if (No (Packed_Array_Impl_Type (gnat_array))
> +      && Known_Alignment (gnat_array))
> +    max_align = validate_alignment (Alignment (gnat_array), gnat_array, 0);
> +  else
> +    max_align = 0;
>  
>    /* Try to get a smaller form of the component if needed.  */
>    if ((Is_Packed (gnat_array) || Has_Component_Size_Clause (gnat_array))
> @@ -5243,7 +5222,7 @@ gnat_to_gnu_component_type (Entity_Id gn
>        && RECORD_OR_UNION_TYPE_P (gnu_type)
>        && !TYPE_FAT_POINTER_P (gnu_type)
>        && tree_fits_uhwi_p (TYPE_SIZE (gnu_type)))
> -    gnu_type = make_packable_type (gnu_type, false);
> +    gnu_type = make_packable_type (gnu_type, false, max_align);
>  
>    if (Has_Atomic_Components (gnat_array))
>      check_ok_for_atomic_type (gnu_type, gnat_array, true);
> @@ -5276,16 +5255,6 @@ gnat_to_gnu_component_type (Entity_Id gn
>    if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_array))
>      {
>        tree orig_type = gnu_type;
> -      unsigned int max_align;
> -
> -      /* If an alignment is specified, use it as a cap on the component type
> -      so that it can be honored for the whole type.  But ignore it for the
> -      original type of packed array types.  */
> -      if (No (Packed_Array_Impl_Type (gnat_array))
> -       && Known_Alignment (gnat_array))
> -     max_align = validate_alignment (Alignment (gnat_array), gnat_array, 0);
> -      else
> -     max_align = 0;
>  
>        gnu_type = make_type_from_size (gnu_type, gnu_comp_size, false);
>        if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align)
> Index: gcc-interface/gigi.h
> ===================================================================
> --- gcc-interface/gigi.h      (revision 236264)
> +++ gcc-interface/gigi.h      (working copy)
> @@ -129,9 +129,11 @@ extern tree make_aligning_type (tree typ
>     as the field type of a packed record if IN_RECORD is true, or as the
>     component type of a packed array if IN_RECORD is false.  See if we can
>     rewrite it either as a type that has a non-BLKmode, which we can pack
> -   tighter in the packed record case, or as a smaller type.  If so, return
> -   the new type.  If not, return the original type.  */
> -extern tree make_packable_type (tree type, bool in_record);
> +   tighter in the packed record case, or as a smaller type with at most
> +   MAX_ALIGN alignment if the value is non-zero.  If so, return the new
> +   type; if not, return the original type.  */
> +extern tree make_packable_type (tree type, bool in_record,
> +                             unsigned int max_align = 0);
>  
>  /* Given a type TYPE, return a new type whose size is appropriate for SIZE.
>     If TYPE is the best type, return it.  Otherwise, make a new type.  We
> Index: gcc-interface/utils.c
> ===================================================================
> --- gcc-interface/utils.c     (revision 236264)
> +++ gcc-interface/utils.c     (working copy)
> @@ -937,23 +937,24 @@ make_aligning_type (tree type, unsigned
>  /* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used
>     as the field type of a packed record if IN_RECORD is true, or as the
>     component type of a packed array if IN_RECORD is false.  See if we can
> -   rewrite it either as a type that has a non-BLKmode, which we can pack
> -   tighter in the packed record case, or as a smaller type.  If so, return
> -   the new type.  If not, return the original type.  */
> +   rewrite it either as a type that has non-BLKmode, which we can pack
> +   tighter in the packed record case, or as a smaller type with at most
> +   MAX_ALIGN alignment if the value is non-zero.  If so, return the new
> +   type; if not, return the original type.  */
>  
>  tree
> -make_packable_type (tree type, bool in_record)
> +make_packable_type (tree type, bool in_record, unsigned int max_align)
>  {
>    unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
>    unsigned HOST_WIDE_INT new_size;
> -  tree new_type, old_field, field_list = NULL_TREE;
> -  unsigned int align;
> +  unsigned int align = TYPE_ALIGN (type);
> +  unsigned int new_align;
>  
>    /* No point in doing anything if the size is zero.  */
>    if (size == 0)
>      return type;
>  
> -  new_type = make_node (TREE_CODE (type));
> +  tree new_type = make_node (TREE_CODE (type));
>  
>    /* Copy the name and flags from the old type to that of the new.
>       Note that we rely on the pointer equality created here for
> @@ -970,49 +971,50 @@ make_packable_type (tree type, bool in_r
>       type with BLKmode.  */
>    if (in_record && size <= MAX_FIXED_MODE_SIZE)
>      {
> -      align = ceil_pow2 (size);
> -      SET_TYPE_ALIGN (new_type, align);
> -      new_size = (size + align - 1) & -align;
> +      new_size = ceil_pow2 (size);
> +      new_align = MIN (new_size, BIGGEST_ALIGNMENT);
> +      SET_TYPE_ALIGN (new_type, new_align);
>      }
>    else
>      {
> -      unsigned HOST_WIDE_INT align;
> -
>        /* Do not try to shrink the size if the RM size is not constant.  */
>        if (TYPE_CONTAINS_TEMPLATE_P (type)
>         || !tree_fits_uhwi_p (TYPE_ADA_SIZE (type)))
>       return type;
>  
>        /* Round the RM size up to a unit boundary to get the minimal size
> -      for a BLKmode record.  Give up if it's already the size.  */
> +      for a BLKmode record.  Give up if it's already the size and we
> +      don't need to lower the alignment.  */
>        new_size = tree_to_uhwi (TYPE_ADA_SIZE (type));
>        new_size = (new_size + BITS_PER_UNIT - 1) & -BITS_PER_UNIT;
> -      if (new_size == size)
> +      if (new_size == size && (max_align == 0 || align <= max_align))
>       return type;
>  
> -      align = new_size & -new_size;
> -      SET_TYPE_ALIGN (new_type, MIN (TYPE_ALIGN (type), align));
> +      new_align = MIN (new_size & -new_size, BIGGEST_ALIGNMENT);
> +      if (max_align > 0 && new_align > max_align)
> +     new_align = max_align;
> +      SET_TYPE_ALIGN (new_type, MIN (align, new_align));
>      }
>  
>    TYPE_USER_ALIGN (new_type) = 1;
>  
>    /* Now copy the fields, keeping the position and size as we don't want
>       to change the layout by propagating the packedness downwards.  */
> -  for (old_field = TYPE_FIELDS (type); old_field;
> -       old_field = DECL_CHAIN (old_field))
> +  tree new_field_list = NULL_TREE;
> +  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
>      {
> -      tree new_field_type = TREE_TYPE (old_field);
> +      tree new_field_type = TREE_TYPE (field);
>        tree new_field, new_size;
>  
>        if (RECORD_OR_UNION_TYPE_P (new_field_type)
>         && !TYPE_FAT_POINTER_P (new_field_type)
>         && tree_fits_uhwi_p (TYPE_SIZE (new_field_type)))
> -     new_field_type = make_packable_type (new_field_type, true);
> +     new_field_type = make_packable_type (new_field_type, true, max_align);
>  
>        /* However, for the last field in a not already packed record type
>        that is of an aggregate type, we need to use the RM size in the
>        packable version of the record type, see finish_record_type.  */
> -      if (!DECL_CHAIN (old_field)
> +      if (!DECL_CHAIN (field)
>         && !TYPE_PACKED (type)
>         && RECORD_OR_UNION_TYPE_P (new_field_type)
>         && !TYPE_FAT_POINTER_P (new_field_type)
> @@ -1020,24 +1022,24 @@ make_packable_type (tree type, bool in_r
>         && TYPE_ADA_SIZE (new_field_type))
>       new_size = TYPE_ADA_SIZE (new_field_type);
>        else
> -     new_size = DECL_SIZE (old_field);
> +     new_size = DECL_SIZE (field);
>  
>        new_field
> -     = create_field_decl (DECL_NAME (old_field), new_field_type, new_type,
> -                          new_size, bit_position (old_field),
> +     = create_field_decl (DECL_NAME (field), new_field_type, new_type,
> +                          new_size, bit_position (field),
>                            TYPE_PACKED (type),
> -                          !DECL_NONADDRESSABLE_P (old_field));
> +                          !DECL_NONADDRESSABLE_P (field));
>  
> -      DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field);
> -      SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field);
> +      DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (field);
> +      SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, field);
>        if (TREE_CODE (new_type) == QUAL_UNION_TYPE)
> -     DECL_QUALIFIER (new_field) = DECL_QUALIFIER (old_field);
> +     DECL_QUALIFIER (new_field) = DECL_QUALIFIER (field);
>  
> -      DECL_CHAIN (new_field) = field_list;
> -      field_list = new_field;
> +      DECL_CHAIN (new_field) = new_field_list;
> +      new_field_list = new_field;
>      }
>  
> -  finish_record_type (new_type, nreverse (field_list), 2, false);
> +  finish_record_type (new_type, nreverse (new_field_list), 2, false);
>    relate_alias_sets (new_type, type, ALIAS_SET_COPY);
>    if (TYPE_STUB_DECL (type))
>      SET_DECL_PARALLEL_TYPE (TYPE_STUB_DECL (new_type),
> @@ -1054,8 +1056,7 @@ make_packable_type (tree type, bool in_r
>    else
>      {
>        TYPE_SIZE (new_type) = bitsize_int (new_size);
> -      TYPE_SIZE_UNIT (new_type)
> -     = size_int ((new_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
> +      TYPE_SIZE_UNIT (new_type) = size_int (new_size / BITS_PER_UNIT);
>      }
>  
>    if (!TYPE_CONTAINS_TEMPLATE_P (type))
> @@ -1069,8 +1070,8 @@ make_packable_type (tree type, bool in_r
>      SET_TYPE_MODE (new_type,
>                  mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1));
>  
> -  /* If neither the mode nor the size has shrunk, return the old type.  */
> -  if (TYPE_MODE (new_type) == BLKmode && new_size >= size)
> +  /* If neither mode nor size nor alignment shrunk, return the old type.  */
> +  if (TYPE_MODE (new_type) == BLKmode && new_size >= size && max_align == 0)
>      return type;
>  
>    return new_type;

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany

Reply via email to