exp_util.adb (Remove_Side_Effects): Also make a constant if we need to capture the value for a small not...
* exp_util.adb (Remove_Side_Effects): Also make a constant if we need to capture the value for a small not by-reference record type. * freeze.ads (Check_Compile_Time_Size): Adjust comment. * freeze.adb (Set_Small_Size): Likewise. Accept a size in the range of 33 .. 64 bits. (Check_Compile_Time_Size): Merge scalar and access type cases. Change variable name in array type case. For the computation of the packed size, deal with record components and remove redundant test. (Freeze_Array_Type): Also adjust packing status when the size of the component type is in the range 33 .. 64 bits. * doc/gnat_rm/representation_clauses_and_pragmas.rst: Turn primitive into elementary type throughout. Minor tweaks. (Alignment Clauses): Document actual alignment of packed array types. (Pragma Pack for Arrays): List only the 3 main cases and adjust. Add "simple" to the record case. Document effect on non packable types. (Pragma Pack for Records): Likewise. Add record case and adjust. From-SVN: r236275
This commit is contained in:
parent
0b9004ed56
commit
34da9c9840
|
@ -1,3 +1,22 @@
|
||||||
|
2016-05-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
|
* exp_util.adb (Remove_Side_Effects): Also make a constant if we need
|
||||||
|
to capture the value for a small not by-reference record type.
|
||||||
|
* freeze.ads (Check_Compile_Time_Size): Adjust comment.
|
||||||
|
* freeze.adb (Set_Small_Size): Likewise. Accept a size in the range
|
||||||
|
of 33 .. 64 bits.
|
||||||
|
(Check_Compile_Time_Size): Merge scalar and access type cases. Change
|
||||||
|
variable name in array type case. For the computation of the packed
|
||||||
|
size, deal with record components and remove redundant test.
|
||||||
|
(Freeze_Array_Type): Also adjust packing status when the size of the
|
||||||
|
component type is in the range 33 .. 64 bits.
|
||||||
|
* doc/gnat_rm/representation_clauses_and_pragmas.rst: Turn primitive
|
||||||
|
into elementary type throughout. Minor tweaks.
|
||||||
|
(Alignment Clauses): Document actual alignment of packed array types.
|
||||||
|
(Pragma Pack for Arrays): List only the 3 main cases and adjust. Add
|
||||||
|
"simple" to the record case. Document effect on non packable types.
|
||||||
|
(Pragma Pack for Records): Likewise. Add record case and adjust.
|
||||||
|
|
||||||
2016-05-16 Eric Botcazou <ebotcazou@adacore.com>
|
2016-05-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* gcc-interface/Make-lang.in (GNATMAKE_FOR_HOST): In the canadian
|
* gcc-interface/Make-lang.in (GNATMAKE_FOR_HOST): In the canadian
|
||||||
|
|
|
@ -32,9 +32,9 @@ GNAT requires that all alignment clauses specify a power of 2, and all
|
||||||
default alignments are always a power of 2. The default alignment
|
default alignments are always a power of 2. The default alignment
|
||||||
values are as follows:
|
values are as follows:
|
||||||
|
|
||||||
* *Primitive Types*.
|
* *Elementary Types*.
|
||||||
|
|
||||||
For primitive types, the alignment is the minimum of the actual size of
|
For elementary types, the alignment is the minimum of the actual size of
|
||||||
objects of the type divided by `Storage_Unit`,
|
objects of the type divided by `Storage_Unit`,
|
||||||
and the maximum alignment supported by the target.
|
and the maximum alignment supported by the target.
|
||||||
(This maximum alignment is given by the GNAT-specific attribute
|
(This maximum alignment is given by the GNAT-specific attribute
|
||||||
|
@ -53,10 +53,11 @@ values are as follows:
|
||||||
For arrays, the alignment is equal to the alignment of the component type
|
For arrays, the alignment is equal to the alignment of the component type
|
||||||
for the normal case where no packing or component size is given. If the
|
for the normal case where no packing or component size is given. If the
|
||||||
array is packed, and the packing is effective (see separate section on
|
array is packed, and the packing is effective (see separate section on
|
||||||
packed arrays), then the alignment will be one for long packed arrays,
|
packed arrays), then the alignment will be either 4, 2 or 1 for long packed
|
||||||
or arrays whose length is not known at compile time. For short packed
|
arrays or arrays whose length is not known at compile time, depending on
|
||||||
|
whether the component size is divisible by 4, 2 or is odd. For short packed
|
||||||
arrays, which are handled internally as modular types, the alignment
|
arrays, which are handled internally as modular types, the alignment
|
||||||
will be as described for primitive types, e.g., a packed array of length
|
will be as described for elementary types, e.g. a packed array of length
|
||||||
31 bits will have an object size of four bytes, and an alignment of 4.
|
31 bits will have an object size of four bytes, and an alignment of 4.
|
||||||
|
|
||||||
* *Records*.
|
* *Records*.
|
||||||
|
@ -789,7 +790,7 @@ restrictions placed on component clauses as follows:
|
||||||
little-endian machines, this must be explicitly programmed. This capability
|
little-endian machines, this must be explicitly programmed. This capability
|
||||||
is not provided by `Bit_Order`.
|
is not provided by `Bit_Order`.
|
||||||
|
|
||||||
* Components that are positioned across byte boundaries
|
* Components that are positioned across byte boundaries.
|
||||||
|
|
||||||
but do not occupy an integral number of bytes. Given that bytes are not
|
but do not occupy an integral number of bytes. Given that bytes are not
|
||||||
reordered, such fields would occupy a non-contiguous sequence of bits
|
reordered, such fields would occupy a non-contiguous sequence of bits
|
||||||
|
@ -1069,22 +1070,23 @@ Pragma Pack for Arrays
|
||||||
|
|
||||||
.. index:: Pragma Pack (for arrays)
|
.. index:: Pragma Pack (for arrays)
|
||||||
|
|
||||||
Pragma `Pack` applied to an array has no effect unless the component type
|
Pragma `Pack` applied to an array has an effect that depends upon whether the
|
||||||
is packable. For a component type to be packable, it must be one of the
|
component type is *packable*. For a component type to be *packable*, it must
|
||||||
following cases:
|
be one of the following cases:
|
||||||
|
|
||||||
*
|
* Any elementary type.
|
||||||
Any scalar type
|
|
||||||
*
|
* Any small packed array type with a static size.
|
||||||
Any type whose size is specified with a size clause
|
|
||||||
*
|
* Any small simple record type with a static size.
|
||||||
Any packed array type with a static size
|
|
||||||
*
|
|
||||||
Any record type padded because of its default alignment
|
|
||||||
|
|
||||||
For all these cases, if the component subtype size is in the range
|
For all these cases, if the component subtype size is in the range
|
||||||
1 through 63, then the effect of the pragma `Pack` is exactly as though a
|
1 through 64, then the effect of the pragma `Pack` is exactly as though a
|
||||||
component size were specified giving the component subtype size.
|
component size were specified giving the component subtype size.
|
||||||
|
|
||||||
|
All other types are non-packable, they occupy an integral number of storage
|
||||||
|
units and the only effect of pragma Pack is to remove alignment gaps.
|
||||||
|
|
||||||
For example if we have:
|
For example if we have:
|
||||||
|
|
||||||
.. code-block:: ada
|
.. code-block:: ada
|
||||||
|
@ -1095,7 +1097,7 @@ For example if we have:
|
||||||
pragma Pack (ar);
|
pragma Pack (ar);
|
||||||
|
|
||||||
Then the component size of `ar` will be set to 5 (i.e., to `r'size`,
|
Then the component size of `ar` will be set to 5 (i.e., to `r'size`,
|
||||||
and the size of the array `ar` will be exactly 40 bits.
|
and the size of the array `ar` will be exactly 40 bits).
|
||||||
|
|
||||||
Note that in some cases this rather fierce approach to packing can produce
|
Note that in some cases this rather fierce approach to packing can produce
|
||||||
unexpected effects. For example, in Ada 95 and Ada 2005,
|
unexpected effects. For example, in Ada 95 and Ada 2005,
|
||||||
|
@ -1184,23 +1186,21 @@ taken by components. We distinguish between *packable* components and
|
||||||
*non-packable* components.
|
*non-packable* components.
|
||||||
Components of the following types are considered packable:
|
Components of the following types are considered packable:
|
||||||
|
|
||||||
*
|
* Components of an elementary type are packable unless they are aliased,
|
||||||
Components of a primitive type are packable unless they are aliased
|
independent or of an atomic type.
|
||||||
or of an atomic type.
|
|
||||||
|
|
||||||
*
|
* Small packed arrays, where the size is statically known, are represented
|
||||||
Small packed arrays, whose size does not exceed 64 bits, and where the
|
internally as modular integers, and so they are also packable.
|
||||||
size is statically known at compile time, are represented internally
|
|
||||||
as modular integers, and so they are also packable.
|
|
||||||
|
|
||||||
|
* Small simple records, where the size is statically known, are also packable.
|
||||||
|
|
||||||
All packable components occupy the exact number of bits corresponding to
|
For all these cases, if the 'Size value is in the range 1 through 64, the
|
||||||
their `Size` value, and are packed with no padding bits, i.e., they
|
components occupy the exact number of bits corresponding to this value
|
||||||
can start on an arbitrary bit boundary.
|
and are packed with no padding bits, i.e. they can start on an arbitrary
|
||||||
|
bit boundary.
|
||||||
|
|
||||||
All other types are non-packable, they occupy an integral number of
|
All other types are non-packable, they occupy an integral number of storage
|
||||||
storage units, and
|
units and the only effect of pragma Pack is to remove alignment gaps.
|
||||||
are placed at a boundary corresponding to their alignment requirements.
|
|
||||||
|
|
||||||
For example, consider the record
|
For example, consider the record
|
||||||
|
|
||||||
|
@ -1331,7 +1331,7 @@ so for example, the following is permitted:
|
||||||
|
|
||||||
Note: the above rules apply to recent releases of GNAT 5.
|
Note: the above rules apply to recent releases of GNAT 5.
|
||||||
In GNAT 3, there are more severe restrictions on larger components.
|
In GNAT 3, there are more severe restrictions on larger components.
|
||||||
For non-primitive types, including packed arrays with a size greater than
|
For composite types, including packed arrays with a size greater than
|
||||||
64 bits, component clauses must respect the alignment requirement of the
|
64 bits, component clauses must respect the alignment requirement of the
|
||||||
type, in particular, always starting on a byte boundary, and the length
|
type, in particular, always starting on a byte boundary, and the length
|
||||||
must be a multiple of the storage unit.
|
must be a multiple of the storage unit.
|
||||||
|
|
|
@ -7711,15 +7711,22 @@ package body Exp_Util is
|
||||||
|
|
||||||
Scope_Suppress.Suppress := (others => True);
|
Scope_Suppress.Suppress := (others => True);
|
||||||
|
|
||||||
-- If it is an elementary type and we need to capture the value, just
|
-- If this is an elementary or a small not by-reference record type, and
|
||||||
-- make a constant. Likewise if this is not a name reference, except
|
-- we need to capture the value, just make a constant; this is cheap and
|
||||||
-- for a type conversion because we would enter an infinite recursion
|
-- objects of both kinds of types can be bit aligned, so it might not be
|
||||||
-- with Checks.Apply_Predicate_Check if the target type has predicates.
|
-- possible to generate a reference to them. Likewise if this is not a
|
||||||
-- And type conversions need a specific treatment anyway, see below.
|
-- name reference, except for a type conversion because we would enter
|
||||||
-- Also do it if we have a volatile reference and Name_Req is not set
|
-- an infinite recursion with Checks.Apply_Predicate_Check if the target
|
||||||
-- (see comments for Side_Effect_Free).
|
-- type has predicates (and type conversions need a specific treatment
|
||||||
|
-- anyway, see below). Also do it if we have a volatile reference and
|
||||||
|
-- Name_Req is not set (see comments for Side_Effect_Free).
|
||||||
|
|
||||||
if Is_Elementary_Type (Exp_Type)
|
if (Is_Elementary_Type (Exp_Type)
|
||||||
|
or else (Is_Record_Type (Exp_Type)
|
||||||
|
and then Known_Static_RM_Size (Exp_Type)
|
||||||
|
and then RM_Size (Exp_Type) <= 64
|
||||||
|
and then not Has_Discriminants (Exp_Type)
|
||||||
|
and then not Is_By_Reference_Type (Exp_Type)))
|
||||||
and then (Variable_Ref
|
and then (Variable_Ref
|
||||||
or else (not Is_Name_Reference (Exp)
|
or else (not Is_Name_Reference (Exp)
|
||||||
and then Nkind (Exp) /= N_Type_Conversion)
|
and then Nkind (Exp) /= N_Type_Conversion)
|
||||||
|
|
|
@ -745,9 +745,9 @@ package body Freeze is
|
||||||
procedure Check_Compile_Time_Size (T : Entity_Id) is
|
procedure Check_Compile_Time_Size (T : Entity_Id) is
|
||||||
|
|
||||||
procedure Set_Small_Size (T : Entity_Id; S : Uint);
|
procedure Set_Small_Size (T : Entity_Id; S : Uint);
|
||||||
-- Sets the compile time known size (32 bits or less) in the Esize
|
-- Sets the compile time known size (64 bits or less) in the RM_Size
|
||||||
-- field, of T checking for a size clause that was given which attempts
|
-- field of T, checking for a size clause that was given which attempts
|
||||||
-- to give a smaller size, and also checking for an alignment clause.
|
-- to give a smaller size.
|
||||||
|
|
||||||
function Size_Known (T : Entity_Id) return Boolean;
|
function Size_Known (T : Entity_Id) return Boolean;
|
||||||
-- Recursive function that does all the work
|
-- Recursive function that does all the work
|
||||||
|
@ -765,7 +765,7 @@ package body Freeze is
|
||||||
|
|
||||||
procedure Set_Small_Size (T : Entity_Id; S : Uint) is
|
procedure Set_Small_Size (T : Entity_Id; S : Uint) is
|
||||||
begin
|
begin
|
||||||
if S > 32 then
|
if S > 64 then
|
||||||
return;
|
return;
|
||||||
|
|
||||||
-- Check for bad size clause given
|
-- Check for bad size clause given
|
||||||
|
@ -800,14 +800,12 @@ package body Freeze is
|
||||||
if Size_Known_At_Compile_Time (T) then
|
if Size_Known_At_Compile_Time (T) then
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
-- Always True for scalar types. This is true even for generic formal
|
-- Always True for elementary types, even generic formal elementary
|
||||||
-- scalar types. We used to return False in the latter case, but the
|
-- types. We used to return False in the latter case, but the size
|
||||||
-- size is known at compile time, even in the template, we just do
|
-- is known at compile time, even in the template, we just do not
|
||||||
-- not know the exact size but that's not the point of this routine.
|
-- know the exact size but that's not the point of this routine.
|
||||||
|
|
||||||
elsif Is_Scalar_Type (T)
|
elsif Is_Elementary_Type (T) or else Is_Task_Type (T) then
|
||||||
or else Is_Task_Type (T)
|
|
||||||
then
|
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
-- Array types
|
-- Array types
|
||||||
|
@ -817,8 +815,8 @@ package body Freeze is
|
||||||
-- String literals always have known size, and we can set it
|
-- String literals always have known size, and we can set it
|
||||||
|
|
||||||
if Ekind (T) = E_String_Literal_Subtype then
|
if Ekind (T) = E_String_Literal_Subtype then
|
||||||
Set_Small_Size (T, Component_Size (T)
|
Set_Small_Size
|
||||||
* String_Literal_Length (T));
|
(T, Component_Size (T) * String_Literal_Length (T));
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
-- Unconstrained types never have known at compile time size
|
-- Unconstrained types never have known at compile time size
|
||||||
|
@ -839,10 +837,10 @@ package body Freeze is
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Check for all indexes static, and also compute possible size
|
-- Check for all indexes static, and also compute possible size
|
||||||
-- (in case it is less than 32 and may be packable).
|
-- (in case it is not greater than 64 and may be packable).
|
||||||
|
|
||||||
declare
|
declare
|
||||||
Esiz : Uint := Component_Size (T);
|
Size : Uint := Component_Size (T);
|
||||||
Dim : Uint;
|
Dim : Uint;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -869,24 +867,19 @@ package body Freeze is
|
||||||
Dim := Expr_Value (High) - Expr_Value (Low) + 1;
|
Dim := Expr_Value (High) - Expr_Value (Low) + 1;
|
||||||
|
|
||||||
if Dim >= 0 then
|
if Dim >= 0 then
|
||||||
Esiz := Esiz * Dim;
|
Size := Size * Dim;
|
||||||
else
|
else
|
||||||
Esiz := Uint_0;
|
Size := Uint_0;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Next_Index (Index);
|
Next_Index (Index);
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
Set_Small_Size (T, Esiz);
|
Set_Small_Size (T, Size);
|
||||||
return True;
|
return True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
-- Access types always have known at compile time sizes
|
|
||||||
|
|
||||||
elsif Is_Access_Type (T) then
|
|
||||||
return True;
|
|
||||||
|
|
||||||
-- For non-generic private types, go to underlying type if present
|
-- For non-generic private types, go to underlying type if present
|
||||||
|
|
||||||
elsif Is_Private_Type (T)
|
elsif Is_Private_Type (T)
|
||||||
|
@ -1074,11 +1067,10 @@ package body Freeze is
|
||||||
|
|
||||||
if Packed_Size_Known then
|
if Packed_Size_Known then
|
||||||
|
|
||||||
-- We can only deal with elementary types, since for
|
-- We can deal with elementary types, small packed arrays
|
||||||
-- non-elementary components, alignment enters into the
|
-- if the representation is a modular type and also small
|
||||||
-- picture, and we don't know enough to handle proper
|
-- record types (if the size is not greater than 64, but
|
||||||
-- alignment in this context. Packed arrays count as
|
-- the condition is checked by Set_Small_Size).
|
||||||
-- elementary if the representation is a modular type.
|
|
||||||
|
|
||||||
if Is_Elementary_Type (Ctyp)
|
if Is_Elementary_Type (Ctyp)
|
||||||
or else (Is_Array_Type (Ctyp)
|
or else (Is_Array_Type (Ctyp)
|
||||||
|
@ -1086,33 +1078,14 @@ package body Freeze is
|
||||||
(Packed_Array_Impl_Type (Ctyp))
|
(Packed_Array_Impl_Type (Ctyp))
|
||||||
and then Is_Modular_Integer_Type
|
and then Is_Modular_Integer_Type
|
||||||
(Packed_Array_Impl_Type (Ctyp)))
|
(Packed_Array_Impl_Type (Ctyp)))
|
||||||
|
or else Is_Record_Type (Ctyp)
|
||||||
then
|
then
|
||||||
-- Packed size unknown if we have an atomic/VFA type
|
|
||||||
-- or a by-reference type, since the back end knows
|
|
||||||
-- how these are layed out.
|
|
||||||
|
|
||||||
if Is_Atomic_Or_VFA (Ctyp)
|
|
||||||
or else Is_By_Reference_Type (Ctyp)
|
|
||||||
then
|
|
||||||
Packed_Size_Known := False;
|
|
||||||
|
|
||||||
-- If RM_Size is known and static, then we can keep
|
-- If RM_Size is known and static, then we can keep
|
||||||
-- accumulating the packed size
|
-- accumulating the packed size.
|
||||||
|
|
||||||
elsif Known_Static_RM_Size (Ctyp) then
|
if Known_Static_RM_Size (Ctyp) then
|
||||||
|
|
||||||
-- A little glitch, to be removed sometime ???
|
|
||||||
-- gigi does not understand zero sizes yet.
|
|
||||||
|
|
||||||
if RM_Size (Ctyp) = Uint_0 then
|
|
||||||
Packed_Size_Known := False;
|
|
||||||
|
|
||||||
-- Normal case where we can keep accumulating the
|
|
||||||
-- packed array size.
|
|
||||||
|
|
||||||
else
|
|
||||||
Packed_Size := Packed_Size + RM_Size (Ctyp);
|
Packed_Size := Packed_Size + RM_Size (Ctyp);
|
||||||
end if;
|
|
||||||
|
|
||||||
-- If we have a field whose RM_Size is not known then
|
-- If we have a field whose RM_Size is not known then
|
||||||
-- we can't figure out the packed size here.
|
-- we can't figure out the packed size here.
|
||||||
|
@ -1121,8 +1094,7 @@ package body Freeze is
|
||||||
Packed_Size_Known := False;
|
Packed_Size_Known := False;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- If we have a non-elementary type we can't figure out
|
-- For other types we can't figure out the packed size
|
||||||
-- the packed array size (alignment issues).
|
|
||||||
|
|
||||||
else
|
else
|
||||||
Packed_Size_Known := False;
|
Packed_Size_Known := False;
|
||||||
|
@ -2475,13 +2447,15 @@ package body Freeze is
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Actual packing is not needed for 8, 16, 32, 64. Also
|
-- Actual packing is not needed for 8, 16, 32, 64. Also
|
||||||
-- not needed for 24 if alignment is 1.
|
-- not needed for multiples of 8 if alignment is 1, and
|
||||||
|
-- for multiples of 16 (i.e. only 48) if alignment is 2.
|
||||||
|
|
||||||
if Csiz = 8
|
if Csiz = 8
|
||||||
or else Csiz = 16
|
or else Csiz = 16
|
||||||
or else Csiz = 32
|
or else Csiz = 32
|
||||||
or else Csiz = 64
|
or else Csiz = 64
|
||||||
or else (Csiz = 24 and then Alignment (Ctyp) = 1)
|
or else (Csiz mod 8 = 0 and then Alignment (Ctyp) = 1)
|
||||||
|
or else (Csiz = 48 and then Alignment (Ctyp) = 2)
|
||||||
then
|
then
|
||||||
-- Here the array was requested to be packed, but
|
-- Here the array was requested to be packed, but
|
||||||
-- the packing request had no effect, so Is_Packed
|
-- the packing request had no effect, so Is_Packed
|
||||||
|
|
|
@ -151,15 +151,15 @@ package Freeze is
|
||||||
-- fact Gigi decides it is known, but the opposite situation can never
|
-- fact Gigi decides it is known, but the opposite situation can never
|
||||||
-- occur.
|
-- occur.
|
||||||
--
|
--
|
||||||
-- Size is known at compile time, but the actual value of the size is
|
-- Size is known at compile time, but the actual value of the size is not
|
||||||
-- not known to the front end or is definitely 32 or more. In this case
|
-- known to the front end or is definitely greater than 64. In this case,
|
||||||
-- Size_Known_At_Compile_Time is set, but the Esize field is left set
|
-- Size_Known_At_Compile_Time is set, but the RM_Size field is left set
|
||||||
-- to zero (to be set by Gigi).
|
-- to zero (to be set by Gigi).
|
||||||
--
|
--
|
||||||
-- Size is known at compile time, and the actual value of the size is
|
-- Size is known at compile time, and the actual value of the size is
|
||||||
-- known to the front end and is less than 32. In this case, the flag
|
-- known to the front end and is not greater than 64. In this case, the
|
||||||
-- Size_Known_At_Compile_Time is set, and in addition Esize is set to
|
-- flag Size_Known_At_Compile_Time is set, and in addition RM_Size is set
|
||||||
-- the required size, allowing for possible front end packing of an
|
-- to the required size, allowing for possible front end packing of an
|
||||||
-- array using this type as a component type.
|
-- array using this type as a component type.
|
||||||
--
|
--
|
||||||
-- Note: the flag Size_Known_At_Compile_Time is used to determine if the
|
-- Note: the flag Size_Known_At_Compile_Time is used to determine if the
|
||||||
|
|
Loading…
Reference in New Issue