diff options
author | Arnaud Charlet <charlet@adacore.com> | 2017-09-08 09:46:42 +0000 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2017-09-08 11:46:42 +0200 |
commit | f8f50235dbda237d921d2201744455e0257766b8 (patch) | |
tree | 42feb58cd362108a63f0e56e43e572f7ca0e04aa | |
parent | 63a5b3dc89fa01e461c96bde32df592db5bf700f (diff) | |
download | gcc-f8f50235dbda237d921d2201744455e0257766b8.zip gcc-f8f50235dbda237d921d2201744455e0257766b8.tar.gz gcc-f8f50235dbda237d921d2201744455e0257766b8.tar.bz2 |
sem_ch3.adb, [...]: Remove references to Frontend_Layout_On_Target and remaining references to...
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
-rw-r--r-- | gcc/ada/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ada/debug.adb | 6 | ||||
-rw-r--r-- | gcc/ada/exp_aggr.adb | 2 | ||||
-rw-r--r-- | gcc/ada/exp_attr.adb | 4 | ||||
-rw-r--r-- | gcc/ada/exp_ch3.adb | 9 | ||||
-rw-r--r-- | gcc/ada/exp_ch6.adb | 18 | ||||
-rw-r--r-- | gcc/ada/exp_pakd.adb | 2 | ||||
-rw-r--r-- | gcc/ada/gnat1drv.adb | 24 | ||||
-rw-r--r-- | gcc/ada/layout.adb | 2520 | ||||
-rw-r--r-- | gcc/ada/layout.ads | 2 | ||||
-rw-r--r-- | gcc/ada/repinfo.adb | 3 | ||||
-rw-r--r-- | gcc/ada/sem_ch13.adb | 7 | ||||
-rw-r--r-- | gcc/ada/sem_ch3.adb | 17 | ||||
-rw-r--r-- | gcc/ada/sem_eval.adb | 5 | ||||
-rw-r--r-- | gcc/ada/sem_prag.adb | 12 | ||||
-rw-r--r-- | gcc/ada/targparm.adb | 4 | ||||
-rw-r--r-- | gcc/ada/targparm.ads | 25 |
17 files changed, 88 insertions, 2580 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index fc0f2ca..5ce59b4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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. diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 6b740ff..f5a7e25 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -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 diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 55fdde5..3610ed6 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -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) diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 99a24e7..76b99e8 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -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. diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 6ed0f0f..e551961 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -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 := diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 2822765..423de14 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -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; diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index 0ec3ef4..77a44aa 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -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- -- diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index e6fc897..8a974c9 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -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; diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index 577cf04..34c5b5d 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -24,28 +24,16 @@ ------------------------------------------------------------------------------ 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,130 +46,16 @@ 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 @@ -296,1012 +170,6 @@ package body Layout is 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 -- ------------------------------------------ @@ -1352,1056 +220,13 @@ package body Layout is ------------------- procedure Layout_Object (E : Entity_Id) is - T : constant Entity_Id := Etype (E); - + pragma Unreferenced (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)); + -- Nothing to do for now, assume backend does the layout - 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; + return; 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; - - if Is_Static_SO_Ref (EsizV) then - EsizV := (EsizV + SSU - 1) / SSU; - end if; - - 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; - - -- Now deal with Value_Size (RM_Siz). We are aiming at - -- an expression that looks like: - - -- if xxDx (V.disc) then rmsiz1 - -- else if xxDx (V.disc) then rmsiz2 - -- else ... - - -- Where rmsiz1, rmsiz2... are the RM_Siz values for the - -- individual variants, and xxDx are the discriminant - -- checking functions generated for the variant type. - - -- If this is the first variant, we simply set the result - -- as the expression. Note that this takes care of the - -- others case. - - if No (RM_Siz_Expr) then - - -- 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. - - 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; - - -- Otherwise construct the appropriate test - - 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. - - Dchoice := First (Discrete_Choices (Var)); - - 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; - - RM_Siz_Expr := - Make_If_Expression (Loc, - Expressions => - New_List - (Dtest, Bits_To_SU (RM_SizV), RM_Siz_Expr)); - end if; - - Prev (Var); - end loop; - end; - end if; - end Layout_Component_List; - - Others_Present : Boolean; - pragma Warnings (Off, Others_Present); - -- Indicates others present, not used in this case - - procedure Non_Static_Choice_Error (Choice : Node_Id); - -- Error routine invoked by the generic instantiation below when - -- the variant part has a nonstatic choice. - - 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; - - ----------------------------- - -- Non_Static_Choice_Error -- - ----------------------------- - - 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; - - -- Start of processing for Layout_Variant_Record - - 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. ??? - - declare - VP : constant Node_Id := - Variant_Part (Component_List (Type_Definition (Decl))); - begin - Check_Choices - (VP, Variants (VP), Etype (Name (VP)), Others_Present); - end; - - -- 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. - - Build_Discr_Checking_Funcs (Decl); - - -- Lay out the discriminants - - First_Discr := First_Discriminant (E); - Last_Discr := First_Discr; - while Present (Next_Discriminant (Last_Discr)) loop - Next_Discriminant (Last_Discr); - 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). - - Layout_Component_List (Component_List (Tdef), Esiz, RM_Siz_Expr); - Set_Esize (E, Esiz); - - -- If the RM_Size is a literal, set its value - - if Nkind (RM_Siz_Expr) = N_Integer_Literal then - Set_RM_Size (E, Intval (RM_Siz_Expr)); - - -- Otherwise we construct a dynamic SO_Ref - - else - Set_RM_Size (E, - SO_Ref_From_Expr - (RM_Siz_Expr, - Ins_Type => E, - Vtype => E)); - end if; - end Layout_Variant_Record; - - -- Start of processing for Layout_Record_Type - - 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; - - -- All other cases - - else - -- Initialize alignment conservatively to 1. This value will be - -- increased as necessary during processing of the record. - - if Unknown_Alignment (E) then - Set_Alignment (E, Uint_1); - 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; - - 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; - - Next_Component_Or_Discriminant (Comp); - 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 Present (Full_View (E)) then - Decl := Declaration_Node (Full_View (E)); - else - Decl := Declaration_Node (E); - end if; - - -- Scan all the components - - 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; - ----------------- -- 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; diff --git a/gcc/ada/layout.ads b/gcc/ada/layout.ads index c204587..57aa93e4 100644 --- a/gcc/ada/layout.ads +++ b/gcc/ada/layout.ads @@ -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- -- diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index e5ea7b0..a62c48b 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -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. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index dea044a..98cc3fa 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -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; --------------------------- diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 7afe9a7..9f1d824 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -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 diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 4171330..a3a1a1f 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -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) diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 674c944..4d1e2b0 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -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; ------------------ diff --git a/gcc/ada/targparm.adb b/gcc/ada/targparm.adb index 7eba136..2ee9245 100644 --- a/gcc/ada/targparm.adb +++ b/gcc/ada/targparm.adb @@ -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; diff --git a/gcc/ada/targparm.ads b/gcc/ada/targparm.ads index 9964425..55b2707 100644 --- a/gcc/ada/targparm.ads +++ b/gcc/ada/targparm.ads @@ -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 -- ------------------------------- @@ -561,18 +550,6 @@ package Targparm is -- 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 -- ----------------- |