1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
11 -- Copyright (C) 2001 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
27 ------------------------------------------------------------------------------
29 with Atree; use Atree;
30 with Checks; use Checks;
31 with Debug; use Debug;
32 with Einfo; use Einfo;
33 with Errout; use Errout;
34 with Exp_Ch3; use Exp_Ch3;
35 with Exp_Util; use Exp_Util;
36 with Nlists; use Nlists;
37 with Nmake; use Nmake;
38 with Repinfo; use Repinfo;
40 with Sem_Ch13; use Sem_Ch13;
41 with Sem_Eval; use Sem_Eval;
42 with Sem_Util; use Sem_Util;
43 with Sinfo; use Sinfo;
44 with Snames; use Snames;
45 with Stand; use Stand;
46 with Targparm; use Targparm;
47 with Tbuild; use Tbuild;
48 with Ttypes; use Ttypes;
49 with Uintp; use Uintp;
51 package body Layout is
53 ------------------------
54 -- Local Declarations --
55 ------------------------
57 SSU : constant Int := Ttypes.System_Storage_Unit;
58 -- Short hand for System_Storage_Unit
60 Vname : constant Name_Id := Name_uV;
61 -- Formal parameter name used for functions generated for size offset
62 -- values that depend on the discriminant. All such functions have the
65 -- function xxx (V : vtyp) return Unsigned is
67 -- return ... expression involving V.discrim
70 -----------------------
71 -- Local Subprograms --
72 -----------------------
74 procedure Adjust_Esize_Alignment (E : Entity_Id);
75 -- E is the entity for a type or object. This procedure checks that the
76 -- size and alignment are compatible, and if not either gives an error
77 -- message if they cannot be adjusted or else adjusts them appropriately.
84 -- This is like Make_Op_Add except that it optimizes some cases knowing
85 -- that associative rearrangement is allowed for constant folding if one
86 -- of the operands is a compile time known value.
88 function Assoc_Multiply
93 -- This is like Make_Op_Multiply except that it optimizes some cases
94 -- knowing that associative rearrangement is allowed for constant
95 -- folding if one of the operands is a compile time known value
97 function Assoc_Subtract
100 Right_Opnd : Node_Id)
102 -- This is like Make_Op_Subtract except that it optimizes some cases
103 -- knowing that associative rearrangement is allowed for constant
104 -- folding if one of the operands is a compile time known value
106 function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id;
107 -- Given expressions for the low bound (Lo) and the high bound (Hi),
108 -- Build an expression for the value hi-lo+1, converted to type
109 -- Standard.Unsigned. Takes care of the case where the operands
110 -- are of an enumeration type (so that the subtraction cannot be
111 -- done directly) by applying the Pos operator to Hi/Lo first.
113 function Expr_From_SO_Ref
117 -- Given a value D from a size or offset field, return an expression
118 -- representing the value stored. If the value is known at compile time,
119 -- then an N_Integer_Literal is returned with the appropriate value. If
120 -- the value references a constant entity, then an N_Identifier node
121 -- referencing this entity is returned. The Loc value is used for the
122 -- Sloc value of constructed notes.
124 function SO_Ref_From_Expr
126 Ins_Type : Entity_Id;
127 Vtype : Entity_Id := Empty)
128 return Dynamic_SO_Ref;
129 -- This routine is used in the case where a size/offset value is dynamic
130 -- and is represented by the expression Expr. SO_Ref_From_Expr checks if
131 -- the Expr contains a reference to the identifier V, and if so builds
132 -- a function depending on discriminants of the formal parameter V which
133 -- is of type Vtype. If not, then a constant entity with the value Expr
134 -- is built. The result is a Dynamic_SO_Ref to the created entity. Note
135 -- that Vtype can be omitted if Expr does not contain any reference to V.
136 -- the created entity. The declaration created is inserted in the freeze
137 -- actions of Ins_Type, which also supplies the Sloc for created nodes.
138 -- This function also takes care of making sure that the expression is
139 -- properly analyzed and resolved (which may not be the case yet if we
140 -- build the expression in this unit).
142 function Get_Max_Size (E : Entity_Id) return Node_Id;
143 -- E is an array type or subtype that has at least one index bound that
144 -- is the value of a record discriminant. For such an array, the function
145 -- computes an expression that yields the maximum possible size of the
146 -- array in storage units. The result is not defined for any other type,
147 -- or for arrays that do not depend on discriminants, and it is a fatal
148 -- error to call this unless Size_Depends_On_Discrminant (E) is True.
150 procedure Layout_Array_Type (E : Entity_Id);
151 -- Front end layout of non-bit-packed array type or subtype
153 procedure Layout_Record_Type (E : Entity_Id);
154 -- Front end layout of record type
155 -- Variant records not handled yet ???
157 procedure Rewrite_Integer (N : Node_Id; V : Uint);
158 -- Rewrite node N with an integer literal whose value is V. The Sloc
159 -- for the new node is taken from N, and the type of the literal is
160 -- set to a copy of the type of N on entry.
162 procedure Set_And_Check_Static_Size
166 -- This procedure is called to check explicit given sizes (possibly
167 -- stored in the Esize and RM_Size fields of E) against computed
168 -- Object_Size (Esiz) and Value_Size (RM_Siz) values. Appropriate
169 -- errors and warnings are posted if specified sizes are inconsistent
170 -- with specified sizes. On return, the Esize and RM_Size fields of
171 -- E are set (either from previously given values, or from the newly
172 -- computed values, as appropriate).
174 ----------------------------
175 -- Adjust_Esize_Alignment --
176 ----------------------------
178 procedure Adjust_Esize_Alignment (E : Entity_Id) is
183 -- Nothing to do if size unknown
185 if Unknown_Esize (E) then
189 -- Determine if size is constrained by an attribute definition clause
190 -- which must be obeyed. If so, we cannot increase the size in this
193 -- For a type, the issue is whether an object size clause has been
194 -- set. A normal size clause constrains only the value size (RM_Size)
197 Esize_Set := Has_Object_Size_Clause (E);
199 -- For an object, the issue is whether a size clause is present
202 Esize_Set := Has_Size_Clause (E);
205 -- If size is known it must be a multiple of the byte size
207 if Esize (E) mod SSU /= 0 then
209 -- If not, and size specified, then give error
213 ("size for& not a multiple of byte size", Size_Clause (E), E);
216 -- Otherwise bump up size to a byte boundary
219 Set_Esize (E, (Esize (E) + SSU - 1) / SSU * SSU);
223 -- Now we have the size set, it must be a multiple of the alignment
224 -- nothing more we can do here if the alignment is unknown here.
226 if Unknown_Alignment (E) then
230 -- At this point both the Esize and Alignment are known, so we need
231 -- to make sure they are consistent.
233 Abits := UI_To_Int (Alignment (E)) * SSU;
235 if Esize (E) mod Abits = 0 then
239 -- Here we have a situation where the Esize is not a multiple of
240 -- the alignment. We must either increase Esize or reduce the
241 -- alignment to correct this situation.
243 -- The case in which we can decrease the alignment is where the
244 -- alignment was not set by an alignment clause, and the type in
245 -- question is a discrete type, where it is definitely safe to
246 -- reduce the alignment. For example:
248 -- t : integer range 1 .. 2;
251 -- In this situation, the initial alignment of t is 4, copied from
252 -- the Integer base type, but it is safe to reduce it to 1 at this
253 -- stage, since we will only be loading a single byte.
255 if Is_Discrete_Type (Etype (E))
256 and then not Has_Alignment_Clause (E)
260 exit when Esize (E) mod Abits = 0;
263 Init_Alignment (E, Abits / SSU);
267 -- Now the only possible approach left is to increase the Esize
268 -- but we can't do that if the size was set by a specific clause.
272 ("size for& is not a multiple of alignment",
275 -- Otherwise we can indeed increase the size to a multiple of alignment
278 Set_Esize (E, ((Esize (E) + (Abits - 1)) / Abits) * Abits);
280 end Adjust_Esize_Alignment;
289 Right_Opnd : Node_Id)
296 -- Case of right operand is a constant
298 if Compile_Time_Known_Value (Right_Opnd) then
300 R := Expr_Value (Right_Opnd);
302 -- Case of left operand is a constant
304 elsif Compile_Time_Known_Value (Left_Opnd) then
306 R := Expr_Value (Left_Opnd);
308 -- Neither operand is a constant, do the addition with no optimization
311 return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
314 -- Case of left operand is an addition
316 if Nkind (L) = N_Op_Add then
318 -- (C1 + E) + C2 = (C1 + C2) + E
320 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
322 (Sinfo.Left_Opnd (L),
323 Expr_Value (Sinfo.Left_Opnd (L)) + R);
326 -- (E + C1) + C2 = E + (C1 + C2)
328 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
330 (Sinfo.Right_Opnd (L),
331 Expr_Value (Sinfo.Right_Opnd (L)) + R);
335 -- Case of left operand is a subtraction
337 elsif Nkind (L) = N_Op_Subtract then
339 -- (C1 - E) + C2 = (C1 + C2) + E
341 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
343 (Sinfo.Left_Opnd (L),
344 Expr_Value (Sinfo.Left_Opnd (L)) + R);
347 -- (E - C1) + C2 = E - (C1 - C2)
349 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
351 (Sinfo.Right_Opnd (L),
352 Expr_Value (Sinfo.Right_Opnd (L)) - R);
357 -- Not optimizable, do the addition
359 return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
366 function Assoc_Multiply
369 Right_Opnd : Node_Id)
376 -- Case of right operand is a constant
378 if Compile_Time_Known_Value (Right_Opnd) then
380 R := Expr_Value (Right_Opnd);
382 -- Case of left operand is a constant
384 elsif Compile_Time_Known_Value (Left_Opnd) then
386 R := Expr_Value (Left_Opnd);
388 -- Neither operand is a constant, do the multiply with no optimization
391 return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
394 -- Case of left operand is an multiplication
396 if Nkind (L) = N_Op_Multiply then
398 -- (C1 * E) * C2 = (C1 * C2) + E
400 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
402 (Sinfo.Left_Opnd (L),
403 Expr_Value (Sinfo.Left_Opnd (L)) * R);
406 -- (E * C1) * C2 = E * (C1 * C2)
408 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
410 (Sinfo.Right_Opnd (L),
411 Expr_Value (Sinfo.Right_Opnd (L)) * R);
416 -- Not optimizable, do the multiplication
418 return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
425 function Assoc_Subtract
428 Right_Opnd : Node_Id)
435 -- Case of right operand is a constant
437 if Compile_Time_Known_Value (Right_Opnd) then
439 R := Expr_Value (Right_Opnd);
441 -- Right operand is a constant, do the subtract with no optimization
444 return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
447 -- Case of left operand is an addition
449 if Nkind (L) = N_Op_Add then
451 -- (C1 + E) - C2 = (C1 - C2) + E
453 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
455 (Sinfo.Left_Opnd (L),
456 Expr_Value (Sinfo.Left_Opnd (L)) - R);
459 -- (E + C1) - C2 = E + (C1 - C2)
461 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
463 (Sinfo.Right_Opnd (L),
464 Expr_Value (Sinfo.Right_Opnd (L)) - R);
468 -- Case of left operand is a subtraction
470 elsif Nkind (L) = N_Op_Subtract then
472 -- (C1 - E) - C2 = (C1 - C2) + E
474 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
476 (Sinfo.Left_Opnd (L),
477 Expr_Value (Sinfo.Left_Opnd (L)) + R);
480 -- (E - C1) - C2 = E - (C1 + C2)
482 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
484 (Sinfo.Right_Opnd (L),
485 Expr_Value (Sinfo.Right_Opnd (L)) + R);
490 -- Not optimizable, do the subtraction
492 return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
499 function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id is
500 Loc : constant Source_Ptr := Sloc (Lo);
501 Typ : constant Entity_Id := Etype (Lo);
506 Lo_Op := New_Copy_Tree (Lo);
507 Hi_Op := New_Copy_Tree (Hi);
509 -- If type is enumeration type, then use Pos attribute to convert
510 -- to integer type for which subtraction is a permitted operation.
512 if Is_Enumeration_Type (Typ) then
514 Make_Attribute_Reference (Loc,
515 Prefix => New_Occurrence_Of (Typ, Loc),
516 Attribute_Name => Name_Pos,
517 Expressions => New_List (Lo_Op));
520 Make_Attribute_Reference (Loc,
521 Prefix => New_Occurrence_Of (Typ, Loc),
522 Attribute_Name => Name_Pos,
523 Expressions => New_List (Hi_Op));
531 Right_Opnd => Lo_Op),
532 Right_Opnd => Make_Integer_Literal (Loc, 1));
535 ----------------------
536 -- Expr_From_SO_Ref --
537 ----------------------
539 function Expr_From_SO_Ref
547 if Is_Dynamic_SO_Ref (D) then
548 Ent := Get_Dynamic_SO_Entity (D);
550 if Is_Discrim_SO_Function (Ent) then
552 Make_Function_Call (Loc,
553 Name => New_Occurrence_Of (Ent, Loc),
554 Parameter_Associations => New_List (
555 Make_Identifier (Loc, Chars => Vname)));
558 return New_Occurrence_Of (Ent, Loc);
562 return Make_Integer_Literal (Loc, D);
564 end Expr_From_SO_Ref;
570 function Get_Max_Size (E : Entity_Id) return Node_Id is
571 Loc : constant Source_Ptr := Sloc (E);
579 type Val_Status_Type is (Const, Dynamic);
581 type Val_Type (Status : Val_Status_Type := Const) is
584 when Const => Val : Uint;
585 when Dynamic => Nod : Node_Id;
588 -- Shows the status of the value so far. Const means that the value
589 -- is constant, and Val is the current constant value. Dynamic means
590 -- that the value is dynamic, and in this case Nod is the Node_Id of
591 -- the expression to compute the value.
594 -- Calculated value so far if Size.Status = Const,
595 -- or expression value so far if Size.Status = Dynamic.
597 SU_Convert_Required : Boolean := False;
598 -- This is set to True if the final result must be converted from
599 -- bits to storage units (rounding up to a storage unit boundary).
601 -----------------------
602 -- Local Subprograms --
603 -----------------------
605 procedure Max_Discrim (N : in out Node_Id);
606 -- If the node N represents a discriminant, replace it by the maximum
607 -- value of the discriminant.
609 procedure Min_Discrim (N : in out Node_Id);
610 -- If the node N represents a discriminant, replace it by the minimum
611 -- value of the discriminant.
617 procedure Max_Discrim (N : in out Node_Id) is
619 if Nkind (N) = N_Identifier
620 and then Ekind (Entity (N)) = E_Discriminant
622 N := Type_High_Bound (Etype (N));
630 procedure Min_Discrim (N : in out Node_Id) is
632 if Nkind (N) = N_Identifier
633 and then Ekind (Entity (N)) = E_Discriminant
635 N := Type_Low_Bound (Etype (N));
639 -- Start of processing for Get_Max_Size
642 pragma Assert (Size_Depends_On_Discriminant (E));
644 -- Initialize status from component size
646 if Known_Static_Component_Size (E) then
647 Size := (Const, Component_Size (E));
650 Size := (Dynamic, Expr_From_SO_Ref (Loc, Component_Size (E)));
653 -- Loop through indices
655 Indx := First_Index (E);
656 while Present (Indx) loop
657 Ityp := Etype (Indx);
658 Lo := Type_Low_Bound (Ityp);
659 Hi := Type_High_Bound (Ityp);
664 -- Value of the current subscript range is statically known
666 if Compile_Time_Known_Value (Lo)
667 and then Compile_Time_Known_Value (Hi)
669 S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
671 -- If known flat bound, entire size of array is zero!
674 return Make_Integer_Literal (Loc, 0);
677 -- Current value is constant, evolve value
679 if Size.Status = Const then
680 Size.Val := Size.Val * S;
682 -- Current value is dynamic
685 -- An interesting little optimization, if we have a pending
686 -- conversion from bits to storage units, and the current
687 -- length is a multiple of the storage unit size, then we
688 -- can take the factor out here statically, avoiding some
689 -- extra dynamic computations at the end.
691 if SU_Convert_Required and then S mod SSU = 0 then
693 SU_Convert_Required := False;
698 Left_Opnd => Size.Nod,
700 Make_Integer_Literal (Loc, Intval => S));
703 -- Value of the current subscript range is dynamic
706 -- If the current size value is constant, then here is where we
707 -- make a transition to dynamic values, which are always stored
708 -- in storage units, However, we do not want to convert to SU's
709 -- too soon, consider the case of a packed array of single bits,
710 -- we want to do the SU conversion after computing the size in
713 if Size.Status = Const then
715 -- If the current value is a multiple of the storage unit,
716 -- then most certainly we can do the conversion now, simply
717 -- by dividing the current value by the storage unit value.
718 -- If this works, we set SU_Convert_Required to False.
720 if Size.Val mod SSU = 0 then
723 (Dynamic, Make_Integer_Literal (Loc, Size.Val / SSU));
724 SU_Convert_Required := False;
726 -- Otherwise, we go ahead and convert the value in bits,
727 -- and set SU_Convert_Required to True to ensure that the
728 -- final value is indeed properly converted.
731 Size := (Dynamic, Make_Integer_Literal (Loc, Size.Val));
732 SU_Convert_Required := True;
738 Len := Compute_Length (Lo, Hi);
740 -- Check possible range of Len
749 Determine_Range (Len, OK, LLo, LHi);
751 Len := Convert_To (Standard_Unsigned, Len);
753 -- If we cannot verify that range cannot be super-flat,
754 -- we need a max with zero, since length must be non-neg.
756 if not OK or else LLo < 0 then
758 Make_Attribute_Reference (Loc,
760 New_Occurrence_Of (Standard_Unsigned, Loc),
761 Attribute_Name => Name_Max,
762 Expressions => New_List (
763 Make_Integer_Literal (Loc, 0),
772 -- Here after processing all bounds to set sizes. If the value is
773 -- a constant, then it is bits, and we just return the value.
775 if Size.Status = Const then
776 return Make_Integer_Literal (Loc, Size.Val);
778 -- Case where the value is dynamic
781 -- Do convert from bits to SU's if needed
783 if SU_Convert_Required then
785 -- The expression required is (Size.Nod + SU - 1) / SU
791 Left_Opnd => Size.Nod,
792 Right_Opnd => Make_Integer_Literal (Loc, SSU - 1)),
793 Right_Opnd => Make_Integer_Literal (Loc, SSU));
800 -----------------------
801 -- Layout_Array_Type --
802 -----------------------
804 procedure Layout_Array_Type (E : Entity_Id) is
805 Loc : constant Source_Ptr := Sloc (E);
806 Ctyp : constant Entity_Id := Component_Type (E);
814 Insert_Typ : Entity_Id;
815 -- This is the type with which any generated constants or functions
816 -- will be associated (i.e. inserted into the freeze actions). This
817 -- is normally the type being layed out. The exception occurs when
818 -- we are laying out Itype's which are local to a record type, and
819 -- whose scope is this record type. Such types do not have freeze
820 -- nodes (because we have no place to put them).
822 ------------------------------------
823 -- How An Array Type is Layed Out --
824 ------------------------------------
826 -- Here is what goes on. We need to multiply the component size of
827 -- the array (which has already been set) by the length of each of
828 -- the indexes. If all these values are known at compile time, then
829 -- the resulting size of the array is the appropriate constant value.
831 -- If the component size or at least one bound is dynamic (but no
832 -- discriminants are present), then the size will be computed as an
833 -- expression that calculates the proper size.
835 -- If there is at least one discriminant bound, then the size is also
836 -- computed as an expression, but this expression contains discriminant
837 -- values which are obtained by selecting from a function parameter, and
838 -- the size is given by a function that is passed the variant record in
839 -- question, and whose body is the expression.
841 type Val_Status_Type is (Const, Dynamic, Discrim);
843 type Val_Type (Status : Val_Status_Type := Const) is
848 -- Calculated value so far if Val_Status = Const
850 when Dynamic | Discrim =>
852 -- Expression value so far if Val_Status /= Const
856 -- Records the value or expression computed so far. Const means that
857 -- the value is constant, and Val is the current constant value.
858 -- Dynamic means that the value is dynamic, and in this case Nod is
859 -- the Node_Id of the expression to compute the value, and Discrim
860 -- means that at least one bound is a discriminant, in which case Nod
861 -- is the expression so far (which will be the body of the function).
864 -- Value of size computed so far. See comments above.
866 Vtyp : Entity_Id := Empty;
867 -- Variant record type for the formal parameter of the
868 -- discriminant function V if Status = Discrim.
870 SU_Convert_Required : Boolean := False;
871 -- This is set to True if the final result must be converted from
872 -- bits to storage units (rounding up to a storage unit boundary).
874 procedure Discrimify (N : in out Node_Id);
875 -- If N represents a discriminant, then the Size.Status is set to
876 -- Discrim, and Vtyp is set. The parameter N is replaced with the
877 -- proper expression to extract the discriminant value from V.
883 procedure Discrimify (N : in out Node_Id) is
888 if Nkind (N) = N_Identifier
889 and then Ekind (Entity (N)) = E_Discriminant
891 Set_Size_Depends_On_Discriminant (E);
893 if Size.Status /= Discrim then
894 Decl := Parent (Parent (Entity (N)));
895 Size := (Discrim, Size.Nod);
896 Vtyp := Defining_Identifier (Decl);
902 Make_Selected_Component (Loc,
903 Prefix => Make_Identifier (Loc, Chars => Vname),
904 Selector_Name => New_Occurrence_Of (Entity (N), Loc));
906 -- Set the Etype attributes of the selected name and its prefix.
907 -- Analyze_And_Resolve can't be called here because the Vname
908 -- entity denoted by the prefix will not yet exist (it's created
909 -- by SO_Ref_From_Expr, called at the end of Layout_Array_Type).
911 Set_Etype (Prefix (N), Vtyp);
916 -- Start of processing for Layout_Array_Type
919 -- Default alignment is component alignment
921 if Unknown_Alignment (E) then
922 Set_Alignment (E, Alignment (Ctyp));
925 -- Calculate proper type for insertions
927 if Is_Record_Type (Scope (E)) then
928 Insert_Typ := Scope (E);
933 -- Cannot do anything if Esize of component type unknown
935 if Unknown_Esize (Ctyp) then
939 -- Set component size if not set already
941 if Unknown_Component_Size (E) then
942 Set_Component_Size (E, Esize (Ctyp));
945 -- (RM 13.3 (48)) says that the size of an unconstrained array
946 -- is implementation defined. We choose to leave it as Unknown
947 -- here, and the actual behavior is determined by the back end.
949 if not Is_Constrained (E) then
953 -- Initialize status from component size
955 if Known_Static_Component_Size (E) then
956 Size := (Const, Component_Size (E));
959 Size := (Dynamic, Expr_From_SO_Ref (Loc, Component_Size (E)));
962 -- Loop to process array indices
964 Indx := First_Index (E);
965 while Present (Indx) loop
966 Ityp := Etype (Indx);
967 Lo := Type_Low_Bound (Ityp);
968 Hi := Type_High_Bound (Ityp);
970 -- Value of the current subscript range is statically known
972 if Compile_Time_Known_Value (Lo)
973 and then Compile_Time_Known_Value (Hi)
975 S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
977 -- If known flat bound, entire size of array is zero!
980 Set_Esize (E, Uint_0);
981 Set_RM_Size (E, Uint_0);
985 -- If constant, evolve value
987 if Size.Status = Const then
988 Size.Val := Size.Val * S;
990 -- Current value is dynamic
993 -- An interesting little optimization, if we have a pending
994 -- conversion from bits to storage units, and the current
995 -- length is a multiple of the storage unit size, then we
996 -- can take the factor out here statically, avoiding some
997 -- extra dynamic computations at the end.
999 if SU_Convert_Required and then S mod SSU = 0 then
1001 SU_Convert_Required := False;
1004 -- Now go ahead and evolve the expression
1007 Assoc_Multiply (Loc,
1008 Left_Opnd => Size.Nod,
1010 Make_Integer_Literal (Loc, Intval => S));
1013 -- Value of the current subscript range is dynamic
1016 -- If the current size value is constant, then here is where we
1017 -- make a transition to dynamic values, which are always stored
1018 -- in storage units, However, we do not want to convert to SU's
1019 -- too soon, consider the case of a packed array of single bits,
1020 -- we want to do the SU conversion after computing the size in
1023 if Size.Status = Const then
1025 -- If the current value is a multiple of the storage unit,
1026 -- then most certainly we can do the conversion now, simply
1027 -- by dividing the current value by the storage unit value.
1028 -- If this works, we set SU_Convert_Required to False.
1030 if Size.Val mod SSU = 0 then
1032 (Dynamic, Make_Integer_Literal (Loc, Size.Val / SSU));
1033 SU_Convert_Required := False;
1035 -- Otherwise, we go ahead and convert the value in bits,
1036 -- and set SU_Convert_Required to True to ensure that the
1037 -- final value is indeed properly converted.
1040 Size := (Dynamic, Make_Integer_Literal (Loc, Size.Val));
1041 SU_Convert_Required := True;
1048 -- Length is hi-lo+1
1050 Len := Compute_Length (Lo, Hi);
1052 -- Check possible range of Len
1060 Set_Parent (Len, E);
1061 Determine_Range (Len, OK, LLo, LHi);
1063 Len := Convert_To (Standard_Unsigned, Len);
1065 -- If range definitely flat or superflat, result size is zero
1067 if OK and then LHi <= 0 then
1068 Set_Esize (E, Uint_0);
1069 Set_RM_Size (E, Uint_0);
1073 -- If we cannot verify that range cannot be super-flat, we
1074 -- need a maximum with zero, since length cannot be negative.
1076 if not OK or else LLo < 0 then
1078 Make_Attribute_Reference (Loc,
1080 New_Occurrence_Of (Standard_Unsigned, Loc),
1081 Attribute_Name => Name_Max,
1082 Expressions => New_List (
1083 Make_Integer_Literal (Loc, 0),
1088 -- At this stage, Len has the expression for the length
1091 Assoc_Multiply (Loc,
1092 Left_Opnd => Size.Nod,
1099 -- Here after processing all bounds to set sizes. If the value is
1100 -- a constant, then it is bits, and the only thing we need to do
1101 -- is to check against explicit given size and do alignment adjust.
1103 if Size.Status = Const then
1104 Set_And_Check_Static_Size (E, Size.Val, Size.Val);
1105 Adjust_Esize_Alignment (E);
1107 -- Case where the value is dynamic
1110 -- Do convert from bits to SU's if needed
1112 if SU_Convert_Required then
1114 -- The expression required is (Size.Nod + SU - 1) / SU
1117 Make_Op_Divide (Loc,
1120 Left_Opnd => Size.Nod,
1121 Right_Opnd => Make_Integer_Literal (Loc, SSU - 1)),
1122 Right_Opnd => Make_Integer_Literal (Loc, SSU));
1125 -- Now set the dynamic size (the Value_Size is always the same
1126 -- as the Object_Size for arrays whose length is dynamic).
1128 -- ??? If Size.Status = Dynamic, Vtyp will not have been set.
1129 -- The added initialization sets it to Empty now, but is this
1132 Set_Esize (E, SO_Ref_From_Expr (Size.Nod, Insert_Typ, Vtyp));
1133 Set_RM_Size (E, Esize (E));
1135 end Layout_Array_Type;
1141 procedure Layout_Object (E : Entity_Id) is
1142 T : constant Entity_Id := Etype (E);
1145 -- Nothing to do if backend does layout
1147 if not Frontend_Layout_On_Target then
1151 -- Set size if not set for object and known for type. Use the
1152 -- RM_Size if that is known for the type and Esize is not.
1154 if Unknown_Esize (E) then
1155 if Known_Esize (T) then
1156 Set_Esize (E, Esize (T));
1158 elsif Known_RM_Size (T) then
1159 Set_Esize (E, RM_Size (T));
1163 -- Set alignment from type if unknown and type alignment known
1165 if Unknown_Alignment (E) and then Known_Alignment (T) then
1166 Set_Alignment (E, Alignment (T));
1169 -- Make sure size and alignment are consistent
1171 Adjust_Esize_Alignment (E);
1173 -- Final adjustment, if we don't know the alignment, and the Esize
1174 -- was not set by an explicit Object_Size attribute clause, then
1175 -- we reset the Esize to unknown, since we really don't know it.
1177 if Unknown_Alignment (E)
1178 and then not Has_Size_Clause (E)
1180 Set_Esize (E, Uint_0);
1184 ------------------------
1185 -- Layout_Record_Type --
1186 ------------------------
1188 procedure Layout_Record_Type (E : Entity_Id) is
1189 Loc : constant Source_Ptr := Sloc (E);
1193 -- Current component being layed out
1195 Prev_Comp : Entity_Id;
1196 -- Previous layed out component
1198 procedure Get_Next_Component_Location
1199 (Prev_Comp : Entity_Id;
1201 New_Npos : out SO_Ref;
1202 New_Fbit : out SO_Ref;
1203 New_NPMax : out SO_Ref;
1204 Force_SU : Boolean);
1205 -- Given the previous component in Prev_Comp, which is already laid
1206 -- out, and the alignment of the following component, lays out the
1207 -- following component, and returns its starting position in New_Npos
1208 -- (Normalized_Position value), New_Fbit (Normalized_First_Bit value),
1209 -- and New_NPMax (Normalized_Position_Max value). If Prev_Comp is empty
1210 -- (no previous component is present), then New_Npos, New_Fbit and
1211 -- New_NPMax are all set to zero on return. This procedure is also
1212 -- used to compute the size of a record or variant by giving it the
1213 -- last component, and the record alignment. Force_SU is used to force
1214 -- the new component location to be aligned on a storage unit boundary,
1215 -- even in a packed record, False means that the new position does not
1216 -- need to be bumped to a storage unit boundary, True means a storage
1217 -- unit boundary is always required.
1219 procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id);
1220 -- Lays out component Comp, given Prev_Comp, the previously laid-out
1221 -- component (Prev_Comp = Empty if no components laid out yet). The
1222 -- alignment of the record itself is also updated if needed. Both
1223 -- Comp and Prev_Comp can be either components or discriminants. A
1224 -- special case is when Comp is Empty, this is used at the end
1225 -- to determine the size of the entire record. For this special
1226 -- call the resulting offset is placed in Final_Offset.
1228 procedure Layout_Components
1232 RM_Siz : out SO_Ref);
1233 -- This procedure lays out the components of the given component list
1234 -- which contains the components starting with From, and ending with To.
1235 -- The Next_Entity chain is used to traverse the components. On entry
1236 -- Prev_Comp is set to the component preceding the list, so that the
1237 -- list is layed out after this component. Prev_Comp is set to Empty if
1238 -- the component list is to be layed out starting at the start of the
1239 -- record. On return, the components are all layed out, and Prev_Comp is
1240 -- set to the last layed out component. On return, Esiz is set to the
1241 -- resulting Object_Size value, which is the length of the record up
1242 -- to and including the last layed out entity. For Esiz, the value is
1243 -- adjusted to match the alignment of the record. RM_Siz is similarly
1244 -- set to the resulting Value_Size value, which is the same length, but
1245 -- not adjusted to meet the alignment. Note that in the case of variant
1246 -- records, Esiz represents the maximum size.
1248 procedure Layout_Non_Variant_Record;
1249 -- Procedure called to layout a non-variant record type or subtype
1251 procedure Layout_Variant_Record;
1252 -- Procedure called to layout a variant record type. Decl is set to the
1253 -- full type declaration for the variant record.
1255 ---------------------------------
1256 -- Get_Next_Component_Location --
1257 ---------------------------------
1259 procedure Get_Next_Component_Location
1260 (Prev_Comp : Entity_Id;
1262 New_Npos : out SO_Ref;
1263 New_Fbit : out SO_Ref;
1264 New_NPMax : out SO_Ref;
1268 -- No previous component, return zero position
1270 if No (Prev_Comp) then
1273 New_NPMax := Uint_0;
1277 -- Here we have a previous component
1280 Loc : constant Source_Ptr := Sloc (Prev_Comp);
1282 Old_Npos : constant SO_Ref := Normalized_Position (Prev_Comp);
1283 Old_Fbit : constant SO_Ref := Normalized_First_Bit (Prev_Comp);
1284 Old_NPMax : constant SO_Ref := Normalized_Position_Max (Prev_Comp);
1285 Old_Esiz : constant SO_Ref := Esize (Prev_Comp);
1287 Old_Maxsz : Node_Id;
1288 -- Expression representing maximum size of previous component
1291 -- Case where previous field had a dynamic size
1293 if Is_Dynamic_SO_Ref (Esize (Prev_Comp)) then
1295 -- If the previous field had a dynamic length, then it is
1296 -- required to occupy an integral number of storage units,
1297 -- and start on a storage unit boundary. This means that
1298 -- the Normalized_First_Bit value is zero in the previous
1299 -- component, and the new value is also set to zero.
1303 -- In this case, the new position is given by an expression
1304 -- that is the sum of old normalized position and old size.
1309 Left_Opnd => Expr_From_SO_Ref (Loc, Old_Npos),
1310 Right_Opnd => Expr_From_SO_Ref (Loc, Old_Esiz)),
1314 -- Get maximum size of previous component
1316 if Size_Depends_On_Discriminant (Etype (Prev_Comp)) then
1317 Old_Maxsz := Get_Max_Size (Etype (Prev_Comp));
1319 Old_Maxsz := Expr_From_SO_Ref (Loc, Old_Esiz);
1322 -- Now we can compute the new max position. If the max size
1323 -- is static and the old position is static, then we can
1324 -- compute the new position statically.
1326 if Nkind (Old_Maxsz) = N_Integer_Literal
1327 and then Known_Static_Normalized_Position_Max (Prev_Comp)
1329 New_NPMax := Old_NPMax + Intval (Old_Maxsz);
1331 -- Otherwise new max position is dynamic
1337 Left_Opnd => Expr_From_SO_Ref (Loc, Old_NPMax),
1338 Right_Opnd => Old_Maxsz),
1343 -- Previous field has known static Esize
1346 New_Fbit := Old_Fbit + Old_Esiz;
1348 -- Bump New_Fbit to storage unit boundary if required
1350 if New_Fbit /= 0 and then Force_SU then
1351 New_Fbit := (New_Fbit + SSU - 1) / SSU * SSU;
1354 -- If old normalized position is static, we can go ahead
1355 -- and compute the new normalized position directly.
1357 if Known_Static_Normalized_Position (Prev_Comp) then
1358 New_Npos := Old_Npos;
1360 if New_Fbit >= SSU then
1361 New_Npos := New_Npos + New_Fbit / SSU;
1362 New_Fbit := New_Fbit mod SSU;
1365 -- Bump alignment if stricter than prev
1367 if Align > Alignment (Prev_Comp) then
1368 New_Npos := (New_Npos + Align - 1) / Align * Align;
1371 -- The max position is always equal to the position if
1372 -- the latter is static, since arrays depending on the
1373 -- values of discriminants never have static sizes.
1375 New_NPMax := New_Npos;
1378 -- Case of old normalized position is dynamic
1381 -- If new bit position is within the current storage unit,
1382 -- we can just copy the old position as the result position
1383 -- (we have already set the new first bit value).
1385 if New_Fbit < SSU then
1386 New_Npos := Old_Npos;
1387 New_NPMax := Old_NPMax;
1389 -- If new bit position is past the current storage unit, we
1390 -- need to generate a new dynamic value for the position
1391 -- ??? need to deal with alignment
1397 Left_Opnd => Expr_From_SO_Ref (Loc, Old_Npos),
1399 Make_Integer_Literal (Loc,
1400 Intval => New_Fbit / SSU)),
1407 Left_Opnd => Expr_From_SO_Ref (Loc, Old_NPMax),
1409 Make_Integer_Literal (Loc,
1410 Intval => New_Fbit / SSU)),
1413 New_Fbit := New_Fbit mod SSU;
1418 end Get_Next_Component_Location;
1420 ----------------------
1421 -- Layout_Component --
1422 ----------------------
1424 procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id) is
1425 Ctyp : constant Entity_Id := Etype (Comp);
1432 -- Parent field is always at start of record, this will overlap
1433 -- the actual fields that are part of the parent, and that's fine
1435 if Chars (Comp) = Name_uParent then
1436 Set_Normalized_Position (Comp, Uint_0);
1437 Set_Normalized_First_Bit (Comp, Uint_0);
1438 Set_Normalized_Position_Max (Comp, Uint_0);
1439 Set_Component_Bit_Offset (Comp, Uint_0);
1440 Set_Esize (Comp, Esize (Ctyp));
1444 -- Check case of type of component has a scope of the record we
1445 -- are laying out. When this happens, the type in question is an
1446 -- Itype that has not yet been layed out (that's because such
1447 -- types do not get frozen in the normal manner, because there
1448 -- is no place for the freeze nodes).
1450 if Scope (Ctyp) = E then
1454 -- Increase alignment of record if necessary. Note that we do not
1455 -- do this for packed records, which have an alignment of one by
1456 -- default, or for records for which an explicit alignment was
1457 -- specified with an alignment clause.
1459 if not Is_Packed (E)
1460 and then not Has_Alignment_Clause (E)
1461 and then Alignment (Ctyp) > Alignment (E)
1463 Set_Alignment (E, Alignment (Ctyp));
1466 -- If component already laid out, then we are done
1468 if Known_Normalized_Position (Comp) then
1472 -- Set size of component from type. We use the Esize except in a
1473 -- packed record, where we use the RM_Size (since that is exactly
1474 -- what the RM_Size value, as distinct from the Object_Size is
1477 if Is_Packed (E) then
1478 Set_Esize (Comp, RM_Size (Ctyp));
1480 Set_Esize (Comp, Esize (Ctyp));
1483 -- Compute the component position from the previous one. See if
1484 -- current component requires being on a storage unit boundary.
1486 -- If record is not packed, we always go to a storage unit boundary
1488 if not Is_Packed (E) then
1494 -- Elementary types do not need SU boundary in packed record
1496 if Is_Elementary_Type (Ctyp) then
1499 -- Packed array types with a modular packed array type do not
1500 -- force a storage unit boundary (since the code generation
1501 -- treats these as equivalent to the underlying modular type),
1503 elsif Is_Array_Type (Ctyp)
1504 and then Is_Bit_Packed_Array (Ctyp)
1505 and then Is_Modular_Integer_Type (Packed_Array_Type (Ctyp))
1509 -- Record types with known length less than or equal to the length
1510 -- of long long integer can also be unaligned, since they can be
1511 -- treated as scalars.
1513 elsif Is_Record_Type (Ctyp)
1514 and then not Is_Dynamic_SO_Ref (Esize (Ctyp))
1515 and then Esize (Ctyp) <= Esize (Standard_Long_Long_Integer)
1519 -- All other cases force a storage unit boundary, even when packed
1526 -- Now get the next component location
1528 Get_Next_Component_Location
1529 (Prev_Comp, Alignment (Ctyp), Npos, Fbit, NPMax, Forc);
1530 Set_Normalized_Position (Comp, Npos);
1531 Set_Normalized_First_Bit (Comp, Fbit);
1532 Set_Normalized_Position_Max (Comp, NPMax);
1534 -- Set Component_Bit_Offset in the static case
1536 if Known_Static_Normalized_Position (Comp)
1537 and then Known_Normalized_First_Bit (Comp)
1539 Set_Component_Bit_Offset (Comp, SSU * Npos + Fbit);
1541 end Layout_Component;
1543 -----------------------
1544 -- Layout_Components --
1545 -----------------------
1547 procedure Layout_Components
1551 RM_Siz : out SO_Ref)
1558 -- Only layout components if there are some to layout!
1560 if Present (From) then
1562 -- Layout components with no component clauses
1566 if (Ekind (Comp) = E_Component
1567 or else Ekind (Comp) = E_Discriminant)
1568 and then No (Component_Clause (Comp))
1570 Layout_Component (Comp, Prev_Comp);
1574 exit when Comp = To;
1579 -- Set size fields, both are zero if no components
1581 if No (Prev_Comp) then
1586 -- First the object size, for which we align past the last
1587 -- field to the alignment of the record (the object size
1588 -- is required to be a multiple of the alignment).
1590 Get_Next_Component_Location
1598 -- If the resulting normalized position is a dynamic reference,
1599 -- then the size is dynamic, and is stored in storage units.
1600 -- In this case, we set the RM_Size to the same value, it is
1601 -- simply not worth distinguishing Esize and RM_Size values in
1602 -- the dynamic case, since the RM has nothing to say about them.
1604 -- Note that a size cannot have been given in this case, since
1605 -- size specifications cannot be given for variable length types.
1608 Align : constant Uint := Alignment (E);
1611 if Is_Dynamic_SO_Ref (End_Npos) then
1614 -- Set the Object_Size allowing for alignment. In the
1615 -- dynamic case, we have to actually do the runtime
1616 -- computation. We can skip this in the non-packed
1617 -- record case if the last component has a smaller
1618 -- alignment than the overall record alignment.
1620 if Is_Dynamic_SO_Ref (End_NPMax) then
1624 or else Alignment (Prev_Comp) < Align
1626 -- The expression we build is
1627 -- (expr + align - 1) / align * align
1632 Make_Op_Multiply (Loc,
1634 Make_Op_Divide (Loc,
1638 Expr_From_SO_Ref (Loc, Esiz),
1640 Make_Integer_Literal (Loc,
1641 Intval => Align - 1)),
1643 Make_Integer_Literal (Loc, Align)),
1645 Make_Integer_Literal (Loc, Align)),
1650 -- Here Esiz is static, so we can adjust the alignment
1651 -- directly go give the required aligned value.
1654 Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
1657 -- Case where computed size is static
1660 -- The ending size was computed in Npos in storage units,
1661 -- but the actual size is stored in bits, so adjust
1662 -- accordingly. We also adjust the size to match the
1665 Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
1667 -- Compute the resulting Value_Size (RM_Size). For this
1668 -- purpose we do not force alignment of the record or
1669 -- storage size alignment of the result.
1671 Get_Next_Component_Location
1679 RM_Siz := End_Npos * SSU + End_Fbit;
1680 Set_And_Check_Static_Size (E, Esiz, RM_Siz);
1684 end Layout_Components;
1686 -------------------------------
1687 -- Layout_Non_Variant_Record --
1688 -------------------------------
1690 procedure Layout_Non_Variant_Record is
1695 Layout_Components (First_Entity (E), Last_Entity (E), Esiz, RM_Siz);
1696 Set_Esize (E, Esiz);
1697 Set_RM_Size (E, RM_Siz);
1698 end Layout_Non_Variant_Record;
1700 ---------------------------
1701 -- Layout_Variant_Record --
1702 ---------------------------
1704 procedure Layout_Variant_Record is
1705 Tdef : constant Node_Id := Type_Definition (Decl);
1706 Dlist : constant List_Id := Discriminant_Specifications (Decl);
1710 RM_Siz_Expr : Node_Id := Empty;
1711 -- Expression for the evolving RM_Siz value. This is typically a
1712 -- conditional expression which involves tests of discriminant
1713 -- values that are formed as references to the entity V. At
1714 -- the end of scanning all the components, a suitable function
1715 -- is constructed in which V is the parameter.
1717 -----------------------
1718 -- Local Subprograms --
1719 -----------------------
1721 procedure Layout_Component_List
1724 RM_Siz_Expr : out Node_Id);
1725 -- Recursive procedure, called to layout one component list
1726 -- Esiz and RM_Siz_Expr are set to the Object_Size and Value_Size
1727 -- values respectively representing the record size up to and
1728 -- including the last component in the component list (including
1729 -- any variants in this component list). RM_Siz_Expr is returned
1730 -- as an expression which may in the general case involve some
1731 -- references to the discriminants of the current record value,
1732 -- referenced by selecting from the entity V.
1734 ---------------------------
1735 -- Layout_Component_List --
1736 ---------------------------
1738 procedure Layout_Component_List
1741 RM_Siz_Expr : out Node_Id)
1743 Citems : constant List_Id := Component_Items (Clist);
1744 Vpart : constant Node_Id := Variant_Part (Clist);
1748 RMS_Ent : Entity_Id;
1751 if Is_Non_Empty_List (Citems) then
1753 (From => Defining_Identifier (First (Citems)),
1754 To => Defining_Identifier (Last (Citems)),
1758 Layout_Components (Empty, Empty, Esiz, RM_Siz);
1761 -- Case where no variants are present in the component list
1765 -- The Esiz value has been correctly set by the call to
1766 -- Layout_Components, so there is nothing more to be done.
1768 -- For RM_Siz, we have an SO_Ref value, which we must convert
1769 -- to an appropriate expression.
1771 if Is_Static_SO_Ref (RM_Siz) then
1773 Make_Integer_Literal (Loc,
1777 RMS_Ent := Get_Dynamic_SO_Entity (RM_Siz);
1779 -- If the size is represented by a function, then we
1780 -- create an appropriate function call using V as
1781 -- the parameter to the call.
1783 if Is_Discrim_SO_Function (RMS_Ent) then
1785 Make_Function_Call (Loc,
1786 Name => New_Occurrence_Of (RMS_Ent, Loc),
1787 Parameter_Associations => New_List (
1788 Make_Identifier (Loc, Chars => Vname)));
1790 -- If the size is represented by a constant, then the
1791 -- expression we want is a reference to this constant
1794 RM_Siz_Expr := New_Occurrence_Of (RMS_Ent, Loc);
1798 -- Case where variants are present in this component list
1809 RM_Siz_Expr := Empty;
1812 Var := Last (Variants (Vpart));
1813 while Present (Var) loop
1815 Layout_Component_List
1816 (Component_List (Var), EsizV, RM_SizV);
1818 -- Set the Object_Size. If this is the first variant,
1819 -- we just set the size of this first variant.
1821 if Var = Last (Variants (Vpart)) then
1824 -- Otherwise the Object_Size is formed as a maximum
1825 -- of Esiz so far from previous variants, and the new
1826 -- Esiz value from the variant we just processed.
1828 -- If both values are static, we can just compute the
1829 -- maximum directly to save building junk nodes.
1831 elsif not Is_Dynamic_SO_Ref (Esiz)
1832 and then not Is_Dynamic_SO_Ref (EsizV)
1834 Esiz := UI_Max (Esiz, EsizV);
1836 -- If either value is dynamic, then we have to generate
1837 -- an appropriate Standard_Unsigned'Max attribute call.
1842 (Make_Attribute_Reference (Loc,
1843 Attribute_Name => Name_Max,
1845 New_Occurrence_Of (Standard_Unsigned, Loc),
1846 Expressions => New_List (
1847 Expr_From_SO_Ref (Loc, Esiz),
1848 Expr_From_SO_Ref (Loc, EsizV))),
1853 -- Now deal with Value_Size (RM_Siz). We are aiming at
1854 -- an expression that looks like:
1856 -- if xxDx (V.disc) then rmsiz1
1857 -- else if xxDx (V.disc) then rmsiz2
1860 -- Where rmsiz1, rmsiz2... are the RM_Siz values for the
1861 -- individual variants, and xxDx are the discriminant
1862 -- checking functions generated for the variant type.
1864 -- If this is the first variant, we simply set the
1865 -- result as the expression. Note that this takes
1866 -- care of the others case.
1868 if No (RM_Siz_Expr) then
1869 RM_Siz_Expr := RM_SizV;
1871 -- Otherwise construct the appropriate test
1874 -- Discriminant to be tested
1877 Make_Selected_Component (Loc,
1879 Make_Identifier (Loc, Chars => Vname),
1882 (Entity (Name (Vpart)), Loc));
1884 -- The test to be used in general is a call to the
1885 -- discriminant checking function. However, it is
1886 -- definitely worth special casing the very common
1887 -- case where a single value is involved.
1889 Dchoice := First (Discrete_Choices (Var));
1891 if No (Next (Dchoice))
1892 and then Nkind (Dchoice) /= N_Range
1896 Left_Opnd => Discrim,
1897 Right_Opnd => New_Copy (Dchoice));
1901 Make_Function_Call (Loc,
1904 (Dcheck_Function (Var), Loc),
1905 Parameter_Associations => New_List (Discrim));
1909 Make_Conditional_Expression (Loc,
1911 New_List (Dtest, RM_SizV, RM_Siz_Expr));
1918 end Layout_Component_List;
1920 -- Start of processing for Layout_Variant_Record
1923 -- We need the discriminant checking functions, since we generate
1924 -- calls to these functions for the RM_Size expression, so make
1925 -- sure that these functions have been constructed in time.
1927 Build_Discr_Checking_Funcs (Decl);
1929 -- Layout the discriminants
1932 (From => Defining_Identifier (First (Dlist)),
1933 To => Defining_Identifier (Last (Dlist)),
1937 -- Layout the main component list (this will make recursive calls
1938 -- to layout all component lists nested within variants).
1940 Layout_Component_List (Component_List (Tdef), Esiz, RM_Siz_Expr);
1941 Set_Esize (E, Esiz);
1943 -- If the RM_Size is a literal, set its value
1945 if Nkind (RM_Siz_Expr) = N_Integer_Literal then
1946 Set_RM_Size (E, Intval (RM_Siz_Expr));
1948 -- Otherwise we construct a dynamic SO_Ref
1957 end Layout_Variant_Record;
1959 -- Start of processing for Layout_Record_Type
1962 -- If this is a cloned subtype, just copy the size fields from the
1963 -- original, nothing else needs to be done in this case, since the
1964 -- components themselves are all shared.
1966 if (Ekind (E) = E_Record_Subtype
1967 or else Ekind (E) = E_Class_Wide_Subtype)
1968 and then Present (Cloned_Subtype (E))
1970 Set_Esize (E, Esize (Cloned_Subtype (E)));
1971 Set_RM_Size (E, RM_Size (Cloned_Subtype (E)));
1972 Set_Alignment (E, Alignment (Cloned_Subtype (E)));
1974 -- Another special case, class-wide types. The RM says that the size
1975 -- of such types is implementation defined (RM 13.3(48)). What we do
1976 -- here is to leave the fields set as unknown values, and the backend
1977 -- determines the actual behavior.
1979 elsif Ekind (E) = E_Class_Wide_Type then
1985 -- Initialize aligment conservatively to 1. This value will
1986 -- be increased as necessary during processing of the record.
1988 if Unknown_Alignment (E) then
1989 Set_Alignment (E, Uint_1);
1992 -- Initialize previous component. This is Empty unless there
1993 -- are components which have already been laid out by component
1994 -- clauses. If there are such components, we start our layout of
1995 -- the remaining components following the last such component
1999 Comp := First_Entity (E);
2000 while Present (Comp) loop
2001 if (Ekind (Comp) = E_Component
2002 or else Ekind (Comp) = E_Discriminant)
2003 and then Present (Component_Clause (Comp))
2007 Component_Bit_Offset (Comp) >
2008 Component_Bit_Offset (Prev_Comp)
2017 -- We have two separate circuits, one for non-variant records and
2018 -- one for variant records. For non-variant records, we simply go
2019 -- through the list of components. This handles all the non-variant
2020 -- cases including those cases of subtypes where there is no full
2021 -- type declaration, so the tree cannot be used to drive the layout.
2022 -- For variant records, we have to drive the layout from the tree
2023 -- since we need to understand the variant structure in this case.
2025 if Present (Full_View (E)) then
2026 Decl := Declaration_Node (Full_View (E));
2028 Decl := Declaration_Node (E);
2031 -- Scan all the components
2033 if Nkind (Decl) = N_Full_Type_Declaration
2034 and then Has_Discriminants (E)
2035 and then Nkind (Type_Definition (Decl)) = N_Record_Definition
2037 Present (Variant_Part (Component_List (Type_Definition (Decl))))
2039 Layout_Variant_Record;
2041 Layout_Non_Variant_Record;
2044 end Layout_Record_Type;
2050 procedure Layout_Type (E : Entity_Id) is
2052 -- For string literal types, for now, kill the size always, this
2053 -- is because gigi does not like or need the size to be set ???
2055 if Ekind (E) = E_String_Literal_Subtype then
2056 Set_Esize (E, Uint_0);
2057 Set_RM_Size (E, Uint_0);
2061 -- For access types, set size/alignment. This is system address
2062 -- size, except for fat pointers (unconstrained array access types),
2063 -- where the size is two times the address size, to accommodate the
2064 -- two pointers that are required for a fat pointer (data and
2065 -- template). Note that E_Access_Protected_Subprogram_Type is not
2066 -- an access type for this purpose since it is not a pointer but is
2067 -- equivalent to a record. For access subtypes, copy the size from
2068 -- the base type since Gigi represents them the same way.
2070 if Is_Access_Type (E) then
2072 -- If Esize already set (e.g. by a size clause), then nothing
2073 -- further to be done here.
2075 if Known_Esize (E) then
2078 -- Access to subprogram is a strange beast, and we let the
2079 -- backend figure out what is needed (it may be some kind
2080 -- of fat pointer, including the static link for example.
2082 elsif Ekind (E) = E_Access_Protected_Subprogram_Type then
2085 -- For access subtypes, copy the size information from base type
2087 elsif Ekind (E) = E_Access_Subtype then
2088 Set_Size_Info (E, Base_Type (E));
2089 Set_RM_Size (E, RM_Size (Base_Type (E)));
2091 -- For other access types, we use either address size, or, if
2092 -- a fat pointer is used (pointer-to-unconstrained array case),
2093 -- twice the address size to accommodate a fat pointer.
2097 Desig : Entity_Id := Designated_Type (E);
2100 if Is_Private_Type (Desig)
2101 and then Present (Full_View (Desig))
2103 Desig := Full_View (Desig);
2106 if (Is_Array_Type (Desig)
2107 and then not Is_Constrained (Desig)
2108 and then not Has_Completion_In_Body (Desig)
2109 and then not Debug_Flag_6)
2111 Init_Size (E, 2 * System_Address_Size);
2113 -- Check for bad convention set
2115 if Convention (E) = Convention_C
2117 Convention (E) = Convention_CPP
2120 ("?this access type does not " &
2121 "correspond to C pointer", E);
2125 Init_Size (E, System_Address_Size);
2130 Set_Prim_Alignment (E);
2132 -- Scalar types: set size and alignment
2134 elsif Is_Scalar_Type (E) then
2136 -- For discrete types, the RM_Size and Esize must be set
2137 -- already, since this is part of the earlier processing
2138 -- and the front end is always required to layout the
2139 -- sizes of such types (since they are available as static
2140 -- attributes). All we do is to check that this rule is
2143 if Is_Discrete_Type (E) then
2145 -- If the RM_Size is not set, then here is where we set it.
2147 -- Note: an RM_Size of zero looks like not set here, but this
2148 -- is a rare case, and we can simply reset it without any harm.
2150 if not Known_RM_Size (E) then
2151 Set_Discrete_RM_Size (E);
2154 -- If Esize for a discrete type is not set then set it
2156 if not Known_Esize (E) then
2162 -- If size is big enough, set it and exit
2164 if S >= RM_Size (E) then
2168 -- If the RM_Size is greater than 64 (happens only
2169 -- when strange values are specified by the user,
2170 -- then Esize is simply a copy of RM_Size, it will
2171 -- be further refined later on)
2174 Set_Esize (E, RM_Size (E));
2177 -- Otherwise double possible size and keep trying
2186 -- For non-discrete sclar types, if the RM_Size is not set,
2187 -- then set it now to a copy of the Esize if the Esize is set.
2190 if Known_Esize (E) and then Unknown_RM_Size (E) then
2191 Set_RM_Size (E, Esize (E));
2195 Set_Prim_Alignment (E);
2197 -- Non-primitive types
2200 -- If RM_Size is known, set Esize if not known
2202 if Known_RM_Size (E) and then Unknown_Esize (E) then
2204 -- If the alignment is known, we bump the Esize up to the
2205 -- next alignment boundary if it is not already on one.
2207 if Known_Alignment (E) then
2209 A : constant Uint := Alignment_In_Bits (E);
2210 S : constant SO_Ref := RM_Size (E);
2213 Set_Esize (E, (S * A + A - 1) / A);
2217 -- If Esize is set, and RM_Size is not, RM_Size is copied from
2218 -- Esize at least for now this seems reasonable, and is in any
2219 -- case needed for compatibility with old versions of gigi.
2220 -- look to be unknown.
2222 elsif Known_Esize (E) and then Unknown_RM_Size (E) then
2223 Set_RM_Size (E, Esize (E));
2226 -- For array base types, set component size if object size of
2227 -- the component type is known and is a small power of 2 (8,
2228 -- 16, 32, 64), since this is what will always be used.
2230 if Ekind (E) = E_Array_Type
2231 and then Unknown_Component_Size (E)
2234 CT : constant Entity_Id := Component_Type (E);
2237 -- For some reasons, access types can cause trouble,
2238 -- So let's just do this for discrete types ???
2241 and then Is_Discrete_Type (CT)
2242 and then Known_Static_Esize (CT)
2245 S : constant Uint := Esize (CT);
2253 Set_Component_Size (E, Esize (CT));
2261 -- Layout array and record types if front end layout set
2263 if Frontend_Layout_On_Target then
2264 if Is_Array_Type (E) and then not Is_Bit_Packed_Array (E) then
2265 Layout_Array_Type (E);
2266 elsif Is_Record_Type (E) then
2267 Layout_Record_Type (E);
2272 ---------------------
2273 -- Rewrite_Integer --
2274 ---------------------
2276 procedure Rewrite_Integer (N : Node_Id; V : Uint) is
2277 Loc : constant Source_Ptr := Sloc (N);
2278 Typ : constant Entity_Id := Etype (N);
2281 Rewrite (N, Make_Integer_Literal (Loc, Intval => V));
2283 end Rewrite_Integer;
2285 -------------------------------
2286 -- Set_And_Check_Static_Size --
2287 -------------------------------
2289 procedure Set_And_Check_Static_Size
2296 procedure Check_Size_Too_Small (Spec : Uint; Min : Uint);
2297 -- Spec is the number of bit specified in the size clause, and
2298 -- Min is the minimum computed size. An error is given that the
2299 -- specified size is too small if Spec < Min, and in this case
2300 -- both Esize and RM_Size are set to unknown in E. The error
2301 -- message is posted on node SC.
2303 procedure Check_Unused_Bits (Spec : Uint; Max : Uint);
2304 -- Spec is the number of bits specified in the size clause, and
2305 -- Max is the maximum computed size. A warning is given about
2306 -- unused bits if Spec > Max. This warning is posted on node SC.
2308 --------------------------
2309 -- Check_Size_Too_Small --
2310 --------------------------
2312 procedure Check_Size_Too_Small (Spec : Uint; Min : Uint) is
2315 Error_Msg_Uint_1 := Min;
2317 ("size for & too small, minimum allowed is ^", SC, E);
2321 end Check_Size_Too_Small;
2323 -----------------------
2324 -- Check_Unused_Bits --
2325 -----------------------
2327 procedure Check_Unused_Bits (Spec : Uint; Max : Uint) is
2330 Error_Msg_Uint_1 := Spec - Max;
2331 Error_Msg_NE ("?^ bits of & unused", SC, E);
2333 end Check_Unused_Bits;
2335 -- Start of processing for Set_And_Check_Static_Size
2338 -- Case where Object_Size (Esize) is already set by a size clause
2340 if Known_Static_Esize (E) then
2341 SC := Size_Clause (E);
2344 SC := Get_Attribute_Definition_Clause (E, Attribute_Object_Size);
2347 -- Perform checks on specified size against computed sizes
2349 if Present (SC) then
2350 Check_Unused_Bits (Esize (E), Esiz);
2351 Check_Size_Too_Small (Esize (E), RM_Siz);
2355 -- Case where Value_Size (RM_Size) is set by specific Value_Size
2356 -- clause (we do not need to worry about Value_Size being set by
2357 -- a Size clause, since that will have set Esize as well, and we
2358 -- already took care of that case).
2360 if Known_Static_RM_Size (E) then
2361 SC := Get_Attribute_Definition_Clause (E, Attribute_Value_Size);
2363 -- Perform checks on specified size against computed sizes
2365 if Present (SC) then
2366 Check_Unused_Bits (RM_Size (E), Esiz);
2367 Check_Size_Too_Small (RM_Size (E), RM_Siz);
2371 -- Set sizes if unknown
2373 if Unknown_Esize (E) then
2374 Set_Esize (E, Esiz);
2377 if Unknown_RM_Size (E) then
2378 Set_RM_Size (E, RM_Siz);
2380 end Set_And_Check_Static_Size;
2382 --------------------------
2383 -- Set_Discrete_RM_Size --
2384 --------------------------
2386 procedure Set_Discrete_RM_Size (Def_Id : Entity_Id) is
2387 FST : constant Entity_Id := First_Subtype (Def_Id);
2390 -- All discrete types except for the base types in standard
2391 -- are constrained, so indicate this by setting Is_Constrained.
2393 Set_Is_Constrained (Def_Id);
2395 -- We set generic types to have an unknown size, since the
2396 -- representation of a generic type is irrelevant, in view
2397 -- of the fact that they have nothing to do with code.
2399 if Is_Generic_Type (Root_Type (FST)) then
2400 Set_RM_Size (Def_Id, Uint_0);
2402 -- If the subtype statically matches the first subtype, then
2403 -- it is required to have exactly the same layout. This is
2404 -- required by aliasing considerations.
2406 elsif Def_Id /= FST and then
2407 Subtypes_Statically_Match (Def_Id, FST)
2409 Set_RM_Size (Def_Id, RM_Size (FST));
2410 Set_Size_Info (Def_Id, FST);
2412 -- In all other cases the RM_Size is set to the minimum size.
2413 -- Note that this routine is never called for subtypes for which
2414 -- the RM_Size is set explicitly by an attribute clause.
2417 Set_RM_Size (Def_Id, UI_From_Int (Minimum_Size (Def_Id)));
2419 end Set_Discrete_RM_Size;
2421 ------------------------
2422 -- Set_Prim_Alignment --
2423 ------------------------
2425 procedure Set_Prim_Alignment (E : Entity_Id) is
2427 -- Do not set alignment for packed array types, unless we are doing
2428 -- front end layout, because otherwise this is always handled in the
2431 if Is_Packed_Array_Type (E) and then not Frontend_Layout_On_Target then
2434 -- If there is an alignment clause, then we respect it
2436 elsif Has_Alignment_Clause (E) then
2439 -- If the size is not set, then don't attempt to set the alignment. This
2440 -- happens in the backend layout case for access to subprogram types.
2442 elsif not Known_Static_Esize (E) then
2445 -- For access types, do not set the alignment if the size is less than
2446 -- the allowed minimum size. This avoids cascaded error messages.
2448 elsif Is_Access_Type (E)
2449 and then Esize (E) < System_Address_Size
2454 -- Here we calculate the alignment as the largest power of two
2455 -- multiple of System.Storage_Unit that does not exceed either
2456 -- the actual size of the type, or the maximum allowed alignment.
2460 UI_To_Int (Esize (E)) / SSU;
2465 while 2 * A <= Ttypes.Maximum_Alignment
2471 -- Now we think we should set the alignment to A, but we
2472 -- skip this if an alignment is already set to a value
2473 -- greater than A (happens for derived types).
2475 -- However, if the alignment is known and too small it
2476 -- must be increased, this happens in a case like:
2478 -- type R is new Character;
2479 -- for R'Size use 16;
2481 -- Here the alignment inherited from Character is 1, but
2482 -- it must be increased to 2 to reflect the increased size.
2484 if Unknown_Alignment (E) or else Alignment (E) < A then
2485 Init_Alignment (E, A);
2488 end Set_Prim_Alignment;
2490 ----------------------
2491 -- SO_Ref_From_Expr --
2492 ----------------------
2494 function SO_Ref_From_Expr
2496 Ins_Type : Entity_Id;
2497 Vtype : Entity_Id := Empty)
2498 return Dynamic_SO_Ref
2500 Loc : constant Source_Ptr := Sloc (Ins_Type);
2502 K : constant Entity_Id :=
2503 Make_Defining_Identifier (Loc,
2504 Chars => New_Internal_Name ('K'));
2508 function Check_Node_V_Ref (N : Node_Id) return Traverse_Result;
2509 -- Function used to check one node for reference to V
2511 function Has_V_Ref is new Traverse_Func (Check_Node_V_Ref);
2512 -- Function used to traverse tree to check for reference to V
2514 ----------------------
2515 -- Check_Node_V_Ref --
2516 ----------------------
2518 function Check_Node_V_Ref (N : Node_Id) return Traverse_Result is
2520 if Nkind (N) = N_Identifier then
2521 if Chars (N) = Vname then
2530 end Check_Node_V_Ref;
2532 -- Start of processing for SO_Ref_From_Expr
2535 -- Case of expression is an integer literal, in this case we just
2536 -- return the value (which must always be non-negative, since size
2537 -- and offset values can never be negative).
2539 if Nkind (Expr) = N_Integer_Literal then
2540 pragma Assert (Intval (Expr) >= 0);
2541 return Intval (Expr);
2544 -- Case where there is a reference to V, create function
2546 if Has_V_Ref (Expr) = Abandon then
2548 pragma Assert (Present (Vtype));
2549 Set_Is_Discrim_SO_Function (K);
2552 Make_Subprogram_Body (Loc,
2555 Make_Function_Specification (Loc,
2556 Defining_Unit_Name => K,
2557 Parameter_Specifications => New_List (
2558 Make_Parameter_Specification (Loc,
2559 Defining_Identifier =>
2560 Make_Defining_Identifier (Loc, Chars => Vname),
2562 New_Occurrence_Of (Vtype, Loc))),
2564 New_Occurrence_Of (Standard_Unsigned, Loc)),
2566 Declarations => Empty_List,
2568 Handled_Statement_Sequence =>
2569 Make_Handled_Sequence_Of_Statements (Loc,
2570 Statements => New_List (
2571 Make_Return_Statement (Loc,
2572 Expression => Expr))));
2574 -- No reference to V, create constant
2578 Make_Object_Declaration (Loc,
2579 Defining_Identifier => K,
2580 Object_Definition =>
2581 New_Occurrence_Of (Standard_Unsigned, Loc),
2582 Constant_Present => True,
2583 Expression => Expr);
2586 Append_Freeze_Action (Ins_Type, Decl);
2588 return Create_Dynamic_SO_Ref (K);
2589 end SO_Ref_From_Expr;