From: Eric Botcazou Date: Mon, 16 May 2016 11:08:53 +0000 (+0000) Subject: * doc/gnat_rm/implementation_defined_attributes.rst X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b3f7567260257b58a77a7c43ba9eb4840f2a09d8;p=gcc.git * 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): Do not 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) : Call maybe_pad_type instead of building the padding type manually. (gnat_to_gnu_entity) : 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. From-SVN: r236279 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b8b14d2a63c..2f5620f2d07 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,36 @@ +2016-05-16 Eric Botcazou + + * 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): Do not 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) : + Call maybe_pad_type instead of building the padding type manually. + (gnat_to_gnu_entity) : 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. + 2016-05-16 Thomas Quinot * freeze.adb (Check_Component_Storage_Order): Also get full view of diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst index 432db36441a..958ab2413f7 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst @@ -969,7 +969,7 @@ must have the same scalar storage order as the parent type. 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. diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 901e2ef937e..69492fc1748 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -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: +-- array types which have a packed representation. There are four 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. +-- 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 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. +-- 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, diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index cb1c117b30b..e6ea474eec1 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -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; diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index dbdd33dc8fc..9f7c1dc01c6 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -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); diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index ea82596b820..0ec3ef44814 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -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 diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index c040f07bafe..8b74f86addd 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -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); diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index f3d2b52671d..8f2be234f8a 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1961,47 +1961,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* 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; - - /* Set the RM size before wrapping up the type. */ - SET_TYPE_RM_SIZE (gnu_type, - UI_To_gnu (RM_Size (gnat_entity), bitsizetype)); + tree gnu_size = 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); + /* Set the RM size before wrapping the type. */ + SET_TYPE_RM_SIZE (gnu_type, gnu_size); - /* Now save it and build the enclosing record type. */ - gnu_field_type = gnu_type; + gnu_type + = maybe_pad_type (gnu_type, TYPE_SIZE (gnu_type), align, + gnat_entity, false, true, definition, false); - 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); - - finish_record_type (gnu_type, gnu_field, 2, false); - compute_record_mode (gnu_type); - - if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL) - SET_TYPE_DEBUG_TYPE (gnu_type, gnu_field_type); + SET_TYPE_ADA_SIZE (gnu_type, gnu_size); } break; @@ -2909,10 +2882,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) 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 gnat_array, bool definition, 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 gnat_array, bool definition, && 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 gnat_array, bool definition, 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) diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 9cc744b24f2..099923d97fb 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -129,9 +129,11 @@ extern tree make_aligning_type (tree type, unsigned int align, tree size, 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 diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 8c36149a18c..74940655c68 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -937,23 +937,24 @@ make_aligning_type (tree type, unsigned int align, tree size, /* 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_record) 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_record) && 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_record) 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_record) 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;