(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) <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.
From-SVN: r236279
+2016-05-16 Eric Botcazou <ebotcazou@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): 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) <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.
+
2016-05-16 Thomas Quinot <quinot@adacore.com>
* freeze.adb (Check_Component_Storage_Order): Also get full view of
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.
-- 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,
-- 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
-- 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,
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;
-- 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
-- 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);
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);
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
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;
Type_Definition => Typedef);
end;
- -- Set type as packed array type and install it
-
- Set_Is_Packed_Array_Impl_Type (PAT);
Install_PAT;
return;
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;
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
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);
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
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;
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);
/* 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;
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;
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))
&& 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);
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)
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
/* 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
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)
&& 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),
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))
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;