This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Ada] Extend pragma Implicit_Packing for records to composite components
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 16 May 2016 13:20:57 +0200
- Subject: [Ada] Extend pragma Implicit_Packing for records to composite components
- Authentication-results: sourceware.org; auth=none
The implementation of pragma Implicit_Packing for record types was restricted
to scalar components, i.e. it gave up as soon as there was one non-scalar
component in the record type. This change extends it to all the other kinds
of components, at least if they are small.
The following package must compile quietly:
pragma Implicit_Packing;
package P is
type Rec1 is record
B : Boolean;
end record;
for Rec1'Size use 1;
type Rec2 is record
B : Boolean;
R : Rec1;
end record;
for Rec2'Size use 2;
type Rec3 is record
B : Boolean;
R : Rec2;
end record;
for Rec3'Size use 3;
end P;
Tested on x86_64-suse-linux, applied on the mainline.
2016-05-16 Eric Botcazou <ebotcazou@adacore.com>
* freeze.adb (Freeze_Record_Type): Extend pragma Implicit_Packing to
components of any elementary types and of composite types.
--
Eric Botcazou
Index: freeze.adb
===================================================================
--- freeze.adb (revision 236281)
+++ freeze.adb (working copy)
@@ -3534,13 +3534,23 @@ package body Freeze is
-- Set True if we find at least one component whose type has a
-- Scalar_Storage_Order attribute definition clause.
- All_Scalar_Components : Boolean := True;
- -- Set False if we encounter a component of a non-scalar type
+ All_Elem_Components : Boolean := True;
+ -- Set False if we encounter a component of a composite type
- Scalar_Component_Total_RM_Size : Uint := Uint_0;
- Scalar_Component_Total_Esize : Uint := Uint_0;
- -- Accumulates total RM_Size values and total Esize values of all
- -- scalar components. Used for processing of Implicit_Packing.
+ All_Sized_Components : Boolean := True;
+ -- Set False if we encounter a component with unknown RM_Size
+
+ All_Storage_Unit_Components : Boolean := True;
+ -- Set False if we encounter a component of a composite type whose
+ -- RM_Size is not a multiple of the storage unit.
+
+ Elem_Component_Total_Esize : Uint := Uint_0;
+ -- Accumulates total Esize values of all elementary components. Used
+ -- for processing of Implicit_Packing.
+
+ Sized_Component_Total_RM_Size : Uint := Uint_0;
+ -- Accumulates total RM_Size values of all sized components. Used
+ -- for processing of Implicit_Packing.
function Check_Allocator (N : Node_Id) return Node_Id;
-- If N is an allocator, possibly wrapped in one or more level of
@@ -3835,13 +3845,22 @@ package body Freeze is
-- this stage we might be dealing with a real component, or with
-- an implicit subtype declaration.
- if not Is_Scalar_Type (Etype (Comp)) then
- All_Scalar_Components := False;
+ if Known_Static_RM_Size (Etype (Comp)) then
+ Sized_Component_Total_RM_Size :=
+ Sized_Component_Total_RM_Size + RM_Size (Etype (Comp));
+
+ if Is_Elementary_Type (Etype (Comp)) then
+ Elem_Component_Total_Esize :=
+ Elem_Component_Total_Esize + Esize (Etype (Comp));
+ else
+ All_Elem_Components := False;
+
+ if RM_Size (Etype (Comp)) mod System_Storage_Unit /= 0 then
+ All_Storage_Unit_Components := False;
+ end if;
+ end if;
else
- Scalar_Component_Total_RM_Size :=
- Scalar_Component_Total_RM_Size + RM_Size (Etype (Comp));
- Scalar_Component_Total_Esize :=
- Scalar_Component_Total_Esize + Esize (Etype (Comp));
+ All_Sized_Components := False;
end if;
-- If the component is an Itype with Delayed_Freeze and is either
@@ -4312,26 +4331,33 @@ package body Freeze is
and then not Aliased_Component
- -- Must have size clause and all scalar components
+ -- Must have size clause and all sized components
and then Has_Size_Clause (Rec)
- and then All_Scalar_Components
+ and then All_Sized_Components
-- Do not try implicit packing on records with discriminants, too
-- complicated, especially in the variant record case.
and then not Has_Discriminants (Rec)
- -- We can implicitly pack if the specified size of the record is
- -- less than the sum of the object sizes (no point in packing if
- -- this is not the case).
-
- and then RM_Size (Rec) < Scalar_Component_Total_Esize
+ -- We want to implicitly pack if the specified size of the record
+ -- is less than the sum of the object sizes (no point in packing
+ -- if this is not the case) if we can compute it, i.e. if we have
+ -- only elementary components. Otherwise, we have at least one
+ -- composite component and we want to implicit pack only if bit
+ -- packing is required for it, as we are sure in this case that
+ -- the back end cannot do the expected layout without packing.
+
+ and then ((All_Elem_Components
+ and then RM_Size (Rec) < Elem_Component_Total_Esize)
+ or else (not All_Elem_Components
+ and then not All_Storage_Unit_Components))
-- And the total RM size cannot be greater than the specified size
-- since otherwise packing will not get us where we have to be.
- and then RM_Size (Rec) >= Scalar_Component_Total_RM_Size
+ and then RM_Size (Rec) >= Sized_Component_Total_RM_Size
-- Never do implicit packing in CodePeer or SPARK modes since
-- we don't do any packing in these modes, since this generates