sem_ch3.adb, [...]: Remove references to Frontend_Layout_On_Target and remaining...
authorArnaud Charlet <charlet@adacore.com>
Fri, 8 Sep 2017 09:46:42 +0000 (09:46 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Fri, 8 Sep 2017 09:46:42 +0000 (11:46 +0200)
2017-09-08  Arnaud Charlet  <charlet@adacore.com>

* sem_ch3.adb, layout.adb, layout.ads, exp_attr.adb, debug.adb,
exp_pakd.adb, sem_prag.adb, gnat1drv.adb, targparm.adb, targparm.ads,
repinfo.adb, exp_ch6.adb, exp_aggr.adb, sem_eval.adb, sem_ch13.adb,
exp_ch3.adb: Remove references to Frontend_Layout_On_Target and
remaining references to AAMP_On_Target.

From-SVN: r251877

17 files changed:
gcc/ada/ChangeLog
gcc/ada/debug.adb
gcc/ada/exp_aggr.adb
gcc/ada/exp_attr.adb
gcc/ada/exp_ch3.adb
gcc/ada/exp_ch6.adb
gcc/ada/exp_pakd.adb
gcc/ada/gnat1drv.adb
gcc/ada/layout.adb
gcc/ada/layout.ads
gcc/ada/repinfo.adb
gcc/ada/sem_ch13.adb
gcc/ada/sem_ch3.adb
gcc/ada/sem_eval.adb
gcc/ada/sem_prag.adb
gcc/ada/targparm.adb
gcc/ada/targparm.ads

index fc0f2caca19b7fb63f17038ddf80a99dcdce0b9b..5ce59b4df030f8f5d98759e22267dd6751872bc3 100644 (file)
@@ -1,3 +1,11 @@
+2017-09-08  Arnaud Charlet  <charlet@adacore.com>
+
+       * sem_ch3.adb, layout.adb, layout.ads, exp_attr.adb, debug.adb,
+       exp_pakd.adb, sem_prag.adb, gnat1drv.adb, targparm.adb, targparm.ads,
+       repinfo.adb, exp_ch6.adb, exp_aggr.adb, sem_eval.adb, sem_ch13.adb,
+       exp_ch3.adb: Remove references to Frontend_Layout_On_Target and
+       remaining references to AAMP_On_Target.
+
 2017-09-08  Ed Schonberg  <schonberg@adacore.com>
 
        * style.adb: Fix typo.
index 6b740ff5cef6a645811016861c16fec1cabae87a..f5a7e25e33955e795cba5ce34e5026bcba5a7486 100644 (file)
@@ -69,7 +69,7 @@ package body Debug is
    --  dC   Output debugging information on check suppression
    --  dD   Delete elaboration checks in inner level routines
    --  dE   Apply elaboration checks to predefined units
-   --  dF   Front end data layout enabled
+   --  dF
    --  dG   Generate all warnings including those normally suppressed
    --  dH   Hold (kill) call to gigi
    --  dI   Inhibit internal name numbering in gnatG listing
@@ -383,10 +383,6 @@ package body Debug is
    --  dE   Apply compile time elaboration checking for with relations between
    --       predefined units. Normally no checks are made.
 
-   --  dF   Front end data layout enabled. Normally front end data layout
-   --       is only enabled if the target parameter Backend_Layout is False.
-   --       This debugging switch enables it unconditionally.
-
    --  dG   Generate all warnings. Normally Errout suppresses warnings on
    --       units that are not part of the main extended source, and also
    --       suppresses warnings on instantiations in the main extended
index 55fdde5b899cfa8f3ed297f70419928941f27122..3610ed63ead9849c175fdb999f50d7bfa28ce08d 100644 (file)
@@ -59,7 +59,6 @@ with Sinfo;    use Sinfo;
 with Snames;   use Snames;
 with Stand;    use Stand;
 with Stringt;  use Stringt;
-with Targparm; use Targparm;
 with Tbuild;   use Tbuild;
 with Uintp;    use Uintp;
 
@@ -6262,7 +6261,6 @@ package body Exp_Aggr is
          --  then we could go into an infinite recursion.
 
          if (In_Place_Assign_OK_For_Declaration or else Maybe_In_Place_OK)
-           and then not AAMP_On_Target
            and then not CodePeer_Mode
            and then not Modify_Tree_For_C
            and then not Possible_Bit_Aligned_Component (Target)
index 99a24e7139d5987004ddfaed36aad6ceaed328ac..76b99e89c91924b1efb792690ea23d9f4ba956ea 100644 (file)
@@ -62,7 +62,6 @@ with Sinfo;    use Sinfo;
 with Snames;   use Snames;
 with Stand;    use Stand;
 with Stringt;  use Stringt;
-with Targparm; use Targparm;
 with Tbuild;   use Tbuild;
 with Ttypes;   use Ttypes;
 with Uintp;    use Uintp;
@@ -8233,7 +8232,6 @@ package body Exp_Attr is
       function Is_GCC_Target return Boolean is
       begin
          return not CodePeer_Mode
-           and then not AAMP_On_Target
            and then not Modify_Tree_For_C;
       end Is_GCC_Target;
 
@@ -8243,7 +8241,7 @@ package body Exp_Attr is
       --  Machine and Model can be expanded by the GCC and AAMP back ends only
 
       if Id = Attribute_Machine or else Id = Attribute_Model then
-         return Is_GCC_Target or else AAMP_On_Target;
+         return Is_GCC_Target;
 
       --  Remaining cases handled by all back ends are Rounding and Truncation
       --  when appearing as the operand of a conversion to some integer type.
index 6ed0f0feffa61be8d2a1c6be90693269c30cf348..e5519613f0dd506fa59394218778186d937a3c80 100644 (file)
@@ -67,7 +67,6 @@ with Sem_Util; use Sem_Util;
 with Sinfo;    use Sinfo;
 with Stand;    use Stand;
 with Snames;   use Snames;
-with Targparm; use Targparm;
 with Tbuild;   use Tbuild;
 with Ttypes;   use Ttypes;
 with Validsw;  use Validsw;
@@ -957,10 +956,6 @@ package body Exp_Ch3 is
          --  label all components of that variant with the function's name.
          --  We only Generate a discriminant-checking function when the
          --  variant is not empty, to prevent the creation of dead code.
-         --  The exception to that is when Frontend_Layout_On_Target is set,
-         --  because the variant record size function generated in package
-         --  Layout needs to generate calls to all discriminant-checking
-         --  functions, including those for empty variants.
 
          Discr_Name := Entity (Name (Variant_Part_Node));
          Variant := First_Non_Pragma (Variants (Variant_Part_Node));
@@ -968,9 +963,7 @@ package body Exp_Ch3 is
          while Present (Variant) loop
             Component_List_Node := Component_List (Variant);
 
-            if not Null_Present (Component_List_Node)
-              or else Frontend_Layout_On_Target
-            then
+            if not Null_Present (Component_List_Node) then
                Func_Id := Build_Dcheck_Function (Discr_Name, Variant);
 
                Decl :=
index 28227653d4480d81b8810d38385b159469fdacb2..423de144bbc0378a0a860e4c1f40359cfe132bcf 100644 (file)
@@ -70,7 +70,6 @@ with Sem_Util;  use Sem_Util;
 with Sinfo;     use Sinfo;
 with Snames;    use Snames;
 with Stand;     use Stand;
-with Targparm;  use Targparm;
 with Tbuild;    use Tbuild;
 with Uintp;     use Uintp;
 with Validsw;   use Validsw;
@@ -1757,19 +1756,10 @@ package body Exp_Ch6 is
 
          if Is_By_Reference_Type (Etype (Formal)) then
 
-            --  If the front-end does not perform full type layout, the actual
-            --  may in fact be properly aligned but there is not enough front-
-            --  end information to determine this. In that case gigi will emit
-            --  an error if a copy is not legal, or generate the proper code.
-            --  For other backends we report the error now.
-
-            --  Seems wrong to be issuing an error in the expander, since it
-            --  will be missed in -gnatc mode ???
-
-            if Frontend_Layout_On_Target then
-               Error_Msg_N
-                 ("misaligned actual cannot be passed by reference", Actual);
-            end if;
+            --  The actual may in fact be properly aligned but there is not
+            --  enough front-end information to determine this. In that case
+            --  gigi will emit an error if a copy is not legal, or generate
+            --  the proper code.
 
             return False;
 
index 0ec3ef4481409b9d9cc494623fe61e3d551dda5c..77a44aa76bb263466afc3d9059b376c36f8752c0 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2017, 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- --
index e6fc897de55fb5ba0269260ac33a1c7afc814ab3..8a974c9f0b98686e8d380cace99f989a667462d7 100644 (file)
@@ -560,13 +560,13 @@ procedure Gnat1drv is
          Atree.Num_Extension_Nodes := Atree.Num_Extension_Nodes + 1;
       end if;
 
-      --  Disable static allocation of dispatch tables if -gnatd.t or if layout
-      --  is enabled. The front end's layout phase currently treats types that
-      --  have discriminant-dependent arrays as not being static even when a
+      --  Disable static allocation of dispatch tables if -gnatd.t is enabled.
+      --  The front end's layout phase currently treats types that have
+      --  discriminant-dependent arrays as not being static even when a
       --  discriminant constraint on the type is static, and this leads to
       --  problems with subtypes of type Ada.Tags.Dispatch_Table_Wrapper. ???
 
-      if Debug_Flag_Dot_T or else Frontend_Layout_On_Target then
+      if Debug_Flag_Dot_T then
          Static_Dispatch_Tables := False;
       end if;
 
@@ -576,12 +576,6 @@ procedure Gnat1drv is
          Ttypes.Bytes_Big_Endian := not Ttypes.Bytes_Big_Endian;
       end if;
 
-      --  Activate front-end layout if debug flag -gnatdF is set
-
-      if Debug_Flag_FF then
-         Targparm.Frontend_Layout_On_Target := True;
-      end if;
-
       --  Set and check exception mechanism. This is only meaningful when
       --  compiling, and in particular not meaningful for special modes used
       --  for program analysis rather than compilation: ASIS mode, CodePeer
@@ -966,10 +960,11 @@ procedure Gnat1drv is
       --  Validate independence pragmas (again using values annotated by the
       --  back end for component layout where possible) but only for non-GCC
       --  back ends, as this is done a priori for GCC back ends.
-
-      if AAMP_On_Target then
-         Sem_Ch13.Validate_Independence;
-      end if;
+      --  ??? We use to test for AAMP_On_Target which is now gone, consider
+      --
+      --  if AAMP_On_Target then
+      --     Sem_Ch13.Validate_Independence;
+      --  end if;
    end Post_Compilation_Validation_Checks;
 
    --  Local variables
@@ -1421,7 +1416,6 @@ begin
         and then
           (not (Back_Annotate_Rep_Info or Generate_SCIL or GNATprove_Mode)
             or else Main_Unit_Kind = N_Subunit
-            or else Frontend_Layout_On_Target
             or else ASIS_GNSA_Mode)
       then
          Post_Compilation_Validation_Checks;
index 577cf0403d998ba999a816174adb42bc7f4197c1..34c5b5d0f9a7a1831a226e97ddb6770f4e44017d 100644 (file)
 ------------------------------------------------------------------------------
 
 with Atree;    use Atree;
-with Checks;   use Checks;
 with Debug;    use Debug;
 with Einfo;    use Einfo;
 with Errout;   use Errout;
-with Exp_Ch3;  use Exp_Ch3;
-with Exp_Util; use Exp_Util;
-with Namet;    use Namet;
-with Nlists;   use Nlists;
-with Nmake;    use Nmake;
 with Opt;      use Opt;
-with Repinfo;  use Repinfo;
-with Sem;      use Sem;
 with Sem_Aux;  use Sem_Aux;
-with Sem_Case; use Sem_Case;
 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 Stand;    use Stand;
-with Targparm; use Targparm;
-with Tbuild;   use Tbuild;
 with Ttypes;   use Ttypes;
 with Uintp;    use Uintp;
 
@@ -58,2349 +46,186 @@ package body Layout is
    SSU : constant Int := Ttypes.System_Storage_Unit;
    --  Short hand for System_Storage_Unit
 
-   Vname : constant Name_Id := Name_uV;
-   --  Formal parameter name used for functions generated for size offset
-   --  values that depend on the discriminant. All such functions have the
-   --  following form:
-   --
-   --     function xxx (V : vtyp) return Unsigned is
-   --     begin
-   --        return ... expression involving V.discrim
-   --     end xxx;
-
-   -----------------------
-   -- Local Subprograms --
-   -----------------------
-
-   function Assoc_Add
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id;
-   --  This is like Make_Op_Add except that it optimizes some cases knowing
-   --  that associative rearrangement is allowed for constant folding if one
-   --  of the operands is a compile time known value.
-
-   function Assoc_Multiply
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id;
-   --  This is like Make_Op_Multiply except that it optimizes some cases
-   --  knowing that associative rearrangement is allowed for constant folding
-   --  if one of the operands is a compile time known value
-
-   function Assoc_Subtract
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id;
-   --  This is like Make_Op_Subtract except that it optimizes some cases
-   --  knowing that associative rearrangement is allowed for constant folding
-   --  if one of the operands is a compile time known value
-
-   function Bits_To_SU (N : Node_Id) return Node_Id;
-   --  This is used when we cross the boundary from static sizes in bits to
-   --  dynamic sizes in storage units. If the argument N is anything other
-   --  than an integer literal, it is returned unchanged, but if it is an
-   --  integer literal, then it is taken as a size in bits, and is replaced
-   --  by the corresponding size in storage units.
-
-   function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id;
-   --  Given expressions for the low bound (Lo) and the high bound (Hi),
-   --  Build an expression for the value hi-lo+1, converted to type
-   --  Standard.Unsigned. Takes care of the case where the operands
-   --  are of an enumeration type (so that the subtraction cannot be
-   --  done directly) by applying the Pos operator to Hi/Lo first.
-
-   procedure Compute_Size_Depends_On_Discriminant (E : Entity_Id);
-   --  Given an array type or an array subtype E, compute whether its size
-   --  depends on the value of one or more discriminants and set the flag
-   --  Size_Depends_On_Discriminant accordingly. This need not be called
-   --  in front end layout mode since it does the computation on its own.
-
-   function Expr_From_SO_Ref
-     (Loc  : Source_Ptr;
-      D    : SO_Ref;
-      Comp : Entity_Id := Empty) return Node_Id;
-   --  Given a value D from a size or offset field, return an expression
-   --  representing the value stored. If the value is known at compile time,
-   --  then an N_Integer_Literal is returned with the appropriate value. If
-   --  the value references a constant entity, then an N_Identifier node
-   --  referencing this entity is returned. If the value denotes a size
-   --  function, then returns a call node denoting the given function, with
-   --  a single actual parameter that either refers to the parameter V of
-   --  an enclosing size function (if Comp is Empty or its type doesn't match
-   --  the function's formal), or else is a selected component V.c when Comp
-   --  denotes a component c whose type matches that of the function formal.
-   --  The Loc value is used for the Sloc value of constructed notes.
-
-   function SO_Ref_From_Expr
-     (Expr      : Node_Id;
-      Ins_Type  : Entity_Id;
-      Vtype     : Entity_Id := Empty;
-      Make_Func : Boolean   := False) return Dynamic_SO_Ref;
-   --  This routine is used in the case where a size/offset value is dynamic
-   --  and is represented by the expression Expr. SO_Ref_From_Expr checks if
-   --  the Expr contains a reference to the identifier V, and if so builds
-   --  a function depending on discriminants of the formal parameter V which
-   --  is of type Vtype. Otherwise, if the parameter Make_Func is True, then
-   --  Expr will be encapsulated in a parameterless function; if Make_Func is
-   --  False, then a constant entity with the value Expr is built. The result
-   --  is a Dynamic_SO_Ref to the created entity. Note that Vtype can be
-   --  omitted if Expr does not contain any reference to V, the created entity.
-   --  The declaration created is inserted in the freeze actions of Ins_Type,
-   --  which also supplies the Sloc for created nodes. This function also takes
-   --  care of making sure that the expression is properly analyzed and
-   --  resolved (which may not be the case yet if we build the expression
-   --  in this unit).
-
-   function Get_Max_SU_Size (E : Entity_Id) return Node_Id;
-   --  E is an array type or subtype that has at least one index bound that
-   --  is the value of a record discriminant. For such an array, the function
-   --  computes an expression that yields the maximum possible size of the
-   --  array in storage units. The result is not defined for any other type,
-   --  or for arrays that do not depend on discriminants, and it is a fatal
-   --  error to call this unless Size_Depends_On_Discriminant (E) is True.
-
-   procedure Layout_Array_Type (E : Entity_Id);
-   --  Front-end layout of non-bit-packed array type or subtype
-
-   procedure Layout_Record_Type (E : Entity_Id);
-   --  Front-end layout of record type
-
-   procedure Rewrite_Integer (N : Node_Id; V : Uint);
-   --  Rewrite node N with an integer literal whose value is V. The Sloc for
-   --  the new node is taken from N, and the type of the literal is set to a
-   --  copy of the type of N on entry.
-
-   procedure Set_And_Check_Static_Size
-     (E      : Entity_Id;
-      Esiz   : SO_Ref;
-      RM_Siz : SO_Ref);
-   --  This procedure is called to check explicit given sizes (possibly stored
-   --  in the Esize and RM_Size fields of E) against computed Object_Size
-   --  (Esiz) and Value_Size (RM_Siz) values. Appropriate errors and warnings
-   --  are posted if specified sizes are inconsistent with specified sizes. On
-   --  return, Esize and RM_Size fields of E are set (either from previously
-   --  given values, or from the newly computed values, as appropriate).
-
-   procedure Set_Composite_Alignment (E : Entity_Id);
-   --  This procedure is called for record types and subtypes, and also for
-   --  atomic array types and subtypes. If no alignment is set, and the size
-   --  is 2 or 4 (or 8 if the word size is 8), then the alignment is set to
-   --  match the size.
-
-   ----------------------------
-   -- Adjust_Esize_Alignment --
-   ----------------------------
-
-   procedure Adjust_Esize_Alignment (E : Entity_Id) is
-      Abits     : Int;
-      Esize_Set : Boolean;
-
-   begin
-      --  Nothing to do if size unknown
-
-      if Unknown_Esize (E) then
-         return;
-      end if;
-
-      --  Determine if size is constrained by an attribute definition clause
-      --  which must be obeyed. If so, we cannot increase the size in this
-      --  routine.
-
-      --  For a type, the issue is whether an object size clause has been set.
-      --  A normal size clause constrains only the value size (RM_Size)
-
-      if Is_Type (E) then
-         Esize_Set := Has_Object_Size_Clause (E);
-
-      --  For an object, the issue is whether a size clause is present
-
-      else
-         Esize_Set := Has_Size_Clause (E);
-      end if;
-
-      --  If size is known it must be a multiple of the storage unit size
-
-      if Esize (E) mod SSU /= 0 then
-
-         --  If not, and size specified, then give error
-
-         if Esize_Set then
-            Error_Msg_NE
-              ("size for& not a multiple of storage unit size",
-               Size_Clause (E), E);
-            return;
-
-         --  Otherwise bump up size to a storage unit boundary
-
-         else
-            Set_Esize (E, (Esize (E) + SSU - 1) / SSU * SSU);
-         end if;
-      end if;
-
-      --  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
-         return;
-      end if;
-
-      --  At this point both the Esize and Alignment are known, so we need
-      --  to make sure they are consistent.
-
-      Abits := UI_To_Int (Alignment (E)) * SSU;
-
-      if Esize (E) mod Abits = 0 then
-         return;
-      end if;
-
-      --  Here we have a situation where the Esize is not a multiple of the
-      --  alignment. We must either increase Esize or reduce the alignment to
-      --  correct this situation.
-
-      --  The case in which we can decrease the alignment is where the
-      --  alignment was not set by an alignment clause, and the type in
-      --  question is a discrete type, where it is definitely safe to reduce
-      --  the alignment. For example:
-
-      --    t : integer range 1 .. 2;
-      --    for t'size use 8;
-
-      --  In this situation, the initial alignment of t is 4, copied from
-      --  the Integer base type, but it is safe to reduce it to 1 at this
-      --  stage, since we will only be loading a single storage unit.
-
-      if Is_Discrete_Type (Etype (E)) and then not Has_Alignment_Clause (E)
-      then
-         loop
-            Abits := Abits / 2;
-            exit when Esize (E) mod Abits = 0;
-         end loop;
-
-         Init_Alignment (E, Abits / SSU);
-         return;
-      end if;
-
-      --  Now the only possible approach left is to increase the Esize but we
-      --  can't do that if the size was set by a specific clause.
-
-      if Esize_Set then
-         Error_Msg_NE
-           ("size for& is not a multiple of alignment",
-            Size_Clause (E), E);
-
-      --  Otherwise we can indeed increase the size to a multiple of alignment
-
-      else
-         Set_Esize (E, ((Esize (E) + (Abits - 1)) / Abits) * Abits);
-      end if;
-   end Adjust_Esize_Alignment;
-
-   ---------------
-   -- Assoc_Add --
-   ---------------
-
-   function Assoc_Add
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id
-   is
-      L : Node_Id;
-      R : Uint;
-
-   begin
-      --  Case of right operand is a constant
-
-      if Compile_Time_Known_Value (Right_Opnd) then
-         L := Left_Opnd;
-         R := Expr_Value (Right_Opnd);
-
-      --  Case of left operand is a constant
-
-      elsif Compile_Time_Known_Value (Left_Opnd) then
-         L := Right_Opnd;
-         R := Expr_Value (Left_Opnd);
-
-      --  Neither operand is a constant, do the addition with no optimization
-
-      else
-         return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
-      end if;
-
-      --  Case of left operand is an addition
-
-      if Nkind (L) = N_Op_Add then
-
-         --  (C1 + E) + C2 = (C1 + C2) + E
-
-         if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Left_Opnd (L),
-               Expr_Value (Sinfo.Left_Opnd (L)) + R);
-            return L;
-
-         --  (E + C1) + C2 = E + (C1 + C2)
-
-         elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Right_Opnd (L),
-               Expr_Value (Sinfo.Right_Opnd (L)) + R);
-            return L;
-         end if;
-
-      --  Case of left operand is a subtraction
-
-      elsif Nkind (L) = N_Op_Subtract then
-
-         --  (C1 - E) + C2 = (C1 + C2) - E
-
-         if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Left_Opnd (L),
-               Expr_Value (Sinfo.Left_Opnd (L)) + R);
-            return L;
-
-         --  (E - C1) + C2 = E - (C1 - C2)
-
-         --  If the type is unsigned then only do the optimization if C1 >= C2,
-         --  to avoid creating a negative literal that can't be used with the
-         --  unsigned type.
-
-         elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L))
-           and then (not Is_Unsigned_Type (Etype (Sinfo.Right_Opnd (L)))
-                      or else Expr_Value (Sinfo.Right_Opnd (L)) >= R)
-         then
-            Rewrite_Integer
-              (Sinfo.Right_Opnd (L),
-               Expr_Value (Sinfo.Right_Opnd (L)) - R);
-            return L;
-         end if;
-      end if;
-
-      --  Not optimizable, do the addition
-
-      return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
-   end Assoc_Add;
-
-   --------------------
-   -- Assoc_Multiply --
-   --------------------
-
-   function Assoc_Multiply
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id
-   is
-      L : Node_Id;
-      R : Uint;
-
-   begin
-      --  Case of right operand is a constant
-
-      if Compile_Time_Known_Value (Right_Opnd) then
-         L := Left_Opnd;
-         R := Expr_Value (Right_Opnd);
-
-      --  Case of left operand is a constant
-
-      elsif Compile_Time_Known_Value (Left_Opnd) then
-         L := Right_Opnd;
-         R := Expr_Value (Left_Opnd);
-
-      --  Neither operand is a constant, do the multiply with no optimization
-
-      else
-         return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
-      end if;
-
-      --  Case of left operand is an multiplication
-
-      if Nkind (L) = N_Op_Multiply then
-
-         --  (C1 * E) * C2 = (C1 * C2) + E
-
-         if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Left_Opnd (L),
-               Expr_Value (Sinfo.Left_Opnd (L)) * R);
-            return L;
-
-         --  (E * C1) * C2 = E * (C1 * C2)
-
-         elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Right_Opnd (L),
-               Expr_Value (Sinfo.Right_Opnd (L)) * R);
-            return L;
-         end if;
-      end if;
-
-      --  Not optimizable, do the multiplication
-
-      return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
-   end Assoc_Multiply;
-
-   --------------------
-   -- Assoc_Subtract --
-   --------------------
-
-   function Assoc_Subtract
-     (Loc        : Source_Ptr;
-      Left_Opnd  : Node_Id;
-      Right_Opnd : Node_Id) return Node_Id
-   is
-      L : Node_Id;
-      R : Uint;
-
-   begin
-      --  Case of right operand is a constant
-
-      if Compile_Time_Known_Value (Right_Opnd) then
-         L := Left_Opnd;
-         R := Expr_Value (Right_Opnd);
-
-      --  Right operand is a constant, do the subtract with no optimization
-
-      else
-         return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
-      end if;
-
-      --  Case of left operand is an addition
-
-      if Nkind (L) = N_Op_Add then
-
-         --  (C1 + E) - C2 = (C1 - C2) + E
-
-         if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Left_Opnd (L),
-               Expr_Value (Sinfo.Left_Opnd (L)) - R);
-            return L;
-
-         --  (E + C1) - C2 = E + (C1 - C2)
-
-         elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Right_Opnd (L),
-               Expr_Value (Sinfo.Right_Opnd (L)) - R);
-            return L;
-         end if;
-
-      --  Case of left operand is a subtraction
-
-      elsif Nkind (L) = N_Op_Subtract then
-
-         --  (C1 - E) - C2 = (C1 - C2) + E
-
-         if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Left_Opnd (L),
-               Expr_Value (Sinfo.Left_Opnd (L)) + R);
-            return L;
-
-         --  (E - C1) - C2 = E - (C1 + C2)
-
-         elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
-            Rewrite_Integer
-              (Sinfo.Right_Opnd (L),
-               Expr_Value (Sinfo.Right_Opnd (L)) + R);
-            return L;
-         end if;
-      end if;
-
-      --  Not optimizable, do the subtraction
-
-      return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
-   end Assoc_Subtract;
-
-   ----------------
-   -- Bits_To_SU --
-   ----------------
-
-   function Bits_To_SU (N : Node_Id) return Node_Id is
-   begin
-      if Nkind (N) = N_Integer_Literal then
-         Set_Intval (N, (Intval (N) + (SSU - 1)) / SSU);
-      end if;
-
-      return N;
-   end Bits_To_SU;
-
-   --------------------
-   -- Compute_Length --
-   --------------------
-
-   function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id is
-      Loc    : constant Source_Ptr := Sloc (Lo);
-      Typ    : constant Entity_Id  := Etype (Lo);
-      Lo_Op  : Node_Id;
-      Hi_Op  : Node_Id;
-      Lo_Dim : Uint;
-      Hi_Dim : Uint;
-
-   begin
-      --  If the bounds are First and Last attributes for the same dimension
-      --  and both have prefixes that denotes the same entity, then we create
-      --  and return a Length attribute. This may allow the back end to
-      --  generate better code in cases where it already has the length.
-
-      if Nkind (Lo) = N_Attribute_Reference
-        and then Attribute_Name (Lo) = Name_First
-        and then Nkind (Hi) = N_Attribute_Reference
-        and then Attribute_Name (Hi) = Name_Last
-        and then Is_Entity_Name (Prefix (Lo))
-        and then Is_Entity_Name (Prefix (Hi))
-        and then Entity (Prefix (Lo)) = Entity (Prefix (Hi))
-      then
-         Lo_Dim := Uint_1;
-         Hi_Dim := Uint_1;
-
-         if Present (First (Expressions (Lo))) then
-            Lo_Dim := Expr_Value (First (Expressions (Lo)));
-         end if;
-
-         if Present (First (Expressions (Hi))) then
-            Hi_Dim := Expr_Value (First (Expressions (Hi)));
-         end if;
-
-         if Lo_Dim = Hi_Dim then
-            return
-              Make_Attribute_Reference (Loc,
-                Prefix         => New_Occurrence_Of
-                                    (Entity (Prefix (Lo)), Loc),
-                Attribute_Name => Name_Length,
-                Expressions    => New_List
-                                    (Make_Integer_Literal (Loc, Lo_Dim)));
-         end if;
-      end if;
-
-      Lo_Op := New_Copy_Tree (Lo);
-      Hi_Op := New_Copy_Tree (Hi);
-
-      --  If type is enumeration type, then use Pos attribute to convert
-      --  to integer type for which subtraction is a permitted operation.
-
-      if Is_Enumeration_Type (Typ) then
-         Lo_Op :=
-           Make_Attribute_Reference (Loc,
-             Prefix         => New_Occurrence_Of (Typ, Loc),
-             Attribute_Name => Name_Pos,
-             Expressions    => New_List (Lo_Op));
-
-         Hi_Op :=
-           Make_Attribute_Reference (Loc,
-             Prefix         => New_Occurrence_Of (Typ, Loc),
-             Attribute_Name => Name_Pos,
-             Expressions    => New_List (Hi_Op));
-      end if;
-
-      return
-        Assoc_Add (Loc,
-          Left_Opnd =>
-            Assoc_Subtract (Loc,
-              Left_Opnd  => Hi_Op,
-              Right_Opnd => Lo_Op),
-          Right_Opnd => Make_Integer_Literal (Loc, 1));
-   end Compute_Length;
-
-   ----------------------
-   -- Expr_From_SO_Ref --
-   ----------------------
-
-   function Expr_From_SO_Ref
-     (Loc  : Source_Ptr;
-      D    : SO_Ref;
-      Comp : Entity_Id := Empty) return Node_Id
-   is
-      Ent : Entity_Id;
-
-   begin
-      if Is_Dynamic_SO_Ref (D) then
-         Ent := Get_Dynamic_SO_Entity (D);
-
-         if Is_Discrim_SO_Function (Ent) then
-
-            --  If a component is passed in whose type matches the type of
-            --  the function formal, then select that component from the "V"
-            --  parameter rather than passing "V" directly.
-
-            if Present (Comp)
-               and then Base_Type (Etype (Comp)) =
-                        Base_Type (Etype (First_Formal (Ent)))
-            then
-               return
-                 Make_Function_Call (Loc,
-                   Name                   => New_Occurrence_Of (Ent, Loc),
-                   Parameter_Associations => New_List (
-                     Make_Selected_Component (Loc,
-                       Prefix        => Make_Identifier (Loc, Vname),
-                       Selector_Name => New_Occurrence_Of (Comp, Loc))));
-
-            else
-               return
-                 Make_Function_Call (Loc,
-                   Name                   => New_Occurrence_Of (Ent, Loc),
-                   Parameter_Associations => New_List (
-                     Make_Identifier (Loc, Vname)));
-            end if;
-
-         else
-            return New_Occurrence_Of (Ent, Loc);
-         end if;
-
-      else
-         return Make_Integer_Literal (Loc, D);
-      end if;
-   end Expr_From_SO_Ref;
-
-   ---------------------
-   -- Get_Max_SU_Size --
-   ---------------------
-
-   function Get_Max_SU_Size (E : Entity_Id) return Node_Id is
-      Loc  : constant Source_Ptr := Sloc (E);
-      Indx : Node_Id;
-      Ityp : Entity_Id;
-      Lo   : Node_Id;
-      Hi   : Node_Id;
-      S    : Uint;
-      Len  : Node_Id;
-
-      type Val_Status_Type is (Const, Dynamic);
-
-      type Val_Type (Status : Val_Status_Type := Const) is record
-         case Status is
-            when Const   => Val : Uint;
-            when Dynamic => Nod : Node_Id;
-         end case;
-      end record;
-      --  Shows the status of the value so far. Const means that the value is
-      --  constant, and Val is the current constant value. Dynamic means that
-      --  the value is dynamic, and in this case Nod is the Node_Id of the
-      --  expression to compute the value.
-
-      Size : Val_Type;
-      --  Calculated value so far if Size.Status = Const,
-      --  or expression value so far if Size.Status = Dynamic.
-
-      SU_Convert_Required : Boolean := False;
-      --  This is set to True if the final result must be converted from bits
-      --  to storage units (rounding up to a storage unit boundary).
-
-      -----------------------
-      -- Local Subprograms --
-      -----------------------
-
-      procedure Max_Discrim (N : in out Node_Id);
-      --  If the node N represents a discriminant, replace it by the maximum
-      --  value of the discriminant.
-
-      procedure Min_Discrim (N : in out Node_Id);
-      --  If the node N represents a discriminant, replace it by the minimum
-      --  value of the discriminant.
-
-      -----------------
-      -- Max_Discrim --
-      -----------------
-
-      procedure Max_Discrim (N : in out Node_Id) is
-      begin
-         if Nkind (N) = N_Identifier
-           and then Ekind (Entity (N)) = E_Discriminant
-         then
-            N := Type_High_Bound (Etype (N));
-         end if;
-      end Max_Discrim;
-
-      -----------------
-      -- Min_Discrim --
-      -----------------
-
-      procedure Min_Discrim (N : in out Node_Id) is
-      begin
-         if Nkind (N) = N_Identifier
-           and then Ekind (Entity (N)) = E_Discriminant
-         then
-            N := Type_Low_Bound (Etype (N));
-         end if;
-      end Min_Discrim;
-
-   --  Start of processing for Get_Max_SU_Size
-
-   begin
-      pragma Assert (Size_Depends_On_Discriminant (E));
-
-      --  Initialize status from component size
-
-      if Known_Static_Component_Size (E) then
-         Size := (Const, Component_Size (E));
-
-      else
-         Size := (Dynamic, Expr_From_SO_Ref (Loc, Component_Size (E)));
-      end if;
-
-      --  Loop through indexes
-
-      Indx := First_Index (E);
-      while Present (Indx) loop
-         Ityp := Etype (Indx);
-         Lo := Type_Low_Bound (Ityp);
-         Hi := Type_High_Bound (Ityp);
-
-         Min_Discrim (Lo);
-         Max_Discrim (Hi);
-
-         --  Value of the current subscript range is statically known
-
-         if Compile_Time_Known_Value (Lo)
-              and then
-            Compile_Time_Known_Value (Hi)
-         then
-            S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
-
-            --  If known flat bound, entire size of array is zero
-
-            if S <= 0 then
-               return Make_Integer_Literal (Loc, 0);
-            end if;
-
-            --  Current value is constant, evolve value
-
-            if Size.Status = Const then
-               Size.Val := Size.Val * S;
-
-            --  Current value is dynamic
-
-            else
-               --  An interesting little optimization, if we have a pending
-               --  conversion from bits to storage units, and the current
-               --  length is a multiple of the storage unit size, then we
-               --  can take the factor out here statically, avoiding some
-               --  extra dynamic computations at the end.
-
-               if SU_Convert_Required and then S mod SSU = 0 then
-                  S := S / SSU;
-                  SU_Convert_Required := False;
-               end if;
-
-               Size.Nod :=
-                 Assoc_Multiply (Loc,
-                   Left_Opnd  => Size.Nod,
-                   Right_Opnd =>
-                     Make_Integer_Literal (Loc, Intval => S));
-            end if;
-
-         --  Value of the current subscript range is dynamic
-
-         else
-            --  If the current size value is constant, then here is where we
-            --  make a transition to dynamic values, which are always stored
-            --  in storage units, However, we do not want to convert to SU's
-            --  too soon, consider the case of a packed array of single bits,
-            --  we want to do the SU conversion after computing the size in
-            --  this case.
-
-            if Size.Status = Const then
-
-               --  If the current value is a multiple of the storage unit,
-               --  then most certainly we can do the conversion now, simply
-               --  by dividing the current value by the storage unit value.
-               --  If this works, we set SU_Convert_Required to False.
-
-               if Size.Val mod SSU = 0 then
-
-                  Size :=
-                    (Dynamic, Make_Integer_Literal (Loc, Size.Val / SSU));
-                  SU_Convert_Required := False;
-
-               --  Otherwise, we go ahead and convert the value in bits, and
-               --  set SU_Convert_Required to True to ensure that the final
-               --  value is indeed properly converted.
-
-               else
-                  Size := (Dynamic, Make_Integer_Literal (Loc, Size.Val));
-                  SU_Convert_Required := True;
-               end if;
-            end if;
-
-            --  Length is hi-lo+1
-
-            Len := Compute_Length (Lo, Hi);
-
-            --  Check possible range of Len
-
-            declare
-               OK  : Boolean;
-               LLo : Uint;
-               LHi : Uint;
-               pragma Warnings (Off, LHi);
-
-            begin
-               Set_Parent (Len, E);
-               Determine_Range (Len, OK, LLo, LHi);
-
-               Len := Convert_To (Standard_Unsigned, Len);
-
-               --  If we cannot verify that range cannot be super-flat, we need
-               --  a max with zero, since length must be non-negative.
-
-               if not OK or else LLo < 0 then
-                  Len :=
-                    Make_Attribute_Reference (Loc,
-                      Prefix         =>
-                        New_Occurrence_Of (Standard_Unsigned, Loc),
-                      Attribute_Name => Name_Max,
-                      Expressions    => New_List (
-                        Make_Integer_Literal (Loc, 0),
-                        Len));
-               end if;
-            end;
-         end if;
-
-         Next_Index (Indx);
-      end loop;
-
-      --  Here after processing all bounds to set sizes. If the value is a
-      --  constant, then it is bits, so we convert to storage units.
-
-      if Size.Status = Const then
-         return Bits_To_SU (Make_Integer_Literal (Loc, Size.Val));
-
-      --  Case where the value is dynamic
-
-      else
-         --  Do convert from bits to SU's if needed
-
-         if SU_Convert_Required then
-
-            --  The expression required is (Size.Nod + SU - 1) / SU
-
-            Size.Nod :=
-              Make_Op_Divide (Loc,
-                Left_Opnd =>
-                  Make_Op_Add (Loc,
-                    Left_Opnd  => Size.Nod,
-                    Right_Opnd => Make_Integer_Literal (Loc, SSU - 1)),
-                Right_Opnd => Make_Integer_Literal (Loc, SSU));
-         end if;
-
-         return Size.Nod;
-      end if;
-   end Get_Max_SU_Size;
-
-   -----------------------
-   -- Layout_Array_Type --
-   -----------------------
-
-   procedure Layout_Array_Type (E : Entity_Id) is
-      Loc  : constant Source_Ptr := Sloc (E);
-      Ctyp : constant Entity_Id  := Component_Type (E);
-      Indx : Node_Id;
-      Ityp : Entity_Id;
-      Lo   : Node_Id;
-      Hi   : Node_Id;
-      S    : Uint;
-      Len  : Node_Id;
-
-      Insert_Typ : Entity_Id;
-      --  This is the type with which any generated constants or functions
-      --  will be associated (i.e. inserted into the freeze actions). This
-      --  is normally the type being laid out. The exception occurs when
-      --  we are laying out Itype's which are local to a record type, and
-      --  whose scope is this record type. Such types do not have freeze
-      --  nodes (because we have no place to put them).
-
-      ------------------------------------
-      -- How An Array Type is Laid Out --
-      ------------------------------------
-
-      --  Here is what goes on. We need to multiply the component size of the
-      --  array (which has already been set) by the length of each of the
-      --  indexes. If all these values are known at compile time, then the
-      --  resulting size of the array is the appropriate constant value.
-
-      --  If the component size or at least one bound is dynamic (but no
-      --  discriminants are present), then the size will be computed as an
-      --  expression that calculates the proper size.
-
-      --  If there is at least one discriminant bound, then the size is also
-      --  computed as an expression, but this expression contains discriminant
-      --  values which are obtained by selecting from a function parameter, and
-      --  the size is given by a function that is passed the variant record in
-      --  question, and whose body is the expression.
-
-      type Val_Status_Type is (Const, Dynamic, Discrim);
-
-      type Val_Type (Status : Val_Status_Type := Const) is record
-         case Status is
-            when Const =>
-               Val : Uint;
-               --  Calculated value so far if Val_Status = Const
-
-            when Discrim
-               | Dynamic
-            =>
-               Nod : Node_Id;
-               --  Expression value so far if Val_Status /= Const
-         end case;
-      end record;
-      --  Records the value or expression computed so far. Const means that
-      --  the value is constant, and Val is the current constant value.
-      --  Dynamic means that the value is dynamic, and in this case Nod is
-      --  the Node_Id of the expression to compute the value, and Discrim
-      --  means that at least one bound is a discriminant, in which case Nod
-      --  is the expression so far (which will be the body of the function).
-
-      Size : Val_Type;
-      --  Value of size computed so far. See comments above
-
-      Vtyp : Entity_Id := Empty;
-      --  Variant record type for the formal parameter of the discriminant
-      --  function V if Status = Discrim.
-
-      SU_Convert_Required : Boolean := False;
-      --  This is set to True if the final result must be converted from
-      --  bits to storage units (rounding up to a storage unit boundary).
-
-      Storage_Divisor : Uint := UI_From_Int (SSU);
-      --  This is the amount that a nonstatic computed size will be divided
-      --  by to convert it from bits to storage units. This is normally
-      --  equal to SSU, but can be reduced in the case of packed components
-      --  that fit evenly into a storage unit.
-
-      Make_Size_Function : Boolean := False;
-      --  Indicates whether to request that SO_Ref_From_Expr should
-      --  encapsulate the array size expression in a function.
-
-      procedure Discrimify (N : in out Node_Id);
-      --  If N represents a discriminant, then the Size.Status is set to
-      --  Discrim, and Vtyp is set. The parameter N is replaced with the
-      --  proper expression to extract the discriminant value from V.
-
-      ----------------
-      -- Discrimify --
-      ----------------
-
-      procedure Discrimify (N : in out Node_Id) is
-         Decl : Node_Id;
-         Typ  : Entity_Id;
-
-      begin
-         if Nkind (N) = N_Identifier
-           and then Ekind (Entity (N)) = E_Discriminant
-         then
-            Set_Size_Depends_On_Discriminant (E);
-
-            if Size.Status /= Discrim then
-               Decl := Parent (Parent (Entity (N)));
-               Size := (Discrim, Size.Nod);
-               Vtyp := Defining_Identifier (Decl);
-            end if;
-
-            Typ := Etype (N);
-
-            N :=
-              Make_Selected_Component (Loc,
-                Prefix        => Make_Identifier (Loc, Vname),
-                Selector_Name => New_Occurrence_Of (Entity (N), Loc));
-
-            --  Set the Etype attributes of the selected name and its prefix.
-            --  Analyze_And_Resolve can't be called here because the Vname
-            --  entity denoted by the prefix will not yet exist (it's created
-            --  by SO_Ref_From_Expr, called at the end of Layout_Array_Type).
-
-            Set_Etype (Prefix (N), Vtyp);
-            Set_Etype (N, Typ);
-         end if;
-      end Discrimify;
-
-   --  Start of processing for Layout_Array_Type
-
-   begin
-      --  Default alignment is component alignment
-
-      if Unknown_Alignment (E) then
-         Set_Alignment (E, Alignment (Ctyp));
-      end if;
-
-      --  Calculate proper type for insertions
-
-      if Is_Record_Type (Underlying_Type (Scope (E))) then
-         Insert_Typ := Underlying_Type (Scope (E));
-      else
-         Insert_Typ := E;
-      end if;
-
-      --  If the component type is a generic formal type then there's no point
-      --  in determining a size for the array type.
-
-      if Is_Generic_Type (Ctyp) then
-         return;
-      end if;
-
-      --  Deal with component size if base type
-
-      if Ekind (E) = E_Array_Type then
-
-         --  Cannot do anything if Esize of component type unknown
-
-         if Unknown_Esize (Ctyp) then
-            return;
-         end if;
-
-         --  Set component size if not set already
-
-         if Unknown_Component_Size (E) then
-            Set_Component_Size (E, Esize (Ctyp));
-         end if;
-      end if;
-
-      --  (RM 13.3 (48)) says that the size of an unconstrained array
-      --  is implementation defined. We choose to leave it as Unknown
-      --  here, and the actual behavior is determined by the back end.
-
-      if not Is_Constrained (E) then
-         return;
-      end if;
-
-      --  Initialize status from component size
-
-      if Known_Static_Component_Size (E) then
-         Size := (Const, Component_Size (E));
-
-      else
-         Size := (Dynamic, Expr_From_SO_Ref (Loc, Component_Size (E)));
-      end if;
-
-      --  Loop to process array indexes
-
-      Indx := First_Index (E);
-      while Present (Indx) loop
-         Ityp := Etype (Indx);
-
-         --  If an index of the array is a generic formal type then there is
-         --  no point in determining a size for the array type.
-
-         if Is_Generic_Type (Ityp) then
-            return;
-         end if;
-
-         Lo := Type_Low_Bound (Ityp);
-         Hi := Type_High_Bound (Ityp);
-
-         --  Value of the current subscript range is statically known
-
-         if Compile_Time_Known_Value (Lo)
-              and then
-            Compile_Time_Known_Value (Hi)
-         then
-            S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
-
-            --  If known flat bound, entire size of array is zero
-
-            if S <= 0 then
-               Set_Esize (E, Uint_0);
-               Set_RM_Size (E, Uint_0);
-               return;
-            end if;
-
-            --  If constant, evolve value
-
-            if Size.Status = Const then
-               Size.Val := Size.Val * S;
-
-            --  Current value is dynamic
-
-            else
-               --  An interesting little optimization, if we have a pending
-               --  conversion from bits to storage units, and the current
-               --  length is a multiple of the storage unit size, then we
-               --  can take the factor out here statically, avoiding some
-               --  extra dynamic computations at the end.
-
-               if SU_Convert_Required and then S mod SSU = 0 then
-                  S := S / SSU;
-                  SU_Convert_Required := False;
-               end if;
-
-               --  Now go ahead and evolve the expression
-
-               Size.Nod :=
-                 Assoc_Multiply (Loc,
-                   Left_Opnd  => Size.Nod,
-                   Right_Opnd =>
-                     Make_Integer_Literal (Loc, Intval => S));
-            end if;
-
-         --  Value of the current subscript range is dynamic
-
-         else
-            --  If the current size value is constant, then here is where we
-            --  make a transition to dynamic values, which are always stored
-            --  in storage units, However, we do not want to convert to SU's
-            --  too soon, consider the case of a packed array of single bits,
-            --  we want to do the SU conversion after computing the size in
-            --  this case.
-
-            if Size.Status = Const then
-
-               --  If the current value is a multiple of the storage unit,
-               --  then most certainly we can do the conversion now, simply
-               --  by dividing the current value by the storage unit value.
-               --  If this works, we set SU_Convert_Required to False.
-
-               if Size.Val mod SSU = 0 then
-                  Size :=
-                    (Dynamic, Make_Integer_Literal (Loc, Size.Val / SSU));
-                  SU_Convert_Required := False;
-
-               --  If the current value is a factor of the storage unit, then
-               --  we can use a value of one for the size and reduce the
-               --  strength of the later division.
-
-               elsif SSU mod Size.Val = 0 then
-                  Storage_Divisor := SSU / Size.Val;
-                  Size := (Dynamic, Make_Integer_Literal (Loc, Uint_1));
-                  SU_Convert_Required := True;
-
-               --  Otherwise, we go ahead and convert the value in bits, and
-               --  set SU_Convert_Required to True to ensure that the final
-               --  value is indeed properly converted.
-
-               else
-                  Size := (Dynamic, Make_Integer_Literal (Loc, Size.Val));
-                  SU_Convert_Required := True;
-               end if;
-            end if;
-
-            Discrimify (Lo);
-            Discrimify (Hi);
-
-            --  Length is hi-lo+1
-
-            Len := Compute_Length (Lo, Hi);
-
-            --  If Len isn't a Length attribute, then its range needs to be
-            --  checked a possible Max with zero needs to be computed.
-
-            if Nkind (Len) /= N_Attribute_Reference
-              or else Attribute_Name (Len) /= Name_Length
-            then
-               declare
-                  OK  : Boolean;
-                  LLo : Uint;
-                  LHi : Uint;
-
-               begin
-                  --  Check possible range of Len
-
-                  Set_Parent (Len, E);
-                  Determine_Range (Len, OK, LLo, LHi);
-
-                  Len := Convert_To (Standard_Unsigned, Len);
-
-                  --  If range definitely flat or superflat, result size is 0
-
-                  if OK and then LHi <= 0 then
-                     Set_Esize (E, Uint_0);
-                     Set_RM_Size (E, Uint_0);
-                     return;
-                  end if;
-
-                  --  If we cannot verify that range cannot be super-flat, we
-                  --  need a max with zero, since length cannot be negative.
-
-                  if not OK or else LLo < 0 then
-                     Len :=
-                       Make_Attribute_Reference (Loc,
-                         Prefix         =>
-                           New_Occurrence_Of (Standard_Unsigned, Loc),
-                         Attribute_Name => Name_Max,
-                         Expressions    => New_List (
-                           Make_Integer_Literal (Loc, 0),
-                           Len));
-                  end if;
-               end;
-            end if;
-
-            --  At this stage, Len has the expression for the length
-
-            Size.Nod :=
-              Assoc_Multiply (Loc,
-                Left_Opnd  => Size.Nod,
-                Right_Opnd => Len);
-         end if;
-
-         Next_Index (Indx);
-      end loop;
-
-      --  Here after processing all bounds to set sizes. If the value is a
-      --  constant, then it is bits, and the only thing we need to do is to
-      --  check against explicit given size and do alignment adjust.
-
-      if Size.Status = Const then
-         Set_And_Check_Static_Size (E, Size.Val, Size.Val);
-         Adjust_Esize_Alignment (E);
-
-      --  Case where the value is dynamic
-
-      else
-         --  Do convert from bits to SU's if needed
-
-         if SU_Convert_Required then
-
-            --  The expression required is:
-            --    (Size.Nod + Storage_Divisor - 1) / Storage_Divisor
-
-            Size.Nod :=
-              Make_Op_Divide (Loc,
-                Left_Opnd =>
-                  Make_Op_Add (Loc,
-                    Left_Opnd  => Size.Nod,
-                    Right_Opnd => Make_Integer_Literal
-                                    (Loc, Storage_Divisor - 1)),
-                Right_Opnd => Make_Integer_Literal (Loc, Storage_Divisor));
-         end if;
-
-         --  If the array entity is not declared at the library level and its
-         --  not nested within a subprogram that is marked for inlining, then
-         --  we request that the size expression be encapsulated in a function.
-         --  Since this expression is not needed in most cases, we prefer not
-         --  to incur the overhead of the computation on calls to the enclosing
-         --  subprogram except for subprograms that require the size.
-
-         if not Is_Library_Level_Entity (E) then
-            Make_Size_Function := True;
-
-            declare
-               Parent_Subp : Entity_Id := Enclosing_Subprogram (E);
-
-            begin
-               while Present (Parent_Subp) loop
-                  if Is_Inlined (Parent_Subp) then
-                     Make_Size_Function := False;
-                     exit;
-                  end if;
-
-                  Parent_Subp := Enclosing_Subprogram (Parent_Subp);
-               end loop;
-            end;
-         end if;
-
-         --  Now set the dynamic size (the Value_Size is always the same as the
-         --  Object_Size for arrays whose length is dynamic).
-
-         --  ??? If Size.Status = Dynamic, Vtyp will not have been set.
-         --  The added initialization sets it to Empty now, but is this
-         --  correct?
-
-         Set_Esize
-           (E,
-            SO_Ref_From_Expr
-              (Size.Nod, Insert_Typ, Vtyp, Make_Func => Make_Size_Function));
-         Set_RM_Size (E, Esize (E));
-      end if;
-   end Layout_Array_Type;
-
-   ------------------------------------------
-   -- Compute_Size_Depends_On_Discriminant --
-   ------------------------------------------
-
-   procedure Compute_Size_Depends_On_Discriminant (E : Entity_Id) is
-      Indx : Node_Id;
-      Ityp : Entity_Id;
-      Lo   : Node_Id;
-      Hi   : Node_Id;
-      Res  : Boolean := False;
-
-   begin
-      --  Loop to process array indexes
-
-      Indx := First_Index (E);
-      while Present (Indx) loop
-         Ityp := Etype (Indx);
-
-         --  If an index of the array is a generic formal type then there is
-         --  no point in determining a size for the array type.
-
-         if Is_Generic_Type (Ityp) then
-            return;
-         end if;
-
-         Lo := Type_Low_Bound (Ityp);
-         Hi := Type_High_Bound (Ityp);
-
-         if (Nkind (Lo) = N_Identifier
-              and then Ekind (Entity (Lo)) = E_Discriminant)
-           or else
-            (Nkind (Hi) = N_Identifier
-              and then Ekind (Entity (Hi)) = E_Discriminant)
-         then
-            Res := True;
-         end if;
-
-         Next_Index (Indx);
-      end loop;
-
-      if Res then
-         Set_Size_Depends_On_Discriminant (E);
-      end if;
-   end Compute_Size_Depends_On_Discriminant;
-
-   -------------------
-   -- Layout_Object --
-   -------------------
-
-   procedure Layout_Object (E : Entity_Id) is
-      T : constant Entity_Id := Etype (E);
-
-   begin
-      --  Nothing to do if backend does layout
-
-      if not Frontend_Layout_On_Target then
-         return;
-      end if;
-
-      --  Set size if not set for object and known for type. Use the RM_Size if
-      --  that is known for the type and Esize is not.
-
-      if Unknown_Esize (E) then
-         if Known_Esize (T) then
-            Set_Esize (E, Esize (T));
-
-         elsif Known_RM_Size (T) then
-            Set_Esize (E, RM_Size (T));
-         end if;
-      end if;
-
-      --  Set alignment from type if unknown and type alignment known
-
-      if Unknown_Alignment (E) and then Known_Alignment (T) then
-         Set_Alignment (E, Alignment (T));
-      end if;
-
-      --  Make sure size and alignment are consistent
-
-      Adjust_Esize_Alignment (E);
-
-      --  Final adjustment, if we don't know the alignment, and the Esize was
-      --  not set by an explicit Object_Size attribute clause, then we reset
-      --  the Esize to unknown, since we really don't know it.
-
-      if Unknown_Alignment (E) and then not Has_Size_Clause (E) then
-         Set_Esize (E, Uint_0);
-      end if;
-   end Layout_Object;
-
-   ------------------------
-   -- Layout_Record_Type --
-   ------------------------
-
-   procedure Layout_Record_Type (E : Entity_Id) is
-      Loc  : constant Source_Ptr := Sloc (E);
-      Decl : Node_Id;
-
-      Comp : Entity_Id;
-      --  Current component being laid out
-
-      Prev_Comp : Entity_Id;
-      --  Previous laid out component
-
-      procedure Get_Next_Component_Location
-        (Prev_Comp  : Entity_Id;
-         Align      : Uint;
-         New_Npos   : out SO_Ref;
-         New_Fbit   : out SO_Ref;
-         New_NPMax  : out SO_Ref;
-         Force_SU   : Boolean);
-      --  Given the previous component in Prev_Comp, which is already laid
-      --  out, and the alignment of the following component, lays out the
-      --  following component, and returns its starting position in New_Npos
-      --  (Normalized_Position value), New_Fbit (Normalized_First_Bit value),
-      --  and New_NPMax (Normalized_Position_Max value). If Prev_Comp is empty
-      --  (no previous component is present), then New_Npos, New_Fbit and
-      --  New_NPMax are all set to zero on return. This procedure is also
-      --  used to compute the size of a record or variant by giving it the
-      --  last component, and the record alignment. Force_SU is used to force
-      --  the new component location to be aligned on a storage unit boundary,
-      --  even in a packed record, False means that the new position does not
-      --  need to be bumped to a storage unit boundary, True means a storage
-      --  unit boundary is always required.
-
-      procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id);
-      --  Lays out component Comp, given Prev_Comp, the previously laid-out
-      --  component (Prev_Comp = Empty if no components laid out yet). The
-      --  alignment of the record itself is also updated if needed. Both
-      --  Comp and Prev_Comp can be either components or discriminants.
-
-      procedure Layout_Components
-        (From   : Entity_Id;
-         To     : Entity_Id;
-         Esiz   : out SO_Ref;
-         RM_Siz : out SO_Ref);
-      --  This procedure lays out the components of the given component list
-      --  which contains the components starting with From and ending with To.
-      --  The Next_Entity chain is used to traverse the components. On entry,
-      --  Prev_Comp is set to the component preceding the list, so that the
-      --  list is laid out after this component. Prev_Comp is set to Empty if
-      --  the component list is to be laid out starting at the start of the
-      --  record. On return, the components are all laid out, and Prev_Comp is
-      --  set to the last laid out component. On return, Esiz is set to the
-      --  resulting Object_Size value, which is the length of the record up
-      --  to and including the last laid out entity. For Esiz, the value is
-      --  adjusted to match the alignment of the record. RM_Siz is similarly
-      --  set to the resulting Value_Size value, which is the same length, but
-      --  not adjusted to meet the alignment. Note that in the case of variant
-      --  records, Esiz represents the maximum size.
-
-      procedure Layout_Non_Variant_Record;
-      --  Procedure called to lay out a non-variant record type or subtype
-
-      procedure Layout_Variant_Record;
-      --  Procedure called to lay out a variant record type. Decl is set to the
-      --  full type declaration for the variant record.
-
-      ---------------------------------
-      -- Get_Next_Component_Location --
-      ---------------------------------
-
-      procedure Get_Next_Component_Location
-        (Prev_Comp  : Entity_Id;
-         Align      : Uint;
-         New_Npos   : out SO_Ref;
-         New_Fbit   : out SO_Ref;
-         New_NPMax  : out SO_Ref;
-         Force_SU   : Boolean)
-      is
-      begin
-         --  No previous component, return zero position
-
-         if No (Prev_Comp) then
-            New_Npos  := Uint_0;
-            New_Fbit  := Uint_0;
-            New_NPMax := Uint_0;
-            return;
-         end if;
-
-         --  Here we have a previous component
-
-         declare
-            Loc       : constant Source_Ptr := Sloc (Prev_Comp);
-
-            Old_Npos  : constant SO_Ref := Normalized_Position     (Prev_Comp);
-            Old_Fbit  : constant SO_Ref := Normalized_First_Bit    (Prev_Comp);
-            Old_NPMax : constant SO_Ref := Normalized_Position_Max (Prev_Comp);
-            Old_Esiz  : constant SO_Ref := Esize                   (Prev_Comp);
-
-            Old_Maxsz : Node_Id;
-            --  Expression representing maximum size of previous component
-
-         begin
-            --  Case where previous field had a dynamic size
-
-            if Is_Dynamic_SO_Ref (Esize (Prev_Comp)) then
-
-               --  If the previous field had a dynamic length, then it is
-               --  required to occupy an integral number of storage units,
-               --  and start on a storage unit boundary. This means that
-               --  the Normalized_First_Bit value is zero in the previous
-               --  component, and the new value is also set to zero.
-
-               New_Fbit := Uint_0;
-
-               --  In this case, the new position is given by an expression
-               --  that is the sum of old normalized position and old size.
-
-               New_Npos :=
-                 SO_Ref_From_Expr
-                   (Assoc_Add (Loc,
-                      Left_Opnd  =>
-                        Expr_From_SO_Ref (Loc, Old_Npos),
-                      Right_Opnd =>
-                        Expr_From_SO_Ref (Loc, Old_Esiz, Prev_Comp)),
-                    Ins_Type => E,
-                    Vtype    => E);
-
-               --  Get maximum size of previous component
-
-               if Size_Depends_On_Discriminant (Etype (Prev_Comp)) then
-                  Old_Maxsz := Get_Max_SU_Size (Etype (Prev_Comp));
-               else
-                  Old_Maxsz := Expr_From_SO_Ref (Loc, Old_Esiz, Prev_Comp);
-               end if;
-
-               --  Now we can compute the new max position. If the max size
-               --  is static and the old position is static, then we can
-               --  compute the new position statically.
-
-               if Nkind (Old_Maxsz) = N_Integer_Literal
-                 and then Known_Static_Normalized_Position_Max (Prev_Comp)
-               then
-                  New_NPMax := Old_NPMax + Intval (Old_Maxsz);
-
-               --  Otherwise new max position is dynamic
-
-               else
-                  New_NPMax :=
-                    SO_Ref_From_Expr
-                      (Assoc_Add (Loc,
-                         Left_Opnd  => Expr_From_SO_Ref (Loc, Old_NPMax),
-                         Right_Opnd => Old_Maxsz),
-                       Ins_Type => E,
-                       Vtype    => E);
-               end if;
-
-            --  Previous field has known static Esize
-
-            else
-               New_Fbit := Old_Fbit + Old_Esiz;
-
-               --  Bump New_Fbit to storage unit boundary if required
-
-               if New_Fbit /= 0 and then Force_SU then
-                  New_Fbit := (New_Fbit + SSU - 1) / SSU * SSU;
-               end if;
-
-               --  If old normalized position is static, we can go ahead and
-               --  compute the new normalized position directly.
-
-               if Known_Static_Normalized_Position (Prev_Comp) then
-                  New_Npos := Old_Npos;
-
-                  if New_Fbit >= SSU then
-                     New_Npos := New_Npos + New_Fbit / SSU;
-                     New_Fbit := New_Fbit mod SSU;
-                  end if;
-
-                  --  Bump alignment if stricter than prev
-
-                  if Align > Alignment (Etype (Prev_Comp)) then
-                     New_Npos := (New_Npos + Align - 1) / Align * Align;
-                  end if;
-
-                  --  The max position is always equal to the position if
-                  --  the latter is static, since arrays depending on the
-                  --  values of discriminants never have static sizes.
-
-                  New_NPMax := New_Npos;
-                  return;
-
-               --  Case of old normalized position is dynamic
-
-               else
-                  --  If new bit position is within the current storage unit,
-                  --  we can just copy the old position as the result position
-                  --  (we have already set the new first bit value).
-
-                  if New_Fbit < SSU then
-                     New_Npos  := Old_Npos;
-                     New_NPMax := Old_NPMax;
-
-                  --  If new bit position is past the current storage unit, we
-                  --  need to generate a new dynamic value for the position
-                  --  ??? need to deal with alignment
-
-                  else
-                     New_Npos :=
-                       SO_Ref_From_Expr
-                         (Assoc_Add (Loc,
-                            Left_Opnd  => Expr_From_SO_Ref (Loc, Old_Npos),
-                            Right_Opnd =>
-                              Make_Integer_Literal (Loc,
-                                Intval => New_Fbit / SSU)),
-                          Ins_Type => E,
-                          Vtype    => E);
-
-                     New_NPMax :=
-                       SO_Ref_From_Expr
-                         (Assoc_Add (Loc,
-                            Left_Opnd  => Expr_From_SO_Ref (Loc, Old_NPMax),
-                            Right_Opnd =>
-                              Make_Integer_Literal (Loc,
-                                Intval => New_Fbit / SSU)),
-                            Ins_Type => E,
-                            Vtype    => E);
-                     New_Fbit := New_Fbit mod SSU;
-                  end if;
-               end if;
-            end if;
-         end;
-      end Get_Next_Component_Location;
-
-      ----------------------
-      -- Layout_Component --
-      ----------------------
-
-      procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id) is
-         Ctyp  : constant Entity_Id := Etype (Comp);
-         ORC   : constant Entity_Id := Original_Record_Component (Comp);
-         Npos  : SO_Ref;
-         Fbit  : SO_Ref;
-         NPMax : SO_Ref;
-         Forc  : Boolean;
-
-      begin
-         --  Increase alignment of record if necessary. Note that we do not
-         --  do this for packed records, which have an alignment of one by
-         --  default, or for records for which an explicit alignment was
-         --  specified with an alignment clause.
-
-         if not Is_Packed (E)
-           and then not Has_Alignment_Clause (E)
-           and then Alignment (Ctyp) > Alignment (E)
-         then
-            Set_Alignment (E, Alignment (Ctyp));
-         end if;
-
-         --  If original component set, then use same layout
-
-         if Present (ORC) and then ORC /= Comp then
-            Set_Normalized_Position     (Comp, Normalized_Position     (ORC));
-            Set_Normalized_First_Bit    (Comp, Normalized_First_Bit    (ORC));
-            Set_Normalized_Position_Max (Comp, Normalized_Position_Max (ORC));
-            Set_Component_Bit_Offset    (Comp, Component_Bit_Offset    (ORC));
-            Set_Esize                   (Comp, Esize                   (ORC));
-            return;
-         end if;
-
-         --  Parent field is always at start of record, this will overlap
-         --  the actual fields that are part of the parent, and that's fine
-
-         if Chars (Comp) = Name_uParent then
-            Set_Normalized_Position     (Comp, Uint_0);
-            Set_Normalized_First_Bit    (Comp, Uint_0);
-            Set_Normalized_Position_Max (Comp, Uint_0);
-            Set_Component_Bit_Offset    (Comp, Uint_0);
-            Set_Esize                   (Comp, Esize (Ctyp));
-            return;
-         end if;
-
-         --  Check case of type of component has a scope of the record we are
-         --  laying out. When this happens, the type in question is an Itype
-         --  that has not yet been laid out (that's because such types do not
-         --  get frozen in the normal manner, because there is no place for
-         --  the freeze nodes).
-
-         if Scope (Ctyp) = E then
-            Layout_Type (Ctyp);
-         end if;
-
-         --  If component already laid out, then we are done
-
-         if Known_Normalized_Position (Comp) then
-            return;
-         end if;
-
-         --  Set size of component from type. We use the Esize except in a
-         --  packed record, where we use the RM_Size (since that is what the
-         --  RM_Size value, as distinct from the Object_Size is useful for).
-
-         if Is_Packed (E) then
-            Set_Esize (Comp, RM_Size (Ctyp));
-         else
-            Set_Esize (Comp, Esize (Ctyp));
-         end if;
-
-         --  Compute the component position from the previous one. See if
-         --  current component requires being on a storage unit boundary.
-
-         --  If record is not packed, we always go to a storage unit boundary
-
-         if not Is_Packed (E) then
-            Forc := True;
-
-         --  Packed cases
-
-         else
-            --  Elementary types do not need SU boundary in packed record
-
-            if Is_Elementary_Type (Ctyp) then
-               Forc := False;
-
-            --  Packed array types with a modular packed array type do not
-            --  force a storage unit boundary (since the code generation
-            --  treats these as equivalent to the underlying modular type),
-
-            elsif Is_Array_Type (Ctyp)
-              and then Is_Bit_Packed_Array (Ctyp)
-              and then Is_Modular_Integer_Type (Packed_Array_Impl_Type (Ctyp))
-            then
-               Forc := False;
-
-            --  Record types with known length less than or equal to the length
-            --  of long long integer can also be unaligned, since they can be
-            --  treated as scalars.
-
-            elsif Is_Record_Type (Ctyp)
-              and then not Is_Dynamic_SO_Ref (Esize (Ctyp))
-              and then Esize (Ctyp) <= Esize (Standard_Long_Long_Integer)
-            then
-               Forc := False;
-
-            --  All other cases force a storage unit boundary, even when packed
-
-            else
-               Forc := True;
-            end if;
-         end if;
-
-         --  Now get the next component location
-
-         Get_Next_Component_Location
-           (Prev_Comp, Alignment (Ctyp), Npos, Fbit, NPMax, Forc);
-         Set_Normalized_Position     (Comp, Npos);
-         Set_Normalized_First_Bit    (Comp, Fbit);
-         Set_Normalized_Position_Max (Comp, NPMax);
-
-         --  Set Component_Bit_Offset in the static case
-
-         if Known_Static_Normalized_Position (Comp)
-           and then Known_Normalized_First_Bit (Comp)
-         then
-            Set_Component_Bit_Offset (Comp, SSU * Npos + Fbit);
-         end if;
-      end Layout_Component;
-
-      -----------------------
-      -- Layout_Components --
-      -----------------------
-
-      procedure Layout_Components
-        (From   : Entity_Id;
-         To     : Entity_Id;
-         Esiz   : out SO_Ref;
-         RM_Siz : out SO_Ref)
-      is
-         End_Npos  : SO_Ref;
-         End_Fbit  : SO_Ref;
-         End_NPMax : SO_Ref;
-
-      begin
-         --  Only lay out components if there are some to lay out
-
-         if Present (From) then
-
-            --  Lay out components with no component clauses
-
-            Comp := From;
-            loop
-               if Ekind (Comp) = E_Component
-                 or else Ekind (Comp) = E_Discriminant
-               then
-                  --  The compatibility of component clauses with composite
-                  --  types isn't checked in Sem_Ch13, so we check it here.
-
-                  if Present (Component_Clause (Comp)) then
-                     if Is_Composite_Type (Etype (Comp))
-                       and then Esize (Comp) < RM_Size (Etype (Comp))
-                     then
-                        Error_Msg_Uint_1 := RM_Size (Etype (Comp));
-                        Error_Msg_NE
-                          ("size for & too small, minimum allowed is ^",
-                           Component_Clause (Comp),
-                           Comp);
-                     end if;
-
-                  else
-                     Layout_Component (Comp, Prev_Comp);
-                     Prev_Comp := Comp;
-                  end if;
-               end if;
-
-               exit when Comp = To;
-               Next_Entity (Comp);
-            end loop;
-         end if;
-
-         --  Set size fields, both are zero if no components
-
-         if No (Prev_Comp) then
-            Esiz := Uint_0;
-            RM_Siz := Uint_0;
-
-            --  If record subtype with non-static discriminants, then we don't
-            --  know which variant will be the one which gets chosen. We don't
-            --  just want to set the maximum size from the base, because the
-            --  size should depend on the particular variant.
-
-            --  What we do is to use the RM_Size of the base type, which has
-            --  the necessary conditional computation of the size, using the
-            --  size information for the particular variant chosen. Records
-            --  with default discriminants for example have an Esize that is
-            --  set to the maximum of all variants, but that's not what we
-            --  want for a constrained subtype.
-
-         elsif Ekind (E) = E_Record_Subtype
-           and then not Has_Static_Discriminants (E)
-         then
-            declare
-               BT : constant Node_Id := Base_Type (E);
-            begin
-               Esiz   := RM_Size (BT);
-               RM_Siz := RM_Size (BT);
-               Set_Alignment (E, Alignment (BT));
-            end;
-
-         else
-            --  First the object size, for which we align past the last field
-            --  to the alignment of the record (the object size is required to
-            --  be a multiple of the alignment).
-
-            Get_Next_Component_Location
-              (Prev_Comp,
-               Alignment (E),
-               End_Npos,
-               End_Fbit,
-               End_NPMax,
-               Force_SU => True);
-
-            --  If the resulting normalized position is a dynamic reference,
-            --  then the size is dynamic, and is stored in storage units. In
-            --  this case, we set the RM_Size to the same value, it is simply
-            --  not worth distinguishing Esize and RM_Size values in the
-            --  dynamic case, since the RM has nothing to say about them.
-
-            --  Note that a size cannot have been given in this case, since
-            --  size specifications cannot be given for variable length types.
-
-            declare
-               Align : constant Uint := Alignment (E);
-
-            begin
-               if Is_Dynamic_SO_Ref (End_Npos) then
-                  RM_Siz := End_Npos;
-
-                  --  Set the Object_Size allowing for the alignment. In the
-                  --  dynamic case, we must do the actual runtime computation.
-                  --  We can skip this in the non-packed record case if the
-                  --  last component has a smaller alignment than the overall
-                  --  record alignment.
-
-                  if Is_Dynamic_SO_Ref (End_NPMax) then
-                     Esiz := End_NPMax;
-
-                     if Is_Packed (E)
-                       or else Alignment (Etype (Prev_Comp)) < Align
-                     then
-                        --  The expression we build is:
-                        --    (expr + align - 1) / align * align
-
-                        Esiz :=
-                          SO_Ref_From_Expr
-                            (Expr =>
-                               Make_Op_Multiply (Loc,
-                                 Left_Opnd =>
-                                   Make_Op_Divide (Loc,
-                                     Left_Opnd =>
-                                       Make_Op_Add (Loc,
-                                         Left_Opnd =>
-                                           Expr_From_SO_Ref (Loc, Esiz),
-                                         Right_Opnd =>
-                                           Make_Integer_Literal (Loc,
-                                             Intval => Align - 1)),
-                                     Right_Opnd =>
-                                       Make_Integer_Literal (Loc, Align)),
-                                 Right_Opnd =>
-                                   Make_Integer_Literal (Loc, Align)),
-                            Ins_Type => E,
-                            Vtype    => E);
-                     end if;
-
-                  --  Here Esiz is static, so we can adjust the alignment
-                  --  directly go give the required aligned value.
-
-                  else
-                     Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
-                  end if;
-
-               --  Case where computed size is static
-
-               else
-                  --  The ending size was computed in Npos in storage units,
-                  --  but the actual size is stored in bits, so adjust
-                  --  accordingly. We also adjust the size to match the
-                  --  alignment here.
-
-                  Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
-
-                  --  Compute the resulting Value_Size (RM_Size). For this
-                  --  purpose we do not force alignment of the record or
-                  --  storage size alignment of the result.
-
-                  Get_Next_Component_Location
-                    (Prev_Comp,
-                     Uint_0,
-                     End_Npos,
-                     End_Fbit,
-                     End_NPMax,
-                     Force_SU => False);
-
-                  RM_Siz := End_Npos * SSU + End_Fbit;
-                  Set_And_Check_Static_Size (E, Esiz, RM_Siz);
-               end if;
-            end;
-         end if;
-      end Layout_Components;
-
-      -------------------------------
-      -- Layout_Non_Variant_Record --
-      -------------------------------
-
-      procedure Layout_Non_Variant_Record is
-         Esiz   : SO_Ref;
-         RM_Siz : SO_Ref;
-      begin
-         Layout_Components (First_Entity (E), Last_Entity (E), Esiz, RM_Siz);
-         Set_Esize   (E, Esiz);
-         Set_RM_Size (E, RM_Siz);
-      end Layout_Non_Variant_Record;
-
-      ---------------------------
-      -- Layout_Variant_Record --
-      ---------------------------
-
-      procedure Layout_Variant_Record is
-         Tdef        : constant Node_Id := Type_Definition (Decl);
-         First_Discr : Entity_Id;
-         Last_Discr  : Entity_Id;
-         Esiz        : SO_Ref;
-
-         RM_Siz : SO_Ref;
-         pragma Warnings (Off, SO_Ref);
-
-         RM_Siz_Expr : Node_Id := Empty;
-         --  Expression for the evolving RM_Siz value. This is typically an if
-         --  expression which involves tests of discriminant values that are
-         --  formed as references to the entity V. At the end of scanning all
-         --  the components, a suitable function is constructed in which V is
-         --  the parameter.
-
-         -----------------------
-         -- Local Subprograms --
-         -----------------------
-
-         procedure Layout_Component_List
-           (Clist       : Node_Id;
-            Esiz        : out SO_Ref;
-            RM_Siz_Expr : out Node_Id);
-         --  Recursive procedure, called to lay out one component list Esiz
-         --  and RM_Siz_Expr are set to the Object_Size and Value_Size values
-         --  respectively representing the record size up to and including the
-         --  last component in the component list (including any variants in
-         --  this component list). RM_Siz_Expr is returned as an expression
-         --  which may in the general case involve some references to the
-         --  discriminants of the current record value, referenced by selecting
-         --  from the entity V.
-
-         ---------------------------
-         -- Layout_Component_List --
-         ---------------------------
-
-         procedure Layout_Component_List
-           (Clist       : Node_Id;
-            Esiz        : out SO_Ref;
-            RM_Siz_Expr : out Node_Id)
-         is
-            Citems  : constant List_Id := Component_Items (Clist);
-            Vpart   : constant Node_Id := Variant_Part (Clist);
-            Prv     : Node_Id;
-            Var     : Node_Id;
-            RM_Siz  : Uint;
-            RMS_Ent : Entity_Id;
-
-         begin
-            if Is_Non_Empty_List (Citems) then
-               Layout_Components
-                 (From   => Defining_Identifier (First (Citems)),
-                  To     => Defining_Identifier (Last  (Citems)),
-                  Esiz   => Esiz,
-                  RM_Siz => RM_Siz);
-            else
-               Layout_Components (Empty, Empty, Esiz, RM_Siz);
-            end if;
-
-            --  Case where no variants are present in the component list
-
-            if No (Vpart) then
-
-               --  The Esiz value has been correctly set by the call to
-               --  Layout_Components, so there is nothing more to be done.
-
-               --  For RM_Siz, we have an SO_Ref value, which we must convert
-               --  to an appropriate expression.
-
-               if Is_Static_SO_Ref (RM_Siz) then
-                  RM_Siz_Expr :=
-                    Make_Integer_Literal (Loc,
-                                          Intval => RM_Siz);
-
-               else
-                  RMS_Ent := Get_Dynamic_SO_Entity (RM_Siz);
-
-                  --  If the size is represented by a function, then we create
-                  --  an appropriate function call using V as the parameter to
-                  --  the call.
-
-                  if Is_Discrim_SO_Function (RMS_Ent) then
-                     RM_Siz_Expr :=
-                       Make_Function_Call (Loc,
-                         Name => New_Occurrence_Of (RMS_Ent, Loc),
-                         Parameter_Associations => New_List (
-                           Make_Identifier (Loc, Vname)));
-
-                  --  If the size is represented by a constant, then the
-                  --  expression we want is a reference to this constant
-
-                  else
-                     RM_Siz_Expr := New_Occurrence_Of (RMS_Ent, Loc);
-                  end if;
-               end if;
-
-            --  Case where variants are present in this component list
-
-            else
-               declare
-                  EsizV    : SO_Ref;
-                  RM_SizV  : Node_Id;
-                  Dchoice  : Node_Id;
-                  Discrim  : Node_Id;
-                  Dtest    : Node_Id;
-                  D_List   : List_Id;
-                  D_Entity : Entity_Id;
-
-               begin
-                  RM_Siz_Expr := Empty;
-                  Prv := Prev_Comp;
-
-                  Var := Last (Variants (Vpart));
-                  while Present (Var) loop
-                     Prev_Comp := Prv;
-                     Layout_Component_List
-                       (Component_List (Var), EsizV, RM_SizV);
-
-                     --  Set the Object_Size. If this is the first variant,
-                     --  we just set the size of this first variant.
-
-                     if Var = Last (Variants (Vpart)) then
-                        Esiz := EsizV;
-
-                     --  Otherwise the Object_Size is formed as a maximum
-                     --  of Esiz so far from previous variants, and the new
-                     --  Esiz value from the variant we just processed.
-
-                     --  If both values are static, we can just compute the
-                     --  maximum directly to save building junk nodes.
-
-                     elsif not Is_Dynamic_SO_Ref (Esiz)
-                       and then not Is_Dynamic_SO_Ref (EsizV)
-                     then
-                        Esiz := UI_Max (Esiz, EsizV);
-
-                     --  If either value is dynamic, then we have to generate
-                     --  an appropriate Standard_Unsigned'Max attribute call.
-                     --  If one of the values is static then it needs to be
-                     --  converted from bits to storage units to be compatible
-                     --  with the dynamic value.
-
-                     else
-                        if Is_Static_SO_Ref (Esiz) then
-                           Esiz := (Esiz + SSU - 1) / SSU;
-                        end if;
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
 
-                        if Is_Static_SO_Ref (EsizV) then
-                           EsizV := (EsizV + SSU - 1) / SSU;
-                        end if;
+   procedure Compute_Size_Depends_On_Discriminant (E : Entity_Id);
+   --  Given an array type or an array subtype E, compute whether its size
+   --  depends on the value of one or more discriminants and set the flag
+   --  Size_Depends_On_Discriminant accordingly. This need not be called
+   --  in front end layout mode since it does the computation on its own.
 
-                        Esiz :=
-                          SO_Ref_From_Expr
-                            (Make_Attribute_Reference (Loc,
-                               Attribute_Name => Name_Max,
-                               Prefix         =>
-                                 New_Occurrence_Of (Standard_Unsigned, Loc),
-                               Expressions => New_List (
-                                 Expr_From_SO_Ref (Loc, Esiz),
-                                 Expr_From_SO_Ref (Loc, EsizV))),
-                             Ins_Type => E,
-                             Vtype    => E);
-                     end if;
+   procedure Set_Composite_Alignment (E : Entity_Id);
+   --  This procedure is called for record types and subtypes, and also for
+   --  atomic array types and subtypes. If no alignment is set, and the size
+   --  is 2 or 4 (or 8 if the word size is 8), then the alignment is set to
+   --  match the size.
 
-                     --  Now deal with Value_Size (RM_Siz). We are aiming at
-                     --  an expression that looks like:
+   ----------------------------
+   -- Adjust_Esize_Alignment --
+   ----------------------------
 
-                     --    if      xxDx (V.disc) then rmsiz1
-                     --    else if xxDx (V.disc) then rmsiz2
-                     --    else ...
+   procedure Adjust_Esize_Alignment (E : Entity_Id) is
+      Abits     : Int;
+      Esize_Set : Boolean;
 
-                     --  Where rmsiz1, rmsiz2... are the RM_Siz values for the
-                     --  individual variants, and xxDx are the discriminant
-                     --  checking functions generated for the variant type.
+   begin
+      --  Nothing to do if size unknown
 
-                     --  If this is the first variant, we simply set the result
-                     --  as the expression. Note that this takes care of the
-                     --  others case.
+      if Unknown_Esize (E) then
+         return;
+      end if;
 
-                     if No (RM_Siz_Expr) then
+      --  Determine if size is constrained by an attribute definition clause
+      --  which must be obeyed. If so, we cannot increase the size in this
+      --  routine.
 
-                        --  If this is the only variant and the size is a
-                        --  literal, then use bit size as is, otherwise convert
-                        --  to storage units and continue to the next variant.
+      --  For a type, the issue is whether an object size clause has been set.
+      --  A normal size clause constrains only the value size (RM_Size)
 
-                        if No (Prev (Var))
-                          and then Nkind (RM_SizV) = N_Integer_Literal
-                        then
-                           RM_Siz_Expr := RM_SizV;
-                        else
-                           RM_Siz_Expr := Bits_To_SU (RM_SizV);
-                        end if;
+      if Is_Type (E) then
+         Esize_Set := Has_Object_Size_Clause (E);
 
-                     --  Otherwise construct the appropriate test
+      --  For an object, the issue is whether a size clause is present
 
-                     else
-                        --  The test to be used in general is a call to the
-                        --  discriminant checking function. However, it is
-                        --  definitely worth special casing the very common
-                        --  case where a single value is involved.
+      else
+         Esize_Set := Has_Size_Clause (E);
+      end if;
 
-                        Dchoice := First (Discrete_Choices (Var));
+      --  If size is known it must be a multiple of the storage unit size
 
-                        if No (Next (Dchoice))
-                          and then Nkind (Dchoice) /= N_Range
-                        then
-                           --  Discriminant to be tested
-
-                           Discrim :=
-                             Make_Selected_Component (Loc,
-                               Prefix        =>
-                                 Make_Identifier (Loc, Vname),
-                               Selector_Name =>
-                                 New_Occurrence_Of
-                                   (Entity (Name (Vpart)), Loc));
-
-                           Dtest :=
-                             Make_Op_Eq (Loc,
-                               Left_Opnd  => Discrim,
-                               Right_Opnd => New_Copy (Dchoice));
-
-                        --  Generate a call to the discriminant-checking
-                        --  function for the variant. Note that the result
-                        --  has to be complemented since the function returns
-                        --  False when the passed discriminant value matches.
-
-                        else
-                           --  The checking function takes all of the type's
-                           --  discriminants as parameters, so a list of all
-                           --  the selected discriminants must be constructed.
-
-                           D_List := New_List;
-                           D_Entity := First_Discriminant (E);
-                           while Present (D_Entity) loop
-                              Append_To (D_List,
-                                Make_Selected_Component (Loc,
-                                  Prefix        =>
-                                    Make_Identifier (Loc, Vname),
-                                  Selector_Name =>
-                                    New_Occurrence_Of (D_Entity, Loc)));
-
-                              D_Entity := Next_Discriminant (D_Entity);
-                           end loop;
-
-                           Dtest :=
-                             Make_Op_Not (Loc,
-                               Right_Opnd =>
-                                 Make_Function_Call (Loc,
-                                   Name =>
-                                     New_Occurrence_Of
-                                       (Dcheck_Function (Var), Loc),
-                                   Parameter_Associations =>
-                                     D_List));
-                        end if;
+      if Esize (E) mod SSU /= 0 then
 
-                        RM_Siz_Expr :=
-                          Make_If_Expression (Loc,
-                            Expressions =>
-                              New_List
-                                (Dtest, Bits_To_SU (RM_SizV), RM_Siz_Expr));
-                     end if;
+         --  If not, and size specified, then give error
 
-                     Prev (Var);
-                  end loop;
-               end;
-            end if;
-         end Layout_Component_List;
+         if Esize_Set then
+            Error_Msg_NE
+              ("size for& not a multiple of storage unit size",
+               Size_Clause (E), E);
+            return;
 
-         Others_Present : Boolean;
-         pragma Warnings (Off, Others_Present);
-         --  Indicates others present, not used in this case
+         --  Otherwise bump up size to a storage unit boundary
 
-         procedure Non_Static_Choice_Error (Choice : Node_Id);
-         --  Error routine invoked by the generic instantiation below when
-         --  the variant part has a nonstatic choice.
+         else
+            Set_Esize (E, (Esize (E) + SSU - 1) / SSU * SSU);
+         end if;
+      end if;
 
-         package Variant_Choices_Processing is new
-           Generic_Check_Choices
-             (Process_Empty_Choice      => No_OP,
-              Process_Non_Static_Choice => Non_Static_Choice_Error,
-              Process_Associated_Node   => No_OP);
-         use Variant_Choices_Processing;
+      --  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.
 
-         -----------------------------
-         -- Non_Static_Choice_Error --
-         -----------------------------
+      if Unknown_Alignment (E) then
+         return;
+      end if;
 
-         procedure Non_Static_Choice_Error (Choice : Node_Id) is
-         begin
-            Flag_Non_Static_Expr
-              ("choice given in case expression is not static!", Choice);
-         end Non_Static_Choice_Error;
+      --  At this point both the Esize and Alignment are known, so we need
+      --  to make sure they are consistent.
 
-      --  Start of processing for Layout_Variant_Record
+      Abits := UI_To_Int (Alignment (E)) * SSU;
 
-      begin
-         --  Call Check_Choices here to ensure that Others_Discrete_Choices
-         --  gets set on any 'others' choice before the discriminant-checking
-         --  functions are generated. Otherwise the function for the 'others'
-         --  alternative will unconditionally return True, causing discriminant
-         --  checks to fail. However, Check_Choices is now normally delayed
-         --  until the type's freeze entity is processed, due to requirements
-         --  coming from subtype predicates, so doing it at this point is
-         --  probably not right in general, but it's not clear how else to deal
-         --  with this situation. Perhaps we should only generate declarations
-         --  for the checking functions here, and somehow delay generation of
-         --  their bodies, but that would be a nontrivial change. ???
+      if Esize (E) mod Abits = 0 then
+         return;
+      end if;
 
-         declare
-            VP : constant Node_Id :=
-                   Variant_Part (Component_List (Type_Definition (Decl)));
-         begin
-            Check_Choices
-              (VP, Variants (VP), Etype (Name (VP)), Others_Present);
-         end;
+      --  Here we have a situation where the Esize is not a multiple of the
+      --  alignment. We must either increase Esize or reduce the alignment to
+      --  correct this situation.
 
-         --  We need the discriminant checking functions, since we generate
-         --  calls to these functions for the RM_Size expression, so make
-         --  sure that these functions have been constructed in time.
+      --  The case in which we can decrease the alignment is where the
+      --  alignment was not set by an alignment clause, and the type in
+      --  question is a discrete type, where it is definitely safe to reduce
+      --  the alignment. For example:
 
-         Build_Discr_Checking_Funcs (Decl);
+      --    t : integer range 1 .. 2;
+      --    for t'size use 8;
 
-         --  Lay out the discriminants
+      --  In this situation, the initial alignment of t is 4, copied from
+      --  the Integer base type, but it is safe to reduce it to 1 at this
+      --  stage, since we will only be loading a single storage unit.
 
-         First_Discr := First_Discriminant (E);
-         Last_Discr  := First_Discr;
-         while Present (Next_Discriminant (Last_Discr)) loop
-            Next_Discriminant (Last_Discr);
+      if Is_Discrete_Type (Etype (E)) and then not Has_Alignment_Clause (E)
+      then
+         loop
+            Abits := Abits / 2;
+            exit when Esize (E) mod Abits = 0;
          end loop;
 
-         Layout_Components
-           (From   => First_Discr,
-            To     => Last_Discr,
-            Esiz   => Esiz,
-            RM_Siz => RM_Siz);
-
-         --  Lay out the main component list (this will make recursive calls
-         --  to lay out all component lists nested within variants).
+         Init_Alignment (E, Abits / SSU);
+         return;
+      end if;
 
-         Layout_Component_List (Component_List (Tdef), Esiz, RM_Siz_Expr);
-         Set_Esize (E, Esiz);
+      --  Now the only possible approach left is to increase the Esize but we
+      --  can't do that if the size was set by a specific clause.
 
-         --  If the RM_Size is a literal, set its value
+      if Esize_Set then
+         Error_Msg_NE
+           ("size for& is not a multiple of alignment",
+            Size_Clause (E), E);
 
-         if Nkind (RM_Siz_Expr) = N_Integer_Literal then
-            Set_RM_Size (E, Intval (RM_Siz_Expr));
+      --  Otherwise we can indeed increase the size to a multiple of alignment
 
-         --  Otherwise we construct a dynamic SO_Ref
+      else
+         Set_Esize (E, ((Esize (E) + (Abits - 1)) / Abits) * Abits);
+      end if;
+   end Adjust_Esize_Alignment;
 
-         else
-            Set_RM_Size (E,
-              SO_Ref_From_Expr
-                (RM_Siz_Expr,
-                 Ins_Type => E,
-                 Vtype    => E));
-         end if;
-      end Layout_Variant_Record;
+   ------------------------------------------
+   -- Compute_Size_Depends_On_Discriminant --
+   ------------------------------------------
 
-   --  Start of processing for Layout_Record_Type
+   procedure Compute_Size_Depends_On_Discriminant (E : Entity_Id) is
+      Indx : Node_Id;
+      Ityp : Entity_Id;
+      Lo   : Node_Id;
+      Hi   : Node_Id;
+      Res  : Boolean := False;
 
    begin
-      --  If this is a cloned subtype, just copy the size fields from the
-      --  original, nothing else needs to be done in this case, since the
-      --  components themselves are all shared.
-
-      if Ekind_In (E, E_Record_Subtype, E_Class_Wide_Subtype)
-        and then Present (Cloned_Subtype (E))
-      then
-         Set_Esize     (E, Esize     (Cloned_Subtype (E)));
-         Set_RM_Size   (E, RM_Size   (Cloned_Subtype (E)));
-         Set_Alignment (E, Alignment (Cloned_Subtype (E)));
-
-      --  Another special case, class-wide types. The RM says that the size
-      --  of such types is implementation defined (RM 13.3(48)). What we do
-      --  here is to leave the fields set as unknown values, and the backend
-      --  determines the actual behavior.
-
-      elsif Ekind (E) = E_Class_Wide_Type then
-         null;
+      --  Loop to process array indexes
 
-      --  All other cases
+      Indx := First_Index (E);
+      while Present (Indx) loop
+         Ityp := Etype (Indx);
 
-      else
-         --  Initialize alignment conservatively to 1. This value will be
-         --  increased as necessary during processing of the record.
+         --  If an index of the array is a generic formal type then there is
+         --  no point in determining a size for the array type.
 
-         if Unknown_Alignment (E) then
-            Set_Alignment (E, Uint_1);
+         if Is_Generic_Type (Ityp) then
+            return;
          end if;
 
-         --  Initialize previous component. This is Empty unless there are
-         --  components which have already been laid out by component clauses.
-         --  If there are such components, we start our lay out of the
-         --  remaining components following the last such component.
-
-         Prev_Comp := Empty;
+         Lo := Type_Low_Bound (Ityp);
+         Hi := Type_High_Bound (Ityp);
 
-         Comp := First_Component_Or_Discriminant (E);
-         while Present (Comp) loop
-            if Present (Component_Clause (Comp)) then
-               if No (Prev_Comp)
-                 or else
-                   Component_Bit_Offset (Comp) >
-                   Component_Bit_Offset (Prev_Comp)
-               then
-                  Prev_Comp := Comp;
-               end if;
-            end if;
+         if (Nkind (Lo) = N_Identifier
+              and then Ekind (Entity (Lo)) = E_Discriminant)
+           or else
+            (Nkind (Hi) = N_Identifier
+              and then Ekind (Entity (Hi)) = E_Discriminant)
+         then
+            Res := True;
+         end if;
 
-            Next_Component_Or_Discriminant (Comp);
-         end loop;
+         Next_Index (Indx);
+      end loop;
 
-         --  We have two separate circuits, one for non-variant records and
-         --  one for variant records. For non-variant records, we simply go
-         --  through the list of components. This handles all the non-variant
-         --  cases including those cases of subtypes where there is no full
-         --  type declaration, so the tree cannot be used to drive the layout.
-         --  For variant records, we have to drive the layout from the tree
-         --  since we need to understand the variant structure in this case.
+      if Res then
+         Set_Size_Depends_On_Discriminant (E);
+      end if;
+   end Compute_Size_Depends_On_Discriminant;
 
-         if Present (Full_View (E)) then
-            Decl := Declaration_Node (Full_View (E));
-         else
-            Decl := Declaration_Node (E);
-         end if;
+   -------------------
+   -- Layout_Object --
+   -------------------
 
-         --  Scan all the components
+   procedure Layout_Object (E : Entity_Id) is
+      pragma Unreferenced (E);
+   begin
+      --  Nothing to do for now, assume backend does the layout
 
-         if Nkind (Decl) = N_Full_Type_Declaration
-           and then Has_Discriminants (E)
-           and then Nkind (Type_Definition (Decl)) = N_Record_Definition
-           and then Present (Component_List (Type_Definition (Decl)))
-           and then
-             Present (Variant_Part (Component_List (Type_Definition (Decl))))
-         then
-            Layout_Variant_Record;
-         else
-            Layout_Non_Variant_Record;
-         end if;
-      end if;
-   end Layout_Record_Type;
+      return;
+   end Layout_Object;
 
    -----------------
    -- Layout_Type --
@@ -2636,65 +461,54 @@ package body Layout is
          end if;
       end if;
 
-      --  Lay out array and record types if front end layout set
-
-      if Frontend_Layout_On_Target then
-         if Is_Array_Type (E) and then not Is_Bit_Packed_Array (E) then
-            Layout_Array_Type (E);
-         elsif Is_Record_Type (E) then
-            Layout_Record_Type (E);
-         end if;
-
-      --  Case of backend layout, we still do a little in the front end
+      --  Even if the backend performs the layout, we still do a little in
+      --  the front end
 
-      else
-         --  Processing for record types
+      --  Processing for record types
 
-         if Is_Record_Type (E) then
+      if Is_Record_Type (E) then
 
-            --  Special remaining processing for record types with a known
-            --  size of 16, 32, or 64 bits whose alignment is not yet set.
-            --  For these types, we set a corresponding alignment matching
-            --  the size if possible, or as large as possible if not.
+         --  Special remaining processing for record types with a known
+         --  size of 16, 32, or 64 bits whose alignment is not yet set.
+         --  For these types, we set a corresponding alignment matching
+         --  the size if possible, or as large as possible if not.
 
-            if Convention (E) = Convention_Ada and then not Debug_Flag_Q then
-               Set_Composite_Alignment (E);
-            end if;
+         if Convention (E) = Convention_Ada and then not Debug_Flag_Q then
+            Set_Composite_Alignment (E);
+         end if;
 
-         --  Processing for array types
+      --  Processing for array types
 
-         elsif Is_Array_Type (E) then
+      elsif Is_Array_Type (E) then
 
-            --  For arrays that are required to be atomic/VFA, we do the same
-            --  processing as described above for short records, since we
-            --  really need to have the alignment set for the whole array.
+         --  For arrays that are required to be atomic/VFA, we do the same
+         --  processing as described above for short records, since we
+         --  really need to have the alignment set for the whole array.
 
-            if Is_Atomic_Or_VFA (E) and then not Debug_Flag_Q then
-               Set_Composite_Alignment (E);
-            end if;
+         if Is_Atomic_Or_VFA (E) and then not Debug_Flag_Q then
+            Set_Composite_Alignment (E);
+         end if;
 
-            --  For unpacked array types, set an alignment of 1 if we know
-            --  that the component alignment is not greater than 1. The reason
-            --  we do this is to avoid unnecessary copying of slices of such
-            --  arrays when passed to subprogram parameters (see special test
-            --  in Exp_Ch6.Expand_Actuals).
+         --  For unpacked array types, set an alignment of 1 if we know
+         --  that the component alignment is not greater than 1. The reason
+         --  we do this is to avoid unnecessary copying of slices of such
+         --  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 Known_Static_Component_Size (E)
-                 and then Component_Size (E) = 1
-               then
-                  Set_Alignment (E, Uint_1);
-               end if;
+         if not Is_Packed (E) and then Unknown_Alignment (E) then
+            if Known_Static_Component_Size (E)
+              and then Component_Size (E) = 1
+            then
+               Set_Alignment (E, Uint_1);
             end if;
+         end if;
 
-            --  We need to know whether the size depends on the value of one
-            --  or more discriminants to select the return mechanism. Skip if
-            --  errors are present, to prevent cascaded messages.
-
-            if Serious_Errors_Detected = 0 then
-               Compute_Size_Depends_On_Discriminant (E);
-            end if;
+         --  We need to know whether the size depends on the value of one
+         --  or more discriminants to select the return mechanism. Skip if
+         --  errors are present, to prevent cascaded messages.
 
+         if Serious_Errors_Detected = 0 then
+            Compute_Size_Depends_On_Discriminant (E);
          end if;
       end if;
 
@@ -2752,113 +566,6 @@ package body Layout is
       end if;
    end Layout_Type;
 
-   ---------------------
-   -- Rewrite_Integer --
-   ---------------------
-
-   procedure Rewrite_Integer (N : Node_Id; V : Uint) is
-      Loc : constant Source_Ptr := Sloc (N);
-      Typ : constant Entity_Id  := Etype (N);
-   begin
-      Rewrite (N, Make_Integer_Literal (Loc, Intval => V));
-      Set_Etype (N, Typ);
-   end Rewrite_Integer;
-
-   -------------------------------
-   -- Set_And_Check_Static_Size --
-   -------------------------------
-
-   procedure Set_And_Check_Static_Size
-     (E      : Entity_Id;
-      Esiz   : SO_Ref;
-      RM_Siz : SO_Ref)
-   is
-      SC : Node_Id;
-
-      procedure Check_Size_Too_Small (Spec : Uint; Min : Uint);
-      --  Spec is the number of bit specified in the size clause, and Min is
-      --  the minimum computed size. An error is given that the specified size
-      --  is too small if Spec < Min, and in this case both Esize and RM_Size
-      --  are set to unknown in E. The error message is posted on node SC.
-
-      procedure Check_Unused_Bits (Spec : Uint; Max : Uint);
-      --  Spec is the number of bits specified in the size clause, and Max is
-      --  the maximum computed size. A warning is given about unused bits if
-      --  Spec > Max. This warning is posted on node SC.
-
-      --------------------------
-      -- Check_Size_Too_Small --
-      --------------------------
-
-      procedure Check_Size_Too_Small (Spec : Uint; Min : Uint) is
-      begin
-         if Spec < Min then
-            Error_Msg_Uint_1 := Min;
-            Error_Msg_NE ("size for & too small, minimum allowed is ^", SC, E);
-            Init_Esize   (E);
-            Init_RM_Size (E);
-         end if;
-      end Check_Size_Too_Small;
-
-      -----------------------
-      -- Check_Unused_Bits --
-      -----------------------
-
-      procedure Check_Unused_Bits (Spec : Uint; Max : Uint) is
-      begin
-         if Spec > Max then
-            Error_Msg_Uint_1 := Spec - Max;
-            Error_Msg_NE ("??^ bits of & unused", SC, E);
-         end if;
-      end Check_Unused_Bits;
-
-   --  Start of processing for Set_And_Check_Static_Size
-
-   begin
-      --  Case where Object_Size (Esize) is already set by a size clause
-
-      if Known_Static_Esize (E) then
-         SC := Size_Clause (E);
-
-         if No (SC) then
-            SC := Get_Attribute_Definition_Clause (E, Attribute_Object_Size);
-         end if;
-
-         --  Perform checks on specified size against computed sizes
-
-         if Present (SC) then
-            Check_Unused_Bits    (Esize (E), Esiz);
-            Check_Size_Too_Small (Esize (E), RM_Siz);
-         end if;
-      end if;
-
-      --  Case where Value_Size (RM_Size) is set by specific Value_Size clause
-      --  (we do not need to worry about Value_Size being set by a Size clause,
-      --  since that will have set Esize as well, and we already took care of
-      --  that case).
-
-      if Known_Static_RM_Size (E) then
-         SC := Get_Attribute_Definition_Clause (E, Attribute_Value_Size);
-
-         --  Perform checks on specified size against computed sizes
-
-         if Present (SC) then
-            Check_Unused_Bits    (RM_Size (E), Esiz);
-            Check_Size_Too_Small (RM_Size (E), RM_Siz);
-         end if;
-      end if;
-
-      --  Set sizes if unknown
-
-      if Unknown_Esize (E) then
-         Set_Esize (E, Esiz);
-      end if;
-
-      if Unknown_RM_Size (E) then
-         Set_RM_Size (E, RM_Siz);
-      end if;
-   end Set_And_Check_Static_Size;
-
    -----------------------------
    -- Set_Composite_Alignment --
    -----------------------------
@@ -3138,13 +845,10 @@ package body Layout is
 
    procedure Set_Elem_Alignment (E : Entity_Id) is
    begin
-      --  Do not set alignment for packed array types, unless we are doing
-      --  front end layout, because otherwise this is always handled in the
+      --  Do not set alignment for packed array types, this is handled in the
       --  backend.
 
-      if Is_Packed_Array_Impl_Type (E)
-        and then not Frontend_Layout_On_Target
-      then
+      if Is_Packed_Array_Impl_Type (E) then
          return;
 
       --  If there is an alignment clause, then we respect it
@@ -3183,14 +887,13 @@ package body Layout is
             S := Ttypes.Maximum_Alignment;
 
          --  If this is an access type and the target doesn't have strict
-         --  alignment and we are not doing front end layout, then cap the
-         --  alignment to that of a regular access type. This will avoid
-         --  giving fat pointers twice the usual alignment for no practical
-         --  benefit since the misalignment doesn't really matter.
+         --  alignment, then cap the alignment to that of a regular access
+         --  type. This will avoid giving fat pointers twice the usual
+         --  alignment for no practical benefit since the misalignment doesn't
+         --  really matter.
 
          elsif Is_Access_Type (E)
            and then not Target_Strict_Alignment
-           and then not Frontend_Layout_On_Target
          then
             S := System_Address_Size / SSU;
 
@@ -3360,139 +1063,4 @@ package body Layout is
       end;
    end Set_Elem_Alignment;
 
-   ----------------------
-   -- SO_Ref_From_Expr --
-   ----------------------
-
-   function SO_Ref_From_Expr
-     (Expr      : Node_Id;
-      Ins_Type  : Entity_Id;
-      Vtype     : Entity_Id := Empty;
-      Make_Func : Boolean   := False) return Dynamic_SO_Ref
-   is
-      Loc  : constant Source_Ptr := Sloc (Ins_Type);
-      K    : constant Entity_Id := Make_Temporary (Loc, 'K');
-      Decl : Node_Id;
-
-      Vtype_Primary_View : Entity_Id;
-
-      function Check_Node_V_Ref (N : Node_Id) return Traverse_Result;
-      --  Function used to check one node for reference to V
-
-      function Has_V_Ref is new Traverse_Func (Check_Node_V_Ref);
-      --  Function used to traverse tree to check for reference to V
-
-      ----------------------
-      -- Check_Node_V_Ref --
-      ----------------------
-
-      function Check_Node_V_Ref (N : Node_Id) return Traverse_Result is
-      begin
-         if Nkind (N) = N_Identifier then
-            if Chars (N) = Vname then
-               return Abandon;
-            else
-               return Skip;
-            end if;
-
-         else
-            return OK;
-         end if;
-      end Check_Node_V_Ref;
-
-   --  Start of processing for SO_Ref_From_Expr
-
-   begin
-      --  Case of expression is an integer literal, in this case we just
-      --  return the value (which must always be non-negative, since size
-      --  and offset values can never be negative).
-
-      if Nkind (Expr) = N_Integer_Literal then
-         pragma Assert (Intval (Expr) >= 0);
-         return Intval (Expr);
-      end if;
-
-      --  Case where there is a reference to V, create function
-
-      if Has_V_Ref (Expr) = Abandon then
-
-         pragma Assert (Present (Vtype));
-
-         --  Check whether Vtype is a view of a private type and ensure that
-         --  we use the primary view of the type (which is denoted by its
-         --  Etype, whether it's the type's partial or full view entity).
-         --  This is needed to make sure that we use the same (primary) view
-         --  of the type for all V formals, whether the current view of the
-         --  type is the partial or full view, so that types will always
-         --  match on calls from one size function to another.
-
-         if Has_Private_Declaration (Vtype) then
-            Vtype_Primary_View := Etype (Vtype);
-         else
-            Vtype_Primary_View := Vtype;
-         end if;
-
-         Set_Is_Discrim_SO_Function (K);
-
-         Decl :=
-           Make_Subprogram_Body (Loc,
-
-             Specification =>
-               Make_Function_Specification (Loc,
-                 Defining_Unit_Name => K,
-                   Parameter_Specifications => New_List (
-                     Make_Parameter_Specification (Loc,
-                       Defining_Identifier =>
-                         Make_Defining_Identifier (Loc, Chars => Vname),
-                       Parameter_Type      =>
-                         New_Occurrence_Of (Vtype_Primary_View, Loc))),
-                   Result_Definition =>
-                     New_Occurrence_Of (Standard_Unsigned, Loc)),
-
-             Declarations => Empty_List,
-
-             Handled_Statement_Sequence =>
-               Make_Handled_Sequence_Of_Statements (Loc,
-                 Statements => New_List (
-                   Make_Simple_Return_Statement (Loc,
-                     Expression => Expr))));
-
-      --  The caller requests that the expression be encapsulated in a
-      --  parameterless function.
-
-      elsif Make_Func then
-         Decl :=
-           Make_Subprogram_Body (Loc,
-
-             Specification =>
-               Make_Function_Specification (Loc,
-                 Defining_Unit_Name => K,
-                   Parameter_Specifications => Empty_List,
-                   Result_Definition =>
-                     New_Occurrence_Of (Standard_Unsigned, Loc)),
-
-             Declarations => Empty_List,
-
-             Handled_Statement_Sequence =>
-               Make_Handled_Sequence_Of_Statements (Loc,
-                 Statements => New_List (
-                   Make_Simple_Return_Statement (Loc, Expression => Expr))));
-
-      --  No reference to V and function not requested, so create a constant
-
-      else
-         Decl :=
-           Make_Object_Declaration (Loc,
-             Defining_Identifier => K,
-             Object_Definition   =>
-               New_Occurrence_Of (Standard_Unsigned, Loc),
-             Constant_Present    => True,
-             Expression          => Expr);
-      end if;
-
-      Append_Freeze_Action (Ins_Type, Decl);
-      Analyze (Decl);
-      return Create_Dynamic_SO_Ref (K);
-   end SO_Ref_From_Expr;
-
 end Layout;
index c204587680c18770cdc6d294cdef88e54a0fd310..57aa93e4f5ae3dbc66e1ac6dae0c055f36fae481 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 2000-2007, Free Software Foundation, Inc.         --
+--          Copyright (C) 2000-2017, 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- --
index e5ea7b028437fb4c7a347c0c11fa9b82bcbe4c2f..a62c48b3798ba45fb95e545e030f65e38fba3c91 100644 (file)
@@ -62,9 +62,6 @@ package body Repinfo is
    -- Representation of GCC Expressions --
    ---------------------------------------
 
-   --    This table is used only if Frontend_Layout_On_Target is False, so gigi
-   --    lays out dynamic size/offset fields using encoded GCC expressions.
-
    --    A table internal to this unit is used to hold the values of back
    --    annotated expressions. This table is written out by -gnatt and read
    --    back in for ASIS processing.
index dea044af5284313d749cd02dde36243267213d45..98cc3fa819121d56c37d85ca9dee6f7b56332856 100644 (file)
@@ -11530,9 +11530,10 @@ package body Sem_Ch13 is
       Compile_Time_Warnings_Errors.Init;
       Unchecked_Conversions.Init;
 
-      if AAMP_On_Target then
-         Independence_Checks.Init;
-      end if;
+      --  ??? Might be needed in the future for some non GCC back-ends
+      --  if AAMP_On_Target then
+      --     Independence_Checks.Init;
+      --  end if;
    end Initialize;
 
    ---------------------------
index 7afe9a7ead61c31dccf09c97b19add83814809ac..9f1d824b4c5580f619b14f5ea85a487a4d042638 100644 (file)
@@ -14467,23 +14467,6 @@ package body Sem_Ch3 is
 
          Set_Parent (New_Compon, Parent (Old_Compon));
 
-         --  If the old component's Esize was already determined and is a
-         --  static value, then the new component simply inherits it. Otherwise
-         --  the old component's size may require run-time determination, but
-         --  the new component's size still might be statically determinable
-         --  (if, for example it has a static constraint). In that case we want
-         --  Layout_Type to recompute the component's size, so we reset its
-         --  size and positional fields.
-
-         if Frontend_Layout_On_Target
-           and then not Known_Static_Esize (Old_Compon)
-         then
-            Set_Esize (New_Compon, Uint_0);
-            Init_Normalized_First_Bit    (New_Compon);
-            Init_Normalized_Position     (New_Compon);
-            Init_Normalized_Position_Max (New_Compon);
-         end if;
-
          --  We do not want this node marked as Comes_From_Source, since
          --  otherwise it would get first class status and a separate cross-
          --  reference line would be generated. Illegitimate children do not
index 41713307cd659137434f217c34cd2ab020c3e1e9..a3a1a1f18ab42a4e55cc2a9838be5cdf18e21425 100644 (file)
@@ -5767,8 +5767,9 @@ package body Sem_Eval is
 
       --  No match if sizes different (from use of 'Object_Size). This test
       --  is excluded if Formal_Derived_Matching is True, as the base types
-      --  can be different in that case and typically have different sizes
-      --  (and Esizes can be set when Frontend_Layout_On_Target is True).
+      --  can be different in that case and typically have different sizes.
+      --  ??? Frontend_Layout_On_Target used to set Esizes but this is no
+      --  longer the case, consider removing the last test below.
 
       elsif not Formal_Derived_Matching
         and then Known_Static_Esize (T1)
index 674c944d8606c16f6e2525f33fd345db414db336..4d1e2b0a1999437dd58c26d1b94f96ceeace0d10 100644 (file)
@@ -10169,14 +10169,18 @@ package body Sem_Prag is
       -------------------------------
 
       procedure Record_Independence_Check (N : Node_Id; E : Entity_Id) is
+         pragma Unreferenced (N, E);
       begin
          --  For GCC back ends the validation is done a priori
+         --  ??? This code is dead, might be useful in the future
 
-         if not AAMP_On_Target then
-            return;
-         end if;
+         --  if not AAMP_On_Target then
+         --     return;
+         --  end if;
 
-         Independence_Checks.Append ((N, E));
+         --  Independence_Checks.Append ((N, E));
+
+         return;
       end Record_Independence_Check;
 
       ------------------
index 7eba1365c3ea4ab86205ec209c87ffc2653d3c3b..2ee9245268add52ec2ca1e34fcfe664f5ca4c1cc 100644 (file)
@@ -793,7 +793,7 @@ package body Targparm is
                   Result := (System_Text (P) = 'T');
 
                   case K is
-                     when AAM => AAMP_On_Target                      := Result;
+                     when AAM => null;
                      when ACR => Always_Compatible_Rep_On_Target     := Result;
                      when ASD => Atomic_Sync_Default_On_Target       := Result;
                      when BDC => Backend_Divide_Checks_On_Target     := Result;
@@ -803,7 +803,7 @@ package body Targparm is
                      when D32 => Duration_32_Bits_On_Target          := Result;
                      when DEN => Denorm_On_Target                    := Result;
                      when EXS => Exit_Status_Supported_On_Target     := Result;
-                     when FEL => Frontend_Layout_On_Target           := Result;
+                     when FEL => null;
                      when FEX => Frontend_Exceptions_On_Target       := Result;
                      when FFO => Fractional_Fixed_Ops_On_Target      := Result;
                      when MOV => Machine_Overflows_On_Target         := Result;
index 9964425baf43e6226865f3a0450f6a6894d10a8b..55b270757982363f50efbe85d9e6f6f796da1bb7 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1999-2015, Free Software Foundation, Inc.         --
+--          Copyright (C) 1999-2017, 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- --
@@ -192,17 +192,6 @@ package Targparm is
    --  Get_Target_Parameters routine which reads the values from a provided
    --  text buffer containing the source of the system package.
 
-   ----------------------------
-   -- Special Target Control --
-   ----------------------------
-
-   --  The great majority of GNAT ports are based on GCC. The switches in
-   --  this section indicate the use of some non-standard target back end
-   --  or other special targetting requirements.
-
-   AAMP_On_Target : Boolean := False;
-   --  Set to True if target is AAMP
-
    -------------------------------
    -- Backend Arithmetic Checks --
    -------------------------------
@@ -560,18 +549,6 @@ package Targparm is
    --  2 ** (-(T'Object_Size - 1)) and whose values have an absolute
    --  value less than 1.0.
 
-   -----------------
-   -- Data Layout --
-   -----------------
-
-   --  Normally when using the GCC backend, Gigi and GCC perform much of the
-   --  data layout using the standard layout capabilities of GCC. If the
-   --  parameter Backend_Layout is set to False, then the front end must
-   --  perform all data layout. For further details see the package Layout.
-
-   Frontend_Layout_On_Target : Boolean := False;
-   --  Set True if front end does layout
-
    -----------------
    -- Subprograms --
    -----------------