From: Eric Botcazou Date: Mon, 16 May 2016 10:14:19 +0000 (+0000) Subject: exp_util.adb (Remove_Side_Effects): Also make a constant if we need to capture the... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=34da9c9840ae773d1b0196a9e27ffa2b40ed14f9;p=gcc.git 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 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6dde4738b5e..fc8fe944bf6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,22 @@ +2016-05-16 Eric Botcazou + + * 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 * gcc-interface/Make-lang.in (GNATMAKE_FOR_HOST): In the canadian diff --git a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst index b9eee2f6c13..0a3dd4a9112 100644 --- a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst @@ -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 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`, and the maximum alignment supported by the target. (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 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 - packed arrays), then the alignment will be one for long packed arrays, - or arrays whose length is not known at compile time. For short packed + packed arrays), then the alignment will be either 4, 2 or 1 for long 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 - 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. * *Records*. @@ -789,7 +790,7 @@ restrictions placed on component clauses as follows: little-endian machines, this must be explicitly programmed. This capability 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 reordered, such fields would occupy a non-contiguous sequence of bits @@ -1069,22 +1070,23 @@ Pragma Pack for Arrays .. index:: Pragma Pack (for arrays) -Pragma `Pack` applied to an array has no effect unless the component type -is packable. For a component type to be packable, it must be one of the -following cases: +Pragma `Pack` applied to an array has an effect that depends upon whether the +component type is *packable*. For a component type to be *packable*, it must +be one of the following cases: -* - Any scalar type -* - Any type whose size is specified with a size clause -* - Any packed array type with a static size -* - Any record type padded because of its default alignment +* Any elementary type. + +* Any small packed array type with a static size. + +* Any small simple record type with a static size. 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. + +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: .. code-block:: ada @@ -1095,7 +1097,7 @@ For example if we have: pragma Pack (ar); 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 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. Components of the following types are considered packable: -* - Components of a primitive type are packable unless they are aliased - or of an atomic type. +* Components of an elementary type are packable unless they are aliased, + independent or of an atomic type. -* - Small packed arrays, whose size does not exceed 64 bits, and where the - size is statically known at compile time, are represented internally - as modular integers, and so they are also packable. +* Small packed arrays, where the size is statically known, 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 -their `Size` value, and are packed with no padding bits, i.e., they -can start on an arbitrary bit boundary. +For all these cases, if the 'Size value is in the range 1 through 64, the +components occupy the exact number of bits corresponding to this value +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 -storage units, and -are placed at a boundary corresponding to their alignment requirements. +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, 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. 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 type, in particular, always starting on a byte boundary, and the length must be a multiple of the storage unit. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 4ea4cb2bf3b..7dbf44acfe8 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -7711,15 +7711,22 @@ package body Exp_Util is Scope_Suppress.Suppress := (others => True); - -- If it is an elementary type and we need to capture the value, just - -- make a constant. Likewise if this is not a name reference, except - -- for a type conversion because we would enter an infinite recursion - -- with Checks.Apply_Predicate_Check if the target 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 this is an elementary or a small not by-reference record type, and + -- we need to capture the value, just make a constant; this is cheap and + -- objects of both kinds of types can be bit aligned, so it might not be + -- possible to generate a reference to them. Likewise if this is not a + -- name reference, except for a type conversion because we would enter + -- an infinite recursion with Checks.Apply_Predicate_Check if the target + -- 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) + 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 or else (not Is_Name_Reference (Exp) and then Nkind (Exp) /= N_Type_Conversion) diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 1fce9477818..d7d9b360450 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -745,9 +745,9 @@ package body Freeze is procedure Check_Compile_Time_Size (T : Entity_Id) is procedure Set_Small_Size (T : Entity_Id; S : Uint); - -- Sets the compile time known size (32 bits or less) in the Esize - -- 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. + -- 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 + -- to give a smaller size. function Size_Known (T : Entity_Id) return Boolean; -- 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 begin - if S > 32 then + if S > 64 then return; -- Check for bad size clause given @@ -800,14 +800,12 @@ package body Freeze is if Size_Known_At_Compile_Time (T) then return True; - -- Always True for scalar types. This is true even for generic formal - -- scalar types. We used to return False in the latter case, but the - -- size is known at compile time, even in the template, we just do - -- not know the exact size but that's not the point of this routine. + -- Always True for elementary types, even generic formal elementary + -- types. We used to return False in the latter case, but the size + -- is known at compile time, even in the template, we just do not + -- know the exact size but that's not the point of this routine. - elsif Is_Scalar_Type (T) - or else Is_Task_Type (T) - then + elsif Is_Elementary_Type (T) or else Is_Task_Type (T) then return True; -- Array types @@ -817,8 +815,8 @@ package body Freeze is -- String literals always have known size, and we can set it if Ekind (T) = E_String_Literal_Subtype then - Set_Small_Size (T, Component_Size (T) - * String_Literal_Length (T)); + Set_Small_Size + (T, Component_Size (T) * String_Literal_Length (T)); return True; -- Unconstrained types never have known at compile time size @@ -839,10 +837,10 @@ package body Freeze is end if; -- 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 - Esiz : Uint := Component_Size (T); + Size : Uint := Component_Size (T); Dim : Uint; begin @@ -869,24 +867,19 @@ package body Freeze is Dim := Expr_Value (High) - Expr_Value (Low) + 1; if Dim >= 0 then - Esiz := Esiz * Dim; + Size := Size * Dim; else - Esiz := Uint_0; + Size := Uint_0; end if; end if; Next_Index (Index); end loop; - Set_Small_Size (T, Esiz); + Set_Small_Size (T, Size); return True; 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 elsif Is_Private_Type (T) @@ -1074,11 +1067,10 @@ package body Freeze is if Packed_Size_Known then - -- We can only deal with elementary types, since for - -- non-elementary components, alignment enters into the - -- picture, and we don't know enough to handle proper - -- alignment in this context. Packed arrays count as - -- elementary if the representation is a modular type. + -- We can deal with elementary types, small packed arrays + -- if the representation is a modular type and also small + -- record types (if the size is not greater than 64, but + -- the condition is checked by Set_Small_Size). if Is_Elementary_Type (Ctyp) or else (Is_Array_Type (Ctyp) @@ -1086,33 +1078,14 @@ package body Freeze is (Packed_Array_Impl_Type (Ctyp)) and then Is_Modular_Integer_Type (Packed_Array_Impl_Type (Ctyp))) + or else Is_Record_Type (Ctyp) 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 - -- accumulating the packed size - - elsif Known_Static_RM_Size (Ctyp) then - - -- A little glitch, to be removed sometime ??? - -- gigi does not understand zero sizes yet. + -- accumulating the packed size. - if RM_Size (Ctyp) = Uint_0 then - Packed_Size_Known := False; + if Known_Static_RM_Size (Ctyp) then - -- Normal case where we can keep accumulating the - -- packed array size. - - else - Packed_Size := Packed_Size + RM_Size (Ctyp); - end if; + Packed_Size := Packed_Size + RM_Size (Ctyp); -- If we have a field whose RM_Size is not known then -- we can't figure out the packed size here. @@ -1121,8 +1094,7 @@ package body Freeze is Packed_Size_Known := False; end if; - -- If we have a non-elementary type we can't figure out - -- the packed array size (alignment issues). + -- For other types we can't figure out the packed size else Packed_Size_Known := False; @@ -2475,13 +2447,15 @@ package body Freeze is end if; -- 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 or else Csiz = 16 or else Csiz = 32 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 -- Here the array was requested to be packed, but -- the packing request had no effect, so Is_Packed diff --git a/gcc/ada/freeze.ads b/gcc/ada/freeze.ads index 81f2e0001ba..079d7132abe 100644 --- a/gcc/ada/freeze.ads +++ b/gcc/ada/freeze.ads @@ -151,15 +151,15 @@ package Freeze is -- fact Gigi decides it is known, but the opposite situation can never -- occur. -- - -- Size is known at compile time, but the actual value of the size is - -- not known to the front end or is definitely 32 or more. In this case - -- Size_Known_At_Compile_Time is set, but the Esize field is left set + -- Size is known at compile time, but the actual value of the size is not + -- known to the front end or is definitely greater than 64. In this case, + -- Size_Known_At_Compile_Time is set, but the RM_Size field is left set -- to zero (to be set by Gigi). -- -- 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 - -- Size_Known_At_Compile_Time is set, and in addition Esize is set to - -- the required size, allowing for possible front end packing of an + -- known to the front end and is not greater than 64. In this case, the + -- flag Size_Known_At_Compile_Time is set, and in addition RM_Size is set + -- to the required size, allowing for possible front end packing of an -- array using this type as a component type. -- -- Note: the flag Size_Known_At_Compile_Time is used to determine if the