* [Ada] Improve support of size and alignment clauses
@ 2011-08-04 9:10 Arnaud Charlet
0 siblings, 0 replies; only message in thread
From: Arnaud Charlet @ 2011-08-04 9:10 UTC (permalink / raw)
To: gcc-patches; +Cc: Eric Botcazou
[-- Attachment #1: Type: text/plain, Size: 2121 bytes --]
This changes the way size and alignment clauses interact with each other.
Size clauses used to set the 'Size of a type in stone, although an alignment
clause could force the back-end to set different values for 'Object_Size
and 'Value_Size of the type, leading to an inconsistency when an object of
this type is declared with this same size clause and rejected.
'Object_Size and 'Value_Size are now decoupled and a size clause on a type
will only set the latter in stone; the former can now be increased by the
back-end to support a given alignment.
The following package must be rejected with the error:
badsize.ads:10:21: size for "RR1" too small, minimum allowed is 64
and the layout given by -gnatR1:
for r1'Object_Size use 64;
for r1'Value_Size use 40;
for r1'Alignment use 4;
for r1 use record
i at 0 range 0 .. 31;
b at 4 range 0 .. 7;
end record;
----
package badsize is
type R1 is record
I : Integer;
B : Boolean;
end record;
for R1'Alignment use 4;
for R1'Size use 40;
RR1 : R1;
for RR1'Size use 40;
end;
----
Tested on x86_64-pc-linux-gnu, committed on trunk
2011-08-04 Eric Botcazou <ebotcazou@adacore.com>
* layout.adb (Layout_Type): For composite types, do not set Esize.
* freeze.adb (Set_Small_Size): Remove test on alignment and do not
set Esize.
(Size_Known): Look at the RM size of components instead of the Esize.
(Freeze_Record_Type): Look at the RM size instead of the Esize to
issue warning and activate Implicit_Packing.
(Freeze_Entity): Likewise. Do not issue a warning for alias/atomic
if the Esize is not known.
* sem_ch13.adb (Analyze_Attribute_Definition_Clause) <Size>: Set Esize
for elementary types only.
(Analyze_Record_Representation_Clause): Look at the RM size instead
of the Esize to issue errors.
* gcc-interface/decl.c (gnat_to_gnu_entity): Do not set Esize if it
is not known.
<E_Record_Type>: Look at the RM size instead of the Esize. Remove
obsolete block.
Look at the RM size instead of the Esize for types if the latter is
not known.
(gnat_to_gnu_field): Use Known_Esize instead of Known_Static_Esize.
[-- Attachment #2: difs --]
[-- Type: text/plain, Size: 10676 bytes --]
Index: layout.adb
===================================================================
--- layout.adb (revision 177334)
+++ layout.adb (working copy)
@@ -2574,27 +2574,11 @@
end;
end if;
- -- If RM_Size is known, set Esize if not known
-
- if Known_RM_Size (E) and then Unknown_Esize (E) then
-
- -- If the alignment is known, we bump the Esize up to the next
- -- alignment boundary if it is not already on one.
-
- if Known_Alignment (E) then
- declare
- A : constant Uint := Alignment_In_Bits (E);
- S : constant SO_Ref := RM_Size (E);
- begin
- Set_Esize (E, (S + A - 1) / A * A);
- end;
- end if;
-
-- If Esize is set, and RM_Size is not, RM_Size is copied from Esize.
-- At least for now this seems reasonable, and is in any case needed
-- for compatibility with old versions of gigi.
- elsif Known_Esize (E) and then Unknown_RM_Size (E) then
+ if Known_Esize (E) and then Unknown_RM_Size (E) then
Set_RM_Size (E, Esize (E));
end if;
Index: freeze.adb
===================================================================
--- freeze.adb (revision 177320)
+++ freeze.adb (working copy)
@@ -623,13 +623,6 @@
if S > 32 then
return;
- -- Don't bother if alignment clause with a value other than 1 is
- -- present, because size may be padded up to meet back end alignment
- -- requirements, and only the back end knows the rules!
-
- elsif Known_Alignment (T) and then Alignment (T) /= 1 then
- return;
-
-- Check for bad size clause given
elsif Has_Size_Clause (T) then
@@ -638,21 +631,12 @@
Error_Msg_NE
("size for& too small, minimum allowed is ^",
Size_Clause (T), T);
-
- elsif Unknown_Esize (T) then
- Set_Esize (T, S);
end if;
- -- Set sizes if not set already
+ -- Set size if not set already
- else
- if Unknown_Esize (T) then
- Set_Esize (T, S);
- end if;
-
- if Unknown_RM_Size (T) then
- Set_RM_Size (T, S);
- end if;
+ elsif Unknown_RM_Size (T) then
+ Set_RM_Size (T, S);
end if;
end Set_Small_Size;
@@ -836,7 +820,7 @@
if not Is_Constrained (T)
and then
No (Discriminant_Default_Value (First_Discriminant (T)))
- and then Unknown_Esize (T)
+ and then Unknown_RM_Size (T)
then
return False;
end if;
@@ -2251,12 +2235,12 @@
-- less than the sum of the object sizes (no point in packing if
-- this is not the case).
- and then Esize (Rec) < Scalar_Component_Total_Esize
+ and then RM_Size (Rec) < Scalar_Component_Total_Esize
-- 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 Esize (Rec) >= Scalar_Component_Total_RM_Size
+ and then RM_Size (Rec) >= Scalar_Component_Total_RM_Size
-- Never do implicit packing in CodePeer mode since we don't do
-- any packing in this mode, since this generates over-complex
@@ -3034,12 +3018,12 @@
-- action that causes stuff to be inherited).
if Present (Size_Clause (E))
- and then Known_Static_Esize (E)
+ and then Known_Static_RM_Size (E)
and then not Is_Packed (E)
and then not Has_Pragma_Pack (E)
and then Number_Dimensions (E) = 1
and then not Has_Component_Size_Clause (E)
- and then Known_Static_Esize (Ctyp)
+ and then Known_Static_RM_Size (Ctyp)
and then not Is_Limited_Composite (E)
and then not Is_Packed (Root_Type (E))
and then not Has_Component_Size_Clause (Root_Type (E))
@@ -3412,12 +3396,18 @@
-- Start of processing for Alias_Atomic_Check
begin
+
+ -- If object size of component type isn't known, we
+ -- cannot be sure so we defer to the back end.
+
+ if not Known_Static_Esize (Ctyp) then
+ null;
+
-- Case where component size has no effect. First
- -- check for object size of component type known
- -- and a multiple of the storage unit size.
+ -- check for object size of component type multiple
+ -- of the storage unit size.
- if Known_Static_Esize (Ctyp)
- and then Esize (Ctyp) mod System_Storage_Unit = 0
+ elsif Esize (Ctyp) mod System_Storage_Unit = 0
-- OK in both packing case and component size case
-- if RM size is known and static and the same as
Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb (revision 177335)
+++ sem_ch13.adb (working copy)
@@ -2348,11 +2348,15 @@
if Is_Type (U_Ent) then
Set_RM_Size (U_Ent, Size);
- -- For scalar types, increase Object_Size to power of 2, but
- -- not less than a storage unit in any case (i.e., normally
+ -- For elementary types, increase Object_Size to power of 2,
+ -- but not less than a storage unit in any case (normally
-- this means it will be byte addressable).
- if Is_Scalar_Type (U_Ent) then
+ -- For all other types, nothing else to do, we leave Esize
+ -- (object size) unset, the back end will set it from the
+ -- size and alignment in an appropriate manner.
+
+ if Is_Elementary_Type (U_Ent) then
if Size <= System_Storage_Unit then
Init_Esize (U_Ent, System_Storage_Unit);
elsif Size <= 16 then
@@ -2363,15 +2367,9 @@
Set_Esize (U_Ent, (Size + 63) / 64 * 64);
end if;
- -- For all other types, object size = value size. The
- -- backend will adjust as needed.
-
- else
- Set_Esize (U_Ent, Size);
+ Alignment_Check_For_Esize_Change (U_Ent);
end if;
- Alignment_Check_For_Esize_Change (U_Ent);
-
-- For objects, set Esize only
else
@@ -3591,7 +3589,7 @@
Lbit := Lbit + UI_From_Int (SSU) * Posit;
if Has_Size_Clause (Rectype)
- and then Esize (Rectype) <= Lbit
+ and then RM_Size (Rectype) <= Lbit
then
Error_Msg_N
("bit number out of range of specified size",
@@ -6008,7 +6006,7 @@
-- Check bit position out of range of specified size
if Has_Size_Clause (Rectype)
- and then Esize (Rectype) <= Lbit
+ and then RM_Size (Rectype) <= Lbit
then
Error_Msg_N
("bit number out of range of specified size",
Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c (revision 177274)
+++ gcc-interface/decl.c (working copy)
@@ -406,8 +406,6 @@
if (esize > max_esize)
esize = max_esize;
}
- else
- esize = LONG_LONG_TYPE_SIZE;
}
switch (kind)
@@ -2773,7 +2771,7 @@
? -1
: (Known_Alignment (gnat_entity)
|| (Strict_Alignment (gnat_entity)
- && Known_Static_Esize (gnat_entity)))
+ && Known_RM_Size (gnat_entity)))
? -2
: 0;
bool has_discr = Has_Discriminants (gnat_entity);
@@ -2824,8 +2822,9 @@
/* If both a size and rep clause was specified, put the size in
the record type now so that it can get the proper mode. */
- if (has_rep && Known_Esize (gnat_entity))
- TYPE_SIZE (gnu_type) = UI_To_gnu (Esize (gnat_entity), sizetype);
+ if (has_rep && Known_RM_Size (gnat_entity))
+ TYPE_SIZE (gnu_type)
+ = UI_To_gnu (RM_Size (gnat_entity), bitsizetype);
/* Always set the alignment here so that it can be used to
set the mode, if it is making the alignment stricter. If
@@ -2842,9 +2841,9 @@
type size instead of the RM size (see validate_size). Cap the
alignment, lest it causes this type size to become too large. */
else if (Strict_Alignment (gnat_entity)
- && Known_Static_Esize (gnat_entity))
+ && Known_RM_Size (gnat_entity))
{
- unsigned int raw_size = UI_To_Int (Esize (gnat_entity));
+ unsigned int raw_size = UI_To_Int (RM_Size (gnat_entity));
unsigned int raw_align = raw_size & -raw_size;
if (raw_align < BIGGEST_ALIGNMENT)
TYPE_ALIGN (gnu_type) = raw_align;
@@ -4583,9 +4582,13 @@
confirming or we don't handle it properly (if the low bound is
non-constant). */
if (!gnu_size && kind != E_String_Literal_Subtype)
- gnu_size = validate_size (Esize (gnat_entity), gnu_type, gnat_entity,
- TYPE_DECL, false,
- Has_Size_Clause (gnat_entity));
+ {
+ Uint gnat_size = Known_Esize (gnat_entity)
+ ? Esize (gnat_entity) : RM_Size (gnat_entity);
+ gnu_size
+ = validate_size (gnat_size, gnu_type, gnat_entity, TYPE_DECL,
+ false, Has_Size_Clause (gnat_entity));
+ }
/* If a size was specified, see if we can make a new type of that size
by rearranging the type, for example from a fat to a thin pointer. */
@@ -6771,7 +6774,7 @@
/* If a size is specified, use it. Otherwise, if the record type is packed,
use the official RM size. See "Handling of Type'Size Values" in Einfo
for further details. */
- if (Known_Static_Esize (gnat_field))
+ if (Known_Esize (gnat_field))
gnu_size = validate_size (Esize (gnat_field), gnu_field_type,
gnat_field, FIELD_DECL, false, true);
else if (packed == 1)
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-08-04 9:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-04 9:10 [Ada] Improve support of size and alignment clauses Arnaud Charlet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).