aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/layout.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/layout.adb')
-rw-r--r--gcc/ada/layout.adb129
1 files changed, 93 insertions, 36 deletions
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index ad80849..e69386c 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2020, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2021, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -23,19 +23,23 @@
-- --
------------------------------------------------------------------------------
-with Atree; use Atree;
-with Debug; use Debug;
-with Einfo; use Einfo;
-with Errout; use Errout;
-with Opt; use Opt;
-with Sem_Aux; use Sem_Aux;
-with Sem_Ch13; use Sem_Ch13;
-with Sem_Eval; use Sem_Eval;
-with Sem_Util; use Sem_Util;
-with Sinfo; use Sinfo;
-with Snames; use Snames;
-with Ttypes; use Ttypes;
-with Uintp; use Uintp;
+with Atree; use Atree;
+with Debug; use Debug;
+with Einfo; use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
+with Errout; use Errout;
+with Opt; use Opt;
+with Sem_Aux; use Sem_Aux;
+with Sem_Ch13; use Sem_Ch13;
+with Sem_Eval; use Sem_Eval;
+with Sem_Util; use Sem_Util;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Utils; use Sinfo.Utils;
+with Snames; use Snames;
+with Ttypes; use Ttypes;
+with Uintp; use Uintp;
package body Layout is
@@ -73,7 +77,7 @@ package body Layout is
begin
-- Nothing to do if size unknown
- if Unknown_Esize (E) then
+ if not Known_Esize (E) then
return;
end if;
@@ -115,7 +119,7 @@ package body Layout is
-- Now we have the size set, it must be a multiple of the alignment
-- nothing more we can do here if the alignment is unknown here.
- if Unknown_Alignment (E) then
+ if not Known_Alignment (E) then
return;
end if;
@@ -235,8 +239,8 @@ package body Layout is
Desig_Type : Entity_Id;
begin
- -- For string literal types, for now, kill the size always, this is
- -- because gigi does not like or need the size to be set ???
+ -- For string literal types, kill the size always, because gigi does not
+ -- like or need the size to be set.
if Ekind (E) = E_String_Literal_Subtype then
Set_Esize (E, Uint_0);
@@ -266,15 +270,15 @@ package body Layout is
Desig_Type := Non_Limited_View (Designated_Type (E));
end if;
- -- If Esize already set (e.g. by a size clause), then nothing further
- -- to be done here.
+ -- If Esize already set (e.g. by a size or value size clause), then
+ -- nothing further to be done here.
if Known_Esize (E) then
null;
- -- Access to subprogram is a strange beast, and we let the backend
- -- figure out what is needed (it may be some kind of fat pointer,
- -- including the static link for example.
+ -- Access to protected subprogram is a strange beast, and we let the
+ -- backend figure out what is needed (it may be some kind of fat
+ -- pointer, including the static link for example).
elsif Is_Access_Protected_Subprogram_Type (E) then
null;
@@ -368,7 +372,7 @@ package body Layout is
if not Known_Esize (E) then
declare
- S : Int := 8;
+ S : Pos := 8;
begin
loop
@@ -381,7 +385,7 @@ package body Layout is
-- If the RM_Size is greater than System_Max_Integer_Size
-- (happens only when strange values are specified by the
-- user), then Esize is simply a copy of RM_Size, it will
- -- be further refined later on).
+ -- be further refined later on.
elsif S = System_Max_Integer_Size then
Set_Esize (E, RM_Size (E));
@@ -400,7 +404,7 @@ package body Layout is
-- it now to a copy of the Esize if the Esize is set.
else
- if Known_Esize (E) and then Unknown_RM_Size (E) then
+ if Known_Esize (E) and then not Known_RM_Size (E) then
Set_RM_Size (E, Esize (E));
end if;
end if;
@@ -421,15 +425,15 @@ package body Layout is
PAT : constant Entity_Id := Packed_Array_Impl_Type (E);
begin
- if Unknown_Esize (E) then
+ if not Known_Esize (E) then
Set_Esize (E, Esize (PAT));
end if;
- if Unknown_RM_Size (E) then
+ if not Known_RM_Size (E) then
Set_RM_Size (E, RM_Size (PAT));
end if;
- if Unknown_Alignment (E) then
+ if not Known_Alignment (E) and then Known_Alignment (PAT) then
Set_Alignment (E, Alignment (PAT));
end if;
end;
@@ -442,13 +446,13 @@ package body Layout is
-- gave up because, in this case, the object size is not a multiple
-- of the alignment and, therefore, cannot be the component size.
- if Ekind (E) = E_Array_Type and then Unknown_Component_Size (E) then
+ if Ekind (E) = E_Array_Type and then not Known_Component_Size (E) then
declare
CT : constant Entity_Id := Component_Type (E);
begin
-- For some reason, access types can cause trouble, So let's
- -- just do this for scalar types ???
+ -- just do this for scalar types.
if Present (CT)
and then Is_Scalar_Type (CT)
@@ -474,7 +478,7 @@ package body Layout is
if Is_Array_Type (E)
and then not Is_Packed (E)
- and then Unknown_Alignment (E)
+ and then not Known_Alignment (E)
and then Known_Alignment (Component_Type (E))
and then Known_Static_Component_Size (E)
and then Known_Static_Esize (Component_Type (E))
@@ -483,6 +487,59 @@ package body Layout is
then
Set_Alignment (E, Alignment (Component_Type (E)));
end if;
+
+ -- If packing was requested, the one-dimensional array is constrained
+ -- with static bounds, the component size was set explicitly, and
+ -- the alignment is known, we can set (if not set explicitly) the
+ -- RM_Size and the Esize of the array type, as RM_Size is equal to
+ -- (arr'length * arr'component_size) and Esize is the same value
+ -- rounded to the next multiple of arr'alignment. This is not
+ -- applicable to packed arrays that are implemented specially
+ -- in GNAT, i.e. when Packed_Array_Impl_Type is set.
+
+ if Is_Array_Type (E)
+ and then Present (First_Index (E)) -- Skip types in error
+ and then Number_Dimensions (E) = 1
+ and then not Present (Packed_Array_Impl_Type (E))
+ and then Has_Pragma_Pack (E)
+ and then Is_Constrained (E)
+ and then Compile_Time_Known_Bounds (E)
+ and then Known_Component_Size (E)
+ and then Known_Alignment (E)
+ then
+ declare
+ Abits : constant Int := UI_To_Int (Alignment (E)) * SSU;
+ Lo, Hi : Node_Id;
+ Siz : Uint;
+
+ begin
+ Get_Index_Bounds (First_Index (E), Lo, Hi);
+
+ -- Even if the bounds are known at compile time, they could
+ -- have been replaced by an error node. Check each bound
+ -- explicitly.
+
+ if Compile_Time_Known_Value (Lo)
+ and then Compile_Time_Known_Value (Hi)
+ then
+ Siz := (Expr_Value (Hi) - Expr_Value (Lo) + 1)
+ * Component_Size (E);
+
+ -- Do not overwrite a different value of 'Size specified
+ -- explicitly by the user. In that case, also do not set
+ -- Esize.
+
+ if not Known_RM_Size (E) or else RM_Size (E) = Siz then
+ Set_RM_Size (E, Siz);
+
+ if not Known_Esize (E) then
+ Siz := ((Siz + (Abits - 1)) / Abits) * Abits;
+ Set_Esize (E, Siz);
+ end if;
+ end if;
+ end if;
+ end;
+ end if;
end if;
-- Even if the backend performs the layout, we still do a little in
@@ -519,7 +576,7 @@ package body Layout is
-- arrays when passed to subprogram parameters (see special test
-- in Exp_Ch6.Expand_Actuals).
- if not Is_Packed (E) and then Unknown_Alignment (E) then
+ if not Is_Packed (E) and then not Known_Alignment (E) then
if Known_Static_Component_Size (E)
and then Component_Size (E) = 1
then
@@ -691,7 +748,7 @@ package body Layout is
if Known_Static_Esize (E) then
Siz := Esize (E);
- elsif Unknown_Esize (E) and then Known_Static_RM_Size (E) then
+ elsif not Known_Esize (E) and then Known_Static_RM_Size (E) then
Siz := RM_Size (E);
else
return;
@@ -796,7 +853,7 @@ package body Layout is
if Calign > Align
and then
- (Unknown_Esize (Comp)
+ (not Known_Esize (Comp)
or else (Known_Static_Esize (Comp)
and then
Esize (Comp) = Calign * SSU))
@@ -963,7 +1020,7 @@ package body Layout is
-- If alignment is currently not set, then we can safely set it to
-- this new calculated value.
- if Unknown_Alignment (E) then
+ if not Known_Alignment (E) then
Init_Alignment (E, A);
-- Cases where we have inherited an alignment