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_Res; use Sem_Res;
43 with Sem_Util; use Sem_Util;
44 with Sinfo; use Sinfo;
45 with Snames; use Snames;
46 with Stand; use Stand;
47 with Targparm; use Targparm;
48 with Tbuild; use Tbuild;
49 with Ttypes; use Ttypes;
50 with Uintp; use Uintp;
52 package body Layout is
54 ------------------------
55 -- Local Declarations --
56 ------------------------
58 SSU : constant Int := Ttypes.System_Storage_Unit;
59 -- Short hand for System_Storage_Unit
61 Vname : constant Name_Id := Name_uV;
62 -- Formal parameter name used for functions generated for size offset
63 -- values that depend on the discriminant. All such functions have the
66 -- function xxx (V : vtyp) return Unsigned is
68 -- return ... expression involving V.discrim
71 -----------------------
72 -- Local Subprograms --
73 -----------------------
75 procedure Adjust_Esize_Alignment (E : Entity_Id);
76 -- E is the entity for a type or object. This procedure checks that the
77 -- size and alignment are compatible, and if not either gives an error
78 -- message if they cannot be adjusted or else adjusts them appropriately.
85 -- This is like Make_Op_Add except that it optimizes some cases knowing
86 -- that associative rearrangement is allowed for constant folding if one
87 -- of the operands is a compile time known value.
89 function Assoc_Multiply
94 -- This is like Make_Op_Multiply except that it optimizes some cases
95 -- knowing that associative rearrangement is allowed for constant
96 -- folding if one of the operands is a compile time known value
98 function Assoc_Subtract
101 Right_Opnd : Node_Id)
103 -- This is like Make_Op_Subtract except that it optimizes some cases
104 -- knowing that associative rearrangement is allowed for constant
105 -- folding if one of the operands is a compile time known value
107 function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id;
108 -- Given expressions for the low bound (Lo) and the high bound (Hi),
109 -- Build an expression for the value hi-lo+1, converted to type
110 -- Standard.Unsigned. Takes care of the case where the operands
111 -- are of an enumeration type (so that the subtraction cannot be
112 -- done directly) by applying the Pos operator to Hi/Lo first.
114 function Expr_From_SO_Ref
118 -- Given a value D from a size or offset field, return an expression
119 -- representing the value stored. If the value is known at compile time,
120 -- then an N_Integer_Literal is returned with the appropriate value. If
121 -- the value references a constant entity, then an N_Identifier node
122 -- referencing this entity is returned. The Loc value is used for the
123 -- Sloc value of constructed notes.
125 function SO_Ref_From_Expr
127 Ins_Type : Entity_Id;
128 Vtype : Entity_Id := Empty)
129 return Dynamic_SO_Ref;
130 -- This routine is used in the case where a size/offset value is dynamic
131 -- and is represented by the expression Expr. SO_Ref_From_Expr checks if
132 -- the Expr contains a reference to the identifier V, and if so builds
133 -- a function depending on discriminants of the formal parameter V which
134 -- is of type Vtype. If not, then a constant entity with the value Expr
135 -- is built. The result is a Dynamic_SO_Ref to the created entity. Note
136 -- that Vtype can be omitted if Expr does not contain any reference to V.
137 -- the created entity. The declaration created is inserted in the freeze
138 -- actions of Ins_Type, which also supplies the Sloc for created nodes.
139 -- This function also takes care of making sure that the expression is
140 -- properly analyzed and resolved (which may not be the case yet if we
141 -- build the expression in this unit).
143 function Get_Max_Size (E : Entity_Id) return Node_Id;
144 -- E is an array type or subtype that has at least one index bound that
145 -- is the value of a record discriminant. For such an array, the function
146 -- computes an expression that yields the maximum possible size of the
147 -- array in storage units. The result is not defined for any other type,
148 -- or for arrays that do not depend on discriminants, and it is a fatal
149 -- error to call this unless Size_Depends_On_Discrminant (E) is True.
151 procedure Layout_Array_Type (E : Entity_Id);
152 -- Front end layout of non-bit-packed array type or subtype
154 procedure Layout_Record_Type (E : Entity_Id);
155 -- Front end layout of record type
156 -- Variant records not handled yet ???
158 procedure Rewrite_Integer (N : Node_Id; V : Uint);
159 -- Rewrite node N with an integer literal whose value is V. The Sloc
160 -- for the new node is taken from N, and the type of the literal is
161 -- set to a copy of the type of N on entry.
163 procedure Set_And_Check_Static_Size
167 -- This procedure is called to check explicit given sizes (possibly
168 -- stored in the Esize and RM_Size fields of E) against computed
169 -- Object_Size (Esiz) and Value_Size (RM_Siz) values. Appropriate
170 -- errors and warnings are posted if specified sizes are inconsistent
171 -- with specified sizes. On return, the Esize and RM_Size fields of
172 -- E are set (either from previously given values, or from the newly
173 -- computed values, as appropriate).
175 ----------------------------
176 -- Adjust_Esize_Alignment --
177 ----------------------------
179 procedure Adjust_Esize_Alignment (E : Entity_Id) is
184 -- Nothing to do if size unknown
186 if Unknown_Esize (E) then
190 -- Determine if size is constrained by an attribute definition clause
191 -- which must be obeyed. If so, we cannot increase the size in this
194 -- For a type, the issue is whether an object size clause has been
195 -- set. A normal size clause constrains only the value size (RM_Size)
198 Esize_Set := Has_Object_Size_Clause (E);
200 -- For an object, the issue is whether a size clause is present
203 Esize_Set := Has_Size_Clause (E);
206 -- If size is known it must be a multiple of the byte size
208 if Esize (E) mod SSU /= 0 then
210 -- If not, and size specified, then give error
214 ("size for& not a multiple of byte size", Size_Clause (E), E);
217 -- Otherwise bump up size to a byte boundary
220 Set_Esize (E, (Esize (E) + SSU - 1) / SSU * SSU);
224 -- Now we have the size set, it must be a multiple of the alignment
225 -- nothing more we can do here if the alignment is unknown here.
227 if Unknown_Alignment (E) then
231 -- At this point both the Esize and Alignment are known, so we need
232 -- to make sure they are consistent.
234 Abits := UI_To_Int (Alignment (E)) * SSU;
236 if Esize (E) mod Abits = 0 then
240 -- Here we have a situation where the Esize is not a multiple of
241 -- the alignment. We must either increase Esize or reduce the
242 -- alignment to correct this situation.
244 -- The case in which we can decrease the alignment is where the
245 -- alignment was not set by an alignment clause, and the type in
246 -- question is a discrete type, where it is definitely safe to
247 -- reduce the alignment. For example:
249 -- t : integer range 1 .. 2;
252 -- In this situation, the initial alignment of t is 4, copied from
253 -- the Integer base type, but it is safe to reduce it to 1 at this
254 -- stage, since we will only be loading a single byte.
256 if Is_Discrete_Type (Etype (E))
257 and then not Has_Alignment_Clause (E)
261 exit when Esize (E) mod Abits = 0;
264 Init_Alignment (E, Abits / SSU);
268 -- Now the only possible approach left is to increase the Esize
269 -- but we can't do that if the size was set by a specific clause.
273 ("size for& is not a multiple of alignment",
276 -- Otherwise we can indeed increase the size to a multiple of alignment
279 Set_Esize (E, ((Esize (E) + (Abits - 1)) / Abits) * Abits);
281 end Adjust_Esize_Alignment;
290 Right_Opnd : Node_Id)
297 -- Case of right operand is a constant
299 if Compile_Time_Known_Value (Right_Opnd) then
301 R := Expr_Value (Right_Opnd);
303 -- Case of left operand is a constant
305 elsif Compile_Time_Known_Value (Left_Opnd) then
307 R := Expr_Value (Left_Opnd);
309 -- Neither operand is a constant, do the addition with no optimization
312 return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
315 -- Case of left operand is an addition
317 if Nkind (L) = N_Op_Add then
319 -- (C1 + E) + C2 = (C1 + C2) + E
321 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
323 (Sinfo.Left_Opnd (L),
324 Expr_Value (Sinfo.Left_Opnd (L)) + R);
327 -- (E + C1) + C2 = E + (C1 + C2)
329 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
331 (Sinfo.Right_Opnd (L),
332 Expr_Value (Sinfo.Right_Opnd (L)) + R);
336 -- Case of left operand is a subtraction
338 elsif Nkind (L) = N_Op_Subtract then
340 -- (C1 - E) + C2 = (C1 + C2) + E
342 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
344 (Sinfo.Left_Opnd (L),
345 Expr_Value (Sinfo.Left_Opnd (L)) + R);
348 -- (E - C1) + C2 = E - (C1 - C2)
350 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
352 (Sinfo.Right_Opnd (L),
353 Expr_Value (Sinfo.Right_Opnd (L)) - R);
358 -- Not optimizable, do the addition
360 return Make_Op_Add (Loc, Left_Opnd, Right_Opnd);
367 function Assoc_Multiply
370 Right_Opnd : Node_Id)
377 -- Case of right operand is a constant
379 if Compile_Time_Known_Value (Right_Opnd) then
381 R := Expr_Value (Right_Opnd);
383 -- Case of left operand is a constant
385 elsif Compile_Time_Known_Value (Left_Opnd) then
387 R := Expr_Value (Left_Opnd);
389 -- Neither operand is a constant, do the multiply with no optimization
392 return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
395 -- Case of left operand is an multiplication
397 if Nkind (L) = N_Op_Multiply then
399 -- (C1 * E) * C2 = (C1 * C2) + E
401 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
403 (Sinfo.Left_Opnd (L),
404 Expr_Value (Sinfo.Left_Opnd (L)) * R);
407 -- (E * C1) * C2 = E * (C1 * C2)
409 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
411 (Sinfo.Right_Opnd (L),
412 Expr_Value (Sinfo.Right_Opnd (L)) * R);
417 -- Not optimizable, do the multiplication
419 return Make_Op_Multiply (Loc, Left_Opnd, Right_Opnd);
426 function Assoc_Subtract
429 Right_Opnd : Node_Id)
436 -- Case of right operand is a constant
438 if Compile_Time_Known_Value (Right_Opnd) then
440 R := Expr_Value (Right_Opnd);
442 -- Right operand is a constant, do the subtract with no optimization
445 return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
448 -- Case of left operand is an addition
450 if Nkind (L) = N_Op_Add then
452 -- (C1 + E) - C2 = (C1 - C2) + E
454 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
456 (Sinfo.Left_Opnd (L),
457 Expr_Value (Sinfo.Left_Opnd (L)) - R);
460 -- (E + C1) - C2 = E + (C1 - C2)
462 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
464 (Sinfo.Right_Opnd (L),
465 Expr_Value (Sinfo.Right_Opnd (L)) - R);
469 -- Case of left operand is a subtraction
471 elsif Nkind (L) = N_Op_Subtract then
473 -- (C1 - E) - C2 = (C1 - C2) + E
475 if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
477 (Sinfo.Left_Opnd (L),
478 Expr_Value (Sinfo.Left_Opnd (L)) + R);
481 -- (E - C1) - C2 = E - (C1 + C2)
483 elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
485 (Sinfo.Right_Opnd (L),
486 Expr_Value (Sinfo.Right_Opnd (L)) + R);
491 -- Not optimizable, do the subtraction
493 return Make_Op_Subtract (Loc, Left_Opnd, Right_Opnd);
500 function Compute_Length (Lo : Node_Id; Hi : Node_Id) return Node_Id is
501 Loc : constant Source_Ptr := Sloc (Lo);
502 Typ : constant Entity_Id := Etype (Lo);
507 Lo_Op := New_Copy_Tree (Lo);
508 Hi_Op := New_Copy_Tree (Hi);
510 -- If type is enumeration type, then use Pos attribute to convert
511 -- to integer type for which subtraction is a permitted operation.
513 if Is_Enumeration_Type (Typ) then
515 Make_Attribute_Reference (Loc,
516 Prefix => New_Occurrence_Of (Typ, Loc),
517 Attribute_Name => Name_Pos,
518 Expressions => New_List (Lo_Op));
521 Make_Attribute_Reference (Loc,
522 Prefix => New_Occurrence_Of (Typ, Loc),
523 Attribute_Name => Name_Pos,
524 Expressions => New_List (Hi_Op));
528 Convert_To (Standard_Unsigned,
533 Right_Opnd => Lo_Op),
534 Right_Opnd => Make_Integer_Literal (Loc, 1)));
537 ----------------------
538 -- Expr_From_SO_Ref --
539 ----------------------
541 function Expr_From_SO_Ref
549 if Is_Dynamic_SO_Ref (D) then
550 Ent := Get_Dynamic_SO_Entity (D);
552 if Is_Discrim_SO_Function (Ent) then
554 Make_Function_Call (Loc,
555 Name => New_Occurrence_Of (Ent, Loc),
556 Parameter_Associations => New_List (
557 Make_Identifier (Loc, Chars => Vname)));
560 return New_Occurrence_Of (Ent, Loc);
564 return Make_Integer_Literal (Loc, D);
566 end Expr_From_SO_Ref;
572 function Get_Max_Size (E : Entity_Id) return Node_Id is
573 Loc : constant Source_Ptr := Sloc (E);
581 type Val_Status_Type is (Const, Dynamic);
582 -- Shows the status of the value so far. Const means that the value
583 -- is constant, and Sval is the current constant value. Dynamic means
584 -- that the value is dynamic, and in this case Snod is the Node_Id of
585 -- the expression to compute the value.
587 Val_Status : Val_Status_Type;
588 -- Indicate status of value so far
590 Sval : Uint := Uint_0;
591 -- Calculated value so far if Val_Status = Const
592 -- (initialized to prevent junk warning)
595 -- Expression value so far if Val_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 Layout_Array_Type
642 pragma Assert (Size_Depends_On_Discriminant (E));
644 -- Initialize status from component size
646 if Known_Static_Component_Size (E) then
648 Sval := Component_Size (E);
651 Val_Status := Dynamic;
652 Snod := Expr_From_SO_Ref (Loc, Component_Size (E));
655 -- Loop through indices
657 Indx := First_Index (E);
658 while Present (Indx) loop
659 Ityp := Etype (Indx);
660 Lo := Type_Low_Bound (Ityp);
661 Hi := Type_High_Bound (Ityp);
666 -- Value of the current subscript range is statically known
668 if Compile_Time_Known_Value (Lo)
669 and then Compile_Time_Known_Value (Hi)
671 S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
673 -- If known flat bound, entire size of array is zero!
676 return Make_Integer_Literal (Loc, 0);
679 -- Current value is constant, evolve value
681 if Val_Status = Const then
684 -- Current value is dynamic
687 -- An interesting little optimization, if we have a pending
688 -- conversion from bits to storage units, and the current
689 -- length is a multiple of the storage unit size, then we
690 -- can take the factor out here statically, avoiding some
691 -- extra dynamic computations at the end.
693 if SU_Convert_Required and then S mod SSU = 0 then
695 SU_Convert_Required := False;
702 Make_Integer_Literal (Loc, Intval => S));
705 -- Value of the current subscript range is dynamic
708 -- If the current size value is constant, then here is where we
709 -- make a transition to dynamic values, which are always stored
710 -- in storage units, However, we do not want to convert to SU's
711 -- too soon, consider the case of a packed array of single bits,
712 -- we want to do the SU conversion after computing the size in
715 if Val_Status = Const then
716 Val_Status := Dynamic;
718 -- If the current value is a multiple of the storage unit,
719 -- then most certainly we can do the conversion now, simply
720 -- by dividing the current value by the storage unit value.
721 -- If this works, we set SU_Convert_Required to False.
723 if Sval mod SSU = 0 then
724 Snod := Make_Integer_Literal (Loc, Sval / SSU);
725 SU_Convert_Required := False;
727 -- Otherwise, we go ahead and convert the value in bits,
728 -- and set SU_Convert_Required to True to ensure that the
729 -- final value is indeed properly converted.
732 Snod := Make_Integer_Literal (Loc, Sval);
733 SU_Convert_Required := True;
739 Len := Compute_Length (Lo, Hi);
741 -- Check possible range of Len
750 Determine_Range (Len, OK, LLo, LHi);
752 -- If we cannot verify that range cannot be super-flat,
753 -- we need a max with zero, since length must be non-neg.
755 if not OK or else LLo < 0 then
757 Make_Attribute_Reference (Loc,
759 New_Occurrence_Of (Standard_Unsigned, Loc),
760 Attribute_Name => Name_Max,
761 Expressions => New_List (
762 Make_Integer_Literal (Loc, 0),
771 -- Here after processing all bounds to set sizes. If the value is
772 -- a constant, then it is bits, and we just return the value.
774 if Val_Status = Const then
775 return Make_Integer_Literal (Loc, Sval);
777 -- Case where the value is dynamic
780 -- Do convert from bits to SU's if needed
782 if SU_Convert_Required then
784 -- The expression required is (Snod + SU - 1) / SU
791 Right_Opnd => Make_Integer_Literal (Loc, SSU - 1)),
792 Right_Opnd => Make_Integer_Literal (Loc, SSU));
799 -----------------------
800 -- Layout_Array_Type --
801 -----------------------
803 procedure Layout_Array_Type (E : Entity_Id) is
804 Loc : constant Source_Ptr := Sloc (E);
805 Ctyp : constant Entity_Id := Component_Type (E);
813 Insert_Typ : Entity_Id;
814 -- This is the type with which any generated constants or functions
815 -- will be associated (i.e. inserted into the freeze actions). This
816 -- is normally the type being layed out. The exception occurs when
817 -- we are laying out Itype's which are local to a record type, and
818 -- whose scope is this record type. Such types do not have freeze
819 -- nodes (because we have no place to put them).
821 ------------------------------------
822 -- How An Array Type is Layed Out --
823 ------------------------------------
825 -- Here is what goes on. We need to multiply the component size of
826 -- the array (which has already been set) by the length of each of
827 -- the indexes. If all these values are known at compile time, then
828 -- the resulting size of the array is the appropriate constant value.
830 -- If the component size or at least one bound is dynamic (but no
831 -- discriminants are present), then the size will be computed as an
832 -- expression that calculates the proper size.
834 -- If there is at least one discriminant bound, then the size is also
835 -- computed as an expression, but this expression contains discriminant
836 -- values which are obtained by selecting from a function parameter, and
837 -- the size is given by a function that is passed the variant record in
838 -- question, and whose body is the expression.
840 type Val_Status_Type is (Const, Dynamic, Discrim);
841 -- Shows the status of the value so far. Const means that the value
842 -- is constant, and Sval is the current constant value. Dynamic means
843 -- that the value is dynamic, and in this case Snod is the Node_Id of
844 -- the expression to compute the value, and Discrim means that at least
845 -- one bound is a discriminant, in which case Snod is the expression so
846 -- far (which will be the body of the function).
848 Val_Status : Val_Status_Type;
849 -- Indicate status of value so far
851 Sval : Uint := Uint_0;
852 -- Calculated value so far if Val_Status = Const
853 -- Initialized to prevent junk warning
856 -- Expression value so far if Val_Status /= Const
859 -- Variant record type for the formal parameter of the discriminant
860 -- function V if Val_Status = Discrim.
862 SU_Convert_Required : Boolean := False;
863 -- This is set to True if the final result must be converted from
864 -- bits to storage units (rounding up to a storage unit boundary).
866 procedure Discrimify (N : in out Node_Id);
867 -- If N represents a discriminant, then the Val_Status is set to
868 -- Discrim, and Vtyp is set. The parameter N is replaced with the
869 -- proper expression to extract the discriminant value from V.
875 procedure Discrimify (N : in out Node_Id) is
880 if Nkind (N) = N_Identifier
881 and then Ekind (Entity (N)) = E_Discriminant
883 Set_Size_Depends_On_Discriminant (E);
885 if Val_Status /= Discrim then
886 Val_Status := Discrim;
887 Decl := Parent (Parent (Entity (N)));
888 Vtyp := Defining_Identifier (Decl);
894 Make_Selected_Component (Loc,
895 Prefix => Make_Identifier (Loc, Chars => Vname),
896 Selector_Name => New_Occurrence_Of (Entity (N), Loc));
898 Analyze_And_Resolve (N, Typ);
902 -- Start of processing for Layout_Array_Type
905 -- Default alignment is component alignment
907 if Unknown_Alignment (E) then
908 Set_Alignment (E, Alignment (Ctyp));
911 -- Calculate proper type for insertions
913 if Is_Record_Type (Scope (E)) then
914 Insert_Typ := Scope (E);
919 -- Cannot do anything if Esize of component type unknown
921 if Unknown_Esize (Ctyp) then
925 -- Set component size if not set already
927 if Unknown_Component_Size (E) then
928 Set_Component_Size (E, Esize (Ctyp));
931 -- (RM 13.3 (48)) says that the size of an unconstrained array
932 -- is implementation defined. We choose to leave it as Unknown
933 -- here, and the actual behavior is determined by the back end.
935 if not Is_Constrained (E) then
939 -- Initialize status from component size
941 if Known_Static_Component_Size (E) then
943 Sval := Component_Size (E);
946 Val_Status := Dynamic;
947 Snod := Expr_From_SO_Ref (Loc, Component_Size (E));
950 -- Loop to process array indices
952 Indx := First_Index (E);
953 while Present (Indx) loop
954 Ityp := Etype (Indx);
955 Lo := Type_Low_Bound (Ityp);
956 Hi := Type_High_Bound (Ityp);
958 -- Value of the current subscript range is statically known
960 if Compile_Time_Known_Value (Lo)
961 and then Compile_Time_Known_Value (Hi)
963 S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
965 -- If known flat bound, entire size of array is zero!
968 Set_Esize (E, Uint_0);
969 Set_RM_Size (E, Uint_0);
973 -- If constant, evolve value
975 if Val_Status = Const then
978 -- Current value is dynamic
981 -- An interesting little optimization, if we have a pending
982 -- conversion from bits to storage units, and the current
983 -- length is a multiple of the storage unit size, then we
984 -- can take the factor out here statically, avoiding some
985 -- extra dynamic computations at the end.
987 if SU_Convert_Required and then S mod SSU = 0 then
989 SU_Convert_Required := False;
992 -- Now go ahead and evolve the expression
998 Make_Integer_Literal (Loc, Intval => S));
1001 -- Value of the current subscript range is dynamic
1004 -- If the current size value is constant, then here is where we
1005 -- make a transition to dynamic values, which are always stored
1006 -- in storage units, However, we do not want to convert to SU's
1007 -- too soon, consider the case of a packed array of single bits,
1008 -- we want to do the SU conversion after computing the size in
1011 if Val_Status = Const then
1012 Val_Status := Dynamic;
1014 -- If the current value is a multiple of the storage unit,
1015 -- then most certainly we can do the conversion now, simply
1016 -- by dividing the current value by the storage unit value.
1017 -- If this works, we set SU_Convert_Required to False.
1019 if Sval mod SSU = 0 then
1020 Snod := Make_Integer_Literal (Loc, Sval / SSU);
1021 SU_Convert_Required := False;
1023 -- Otherwise, we go ahead and convert the value in bits,
1024 -- and set SU_Convert_Required to True to ensure that the
1025 -- final value is indeed properly converted.
1028 Snod := Make_Integer_Literal (Loc, Sval);
1029 SU_Convert_Required := True;
1036 -- Length is hi-lo+1
1038 Len := Compute_Length (Lo, Hi);
1040 -- Check possible range of Len
1048 Set_Parent (Len, E);
1049 Determine_Range (Len, OK, LLo, LHi);
1051 -- If range definitely flat or superflat, result size is zero
1053 if OK and then LHi <= 0 then
1054 Set_Esize (E, Uint_0);
1055 Set_RM_Size (E, Uint_0);
1059 -- If we cannot verify that range cannot be super-flat, we
1060 -- need a maximum with zero, since length cannot be negative.
1062 if not OK or else LLo < 0 then
1064 Make_Attribute_Reference (Loc,
1066 New_Occurrence_Of (Standard_Unsigned, Loc),
1067 Attribute_Name => Name_Max,
1068 Expressions => New_List (
1069 Make_Integer_Literal (Loc, 0),
1074 -- At this stage, Len has the expression for the length
1077 Assoc_Multiply (Loc,
1085 -- Here after processing all bounds to set sizes. If the value is
1086 -- a constant, then it is bits, and the only thing we need to do
1087 -- is to check against explicit given size and do alignment adjust.
1089 if Val_Status = Const then
1090 Set_And_Check_Static_Size (E, Sval, Sval);
1091 Adjust_Esize_Alignment (E);
1093 -- Case where the value is dynamic
1096 -- Do convert from bits to SU's if needed
1098 if SU_Convert_Required then
1100 -- The expression required is (Snod + SU - 1) / SU
1103 Make_Op_Divide (Loc,
1107 Right_Opnd => Make_Integer_Literal (Loc, SSU - 1)),
1108 Right_Opnd => Make_Integer_Literal (Loc, SSU));
1111 -- Now set the dynamic size (the Value_Size is always the same
1112 -- as the Object_Size for arrays whose length is dynamic).
1114 Set_Esize (E, SO_Ref_From_Expr (Snod, Insert_Typ, Vtyp));
1115 Set_RM_Size (E, Esize (E));
1117 end Layout_Array_Type;
1123 procedure Layout_Object (E : Entity_Id) is
1124 T : constant Entity_Id := Etype (E);
1127 -- Nothing to do if backend does layout
1129 if not Frontend_Layout_On_Target then
1133 -- Set size if not set for object and known for type. Use the
1134 -- RM_Size if that is known for the type and Esize is not.
1136 if Unknown_Esize (E) then
1137 if Known_Esize (T) then
1138 Set_Esize (E, Esize (T));
1140 elsif Known_RM_Size (T) then
1141 Set_Esize (E, RM_Size (T));
1145 -- Set alignment from type if unknown and type alignment known
1147 if Unknown_Alignment (E) and then Known_Alignment (T) then
1148 Set_Alignment (E, Alignment (T));
1151 -- Make sure size and alignment are consistent
1153 Adjust_Esize_Alignment (E);
1155 -- Final adjustment, if we don't know the alignment, and the Esize
1156 -- was not set by an explicit Object_Size attribute clause, then
1157 -- we reset the Esize to unknown, since we really don't know it.
1159 if Unknown_Alignment (E)
1160 and then not Has_Size_Clause (E)
1162 Set_Esize (E, Uint_0);
1166 ------------------------
1167 -- Layout_Record_Type --
1168 ------------------------
1170 procedure Layout_Record_Type (E : Entity_Id) is
1171 Loc : constant Source_Ptr := Sloc (E);
1175 -- Current component being layed out
1177 Prev_Comp : Entity_Id;
1178 -- Previous layed out component
1180 procedure Get_Next_Component_Location
1181 (Prev_Comp : Entity_Id;
1183 New_Npos : out SO_Ref;
1184 New_Fbit : out SO_Ref;
1185 New_NPMax : out SO_Ref;
1186 Force_SU : Boolean);
1187 -- Given the previous component in Prev_Comp, which is already laid
1188 -- out, and the alignment of the following component, lays out the
1189 -- following component, and returns its starting position in New_Npos
1190 -- (Normalized_Position value), New_Fbit (Normalized_First_Bit value),
1191 -- and New_NPMax (Normalized_Position_Max value). If Prev_Comp is empty
1192 -- (no previous component is present), then New_Npos, New_Fbit and
1193 -- New_NPMax are all set to zero on return. This procedure is also
1194 -- used to compute the size of a record or variant by giving it the
1195 -- last component, and the record alignment. Force_SU is used to force
1196 -- the new component location to be aligned on a storage unit boundary,
1197 -- even in a packed record, False means that the new position does not
1198 -- need to be bumped to a storage unit boundary, True means a storage
1199 -- unit boundary is always required.
1201 procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id);
1202 -- Lays out component Comp, given Prev_Comp, the previously laid-out
1203 -- component (Prev_Comp = Empty if no components laid out yet). The
1204 -- alignment of the record itself is also updated if needed. Both
1205 -- Comp and Prev_Comp can be either components or discriminants. A
1206 -- special case is when Comp is Empty, this is used at the end
1207 -- to determine the size of the entire record. For this special
1208 -- call the resulting offset is placed in Final_Offset.
1210 procedure Layout_Components
1214 RM_Siz : out SO_Ref);
1215 -- This procedure lays out the components of the given component list
1216 -- which contains the components starting with From, and ending with To.
1217 -- The Next_Entity chain is used to traverse the components. On entry
1218 -- Prev_Comp is set to the component preceding the list, so that the
1219 -- list is layed out after this component. Prev_Comp is set to Empty if
1220 -- the component list is to be layed out starting at the start of the
1221 -- record. On return, the components are all layed out, and Prev_Comp is
1222 -- set to the last layed out component. On return, Esiz is set to the
1223 -- resulting Object_Size value, which is the length of the record up
1224 -- to and including the last layed out entity. For Esiz, the value is
1225 -- adjusted to match the alignment of the record. RM_Siz is similarly
1226 -- set to the resulting Value_Size value, which is the same length, but
1227 -- not adjusted to meet the alignment. Note that in the case of variant
1228 -- records, Esiz represents the maximum size.
1230 procedure Layout_Non_Variant_Record;
1231 -- Procedure called to layout a non-variant record type or subtype
1233 procedure Layout_Variant_Record;
1234 -- Procedure called to layout a variant record type. Decl is set to the
1235 -- full type declaration for the variant record.
1237 ---------------------------------
1238 -- Get_Next_Component_Location --
1239 ---------------------------------
1241 procedure Get_Next_Component_Location
1242 (Prev_Comp : Entity_Id;
1244 New_Npos : out SO_Ref;
1245 New_Fbit : out SO_Ref;
1246 New_NPMax : out SO_Ref;
1250 -- No previous component, return zero position
1252 if No (Prev_Comp) then
1255 New_NPMax := Uint_0;
1259 -- Here we have a previous component
1262 Loc : constant Source_Ptr := Sloc (Prev_Comp);
1264 Old_Npos : constant SO_Ref := Normalized_Position (Prev_Comp);
1265 Old_Fbit : constant SO_Ref := Normalized_First_Bit (Prev_Comp);
1266 Old_NPMax : constant SO_Ref := Normalized_Position_Max (Prev_Comp);
1267 Old_Esiz : constant SO_Ref := Esize (Prev_Comp);
1269 Old_Maxsz : Node_Id;
1270 -- Expression representing maximum size of previous component
1273 -- Case where previous field had a dynamic size
1275 if Is_Dynamic_SO_Ref (Esize (Prev_Comp)) then
1277 -- If the previous field had a dynamic length, then it is
1278 -- required to occupy an integral number of storage units,
1279 -- and start on a storage unit boundary. This means that
1280 -- the Normalized_First_Bit value is zero in the previous
1281 -- component, and the new value is also set to zero.
1285 -- In this case, the new position is given by an expression
1286 -- that is the sum of old normalized position and old size.
1291 Left_Opnd => Expr_From_SO_Ref (Loc, Old_Npos),
1292 Right_Opnd => Expr_From_SO_Ref (Loc, Old_Esiz)),
1296 -- Get maximum size of previous component
1298 if Size_Depends_On_Discriminant (Etype (Prev_Comp)) then
1299 Old_Maxsz := Get_Max_Size (Etype (Prev_Comp));
1301 Old_Maxsz := Expr_From_SO_Ref (Loc, Old_Esiz);
1304 -- Now we can compute the new max position. If the max size
1305 -- is static and the old position is static, then we can
1306 -- compute the new position statically.
1308 if Nkind (Old_Maxsz) = N_Integer_Literal
1309 and then Known_Static_Normalized_Position_Max (Prev_Comp)
1311 New_NPMax := Old_NPMax + Intval (Old_Maxsz);
1313 -- Otherwise new max position is dynamic
1319 Left_Opnd => Expr_From_SO_Ref (Loc, Old_NPMax),
1320 Right_Opnd => Old_Maxsz),
1325 -- Previous field has known static Esize
1328 New_Fbit := Old_Fbit + Old_Esiz;
1330 -- Bump New_Fbit to storage unit boundary if required
1332 if New_Fbit /= 0 and then Force_SU then
1333 New_Fbit := (New_Fbit + SSU - 1) / SSU * SSU;
1336 -- If old normalized position is static, we can go ahead
1337 -- and compute the new normalized position directly.
1339 if Known_Static_Normalized_Position (Prev_Comp) then
1340 New_Npos := Old_Npos;
1342 if New_Fbit >= SSU then
1343 New_Npos := New_Npos + New_Fbit / SSU;
1344 New_Fbit := New_Fbit mod SSU;
1347 -- Bump alignment if stricter than prev
1349 if Align > Alignment (Prev_Comp) then
1350 New_Npos := (New_Npos + Align - 1) / Align * Align;
1353 -- The max position is always equal to the position if
1354 -- the latter is static, since arrays depending on the
1355 -- values of discriminants never have static sizes.
1357 New_NPMax := New_Npos;
1360 -- Case of old normalized position is dynamic
1363 -- If new bit position is within the current storage unit,
1364 -- we can just copy the old position as the result position
1365 -- (we have already set the new first bit value).
1367 if New_Fbit < SSU then
1368 New_Npos := Old_Npos;
1369 New_NPMax := Old_NPMax;
1371 -- If new bit position is past the current storage unit, we
1372 -- need to generate a new dynamic value for the position
1373 -- ??? need to deal with alignment
1379 Left_Opnd => Expr_From_SO_Ref (Loc, Old_Npos),
1381 Make_Integer_Literal (Loc,
1382 Intval => New_Fbit / SSU)),
1389 Left_Opnd => Expr_From_SO_Ref (Loc, Old_NPMax),
1391 Make_Integer_Literal (Loc,
1392 Intval => New_Fbit / SSU)),
1395 New_Fbit := New_Fbit mod SSU;
1400 end Get_Next_Component_Location;
1402 ----------------------
1403 -- Layout_Component --
1404 ----------------------
1406 procedure Layout_Component (Comp : Entity_Id; Prev_Comp : Entity_Id) is
1407 Ctyp : constant Entity_Id := Etype (Comp);
1414 -- Parent field is always at start of record, this will overlap
1415 -- the actual fields that are part of the parent, and that's fine
1417 if Chars (Comp) = Name_uParent then
1418 Set_Normalized_Position (Comp, Uint_0);
1419 Set_Normalized_First_Bit (Comp, Uint_0);
1420 Set_Normalized_Position_Max (Comp, Uint_0);
1421 Set_Component_Bit_Offset (Comp, Uint_0);
1422 Set_Esize (Comp, Esize (Ctyp));
1426 -- Check case of type of component has a scope of the record we
1427 -- are laying out. When this happens, the type in question is an
1428 -- Itype that has not yet been layed out (that's because such
1429 -- types do not get frozen in the normal manner, because there
1430 -- is no place for the freeze nodes).
1432 if Scope (Ctyp) = E then
1436 -- Increase alignment of record if necessary. Note that we do not
1437 -- do this for packed records, which have an alignment of one by
1438 -- default, or for records for which an explicit alignment was
1439 -- specified with an alignment clause.
1441 if not Is_Packed (E)
1442 and then not Has_Alignment_Clause (E)
1443 and then Alignment (Ctyp) > Alignment (E)
1445 Set_Alignment (E, Alignment (Ctyp));
1448 -- If component already laid out, then we are done
1450 if Known_Normalized_Position (Comp) then
1454 -- Set size of component from type. We use the Esize except in a
1455 -- packed record, where we use the RM_Size (since that is exactly
1456 -- what the RM_Size value, as distinct from the Object_Size is
1459 if Is_Packed (E) then
1460 Set_Esize (Comp, RM_Size (Ctyp));
1462 Set_Esize (Comp, Esize (Ctyp));
1465 -- Compute the component position from the previous one. See if
1466 -- current component requires being on a storage unit boundary.
1468 -- If record is not packed, we always go to a storage unit boundary
1470 if not Is_Packed (E) then
1476 -- Elementary types do not need SU boundary in packed record
1478 if Is_Elementary_Type (Ctyp) then
1481 -- Packed array types with a modular packed array type do not
1482 -- force a storage unit boundary (since the code generation
1483 -- treats these as equivalent to the underlying modular type),
1485 elsif Is_Array_Type (Ctyp)
1486 and then Is_Bit_Packed_Array (Ctyp)
1487 and then Is_Modular_Integer_Type (Packed_Array_Type (Ctyp))
1491 -- Record types with known length less than or equal to the length
1492 -- of long long integer can also be unaligned, since they can be
1493 -- treated as scalars.
1495 elsif Is_Record_Type (Ctyp)
1496 and then not Is_Dynamic_SO_Ref (Esize (Ctyp))
1497 and then Esize (Ctyp) <= Esize (Standard_Long_Long_Integer)
1501 -- All other cases force a storage unit boundary, even when packed
1508 -- Now get the next component location
1510 Get_Next_Component_Location
1511 (Prev_Comp, Alignment (Ctyp), Npos, Fbit, NPMax, Forc);
1512 Set_Normalized_Position (Comp, Npos);
1513 Set_Normalized_First_Bit (Comp, Fbit);
1514 Set_Normalized_Position_Max (Comp, NPMax);
1516 -- Set Component_Bit_Offset in the static case
1518 if Known_Static_Normalized_Position (Comp)
1519 and then Known_Normalized_First_Bit (Comp)
1521 Set_Component_Bit_Offset (Comp, SSU * Npos + Fbit);
1523 end Layout_Component;
1525 -----------------------
1526 -- Layout_Components --
1527 -----------------------
1529 procedure Layout_Components
1533 RM_Siz : out SO_Ref)
1540 -- Only layout components if there are some to layout!
1542 if Present (From) then
1544 -- Layout components with no component clauses
1548 if (Ekind (Comp) = E_Component
1549 or else Ekind (Comp) = E_Discriminant)
1550 and then No (Component_Clause (Comp))
1552 Layout_Component (Comp, Prev_Comp);
1556 exit when Comp = To;
1561 -- Set size fields, both are zero if no components
1563 if No (Prev_Comp) then
1568 -- First the object size, for which we align past the last
1569 -- field to the alignment of the record (the object size
1570 -- is required to be a multiple of the alignment).
1572 Get_Next_Component_Location
1580 -- If the resulting normalized position is a dynamic reference,
1581 -- then the size is dynamic, and is stored in storage units.
1582 -- In this case, we set the RM_Size to the same value, it is
1583 -- simply not worth distinguishing Esize and RM_Size values in
1584 -- the dynamic case, since the RM has nothing to say about them.
1586 -- Note that a size cannot have been given in this case, since
1587 -- size specifications cannot be given for variable length types.
1590 Align : constant Uint := Alignment (E);
1593 if Is_Dynamic_SO_Ref (End_Npos) then
1596 -- Set the Object_Size allowing for alignment. In the
1597 -- dynamic case, we have to actually do the runtime
1598 -- computation. We can skip this in the non-packed
1599 -- record case if the last component has a smaller
1600 -- alignment than the overall record alignment.
1602 if Is_Dynamic_SO_Ref (End_NPMax) then
1606 or else Alignment (Prev_Comp) < Align
1608 -- The expression we build is
1609 -- (expr + align - 1) / align * align
1614 Make_Op_Multiply (Loc,
1616 Make_Op_Divide (Loc,
1620 Expr_From_SO_Ref (Loc, Esiz),
1622 Make_Integer_Literal (Loc,
1623 Intval => Align - 1)),
1625 Make_Integer_Literal (Loc, Align)),
1627 Make_Integer_Literal (Loc, Align)),
1632 -- Here Esiz is static, so we can adjust the alignment
1633 -- directly go give the required aligned value.
1636 Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
1639 -- Case where computed size is static
1642 -- The ending size was computed in Npos in storage units,
1643 -- but the actual size is stored in bits, so adjust
1644 -- accordingly. We also adjust the size to match the
1647 Esiz := (End_NPMax + Align - 1) / Align * Align * SSU;
1649 -- Compute the resulting Value_Size (RM_Size). For this
1650 -- purpose we do not force alignment of the record or
1651 -- storage size alignment of the result.
1653 Get_Next_Component_Location
1661 RM_Siz := End_Npos * SSU + End_Fbit;
1662 Set_And_Check_Static_Size (E, Esiz, RM_Siz);
1666 end Layout_Components;
1668 -------------------------------
1669 -- Layout_Non_Variant_Record --
1670 -------------------------------
1672 procedure Layout_Non_Variant_Record is
1677 Layout_Components (First_Entity (E), Last_Entity (E), Esiz, RM_Siz);
1678 Set_Esize (E, Esiz);
1679 Set_RM_Size (E, RM_Siz);
1680 end Layout_Non_Variant_Record;
1682 ---------------------------
1683 -- Layout_Variant_Record --
1684 ---------------------------
1686 procedure Layout_Variant_Record is
1687 Tdef : constant Node_Id := Type_Definition (Decl);
1688 Dlist : constant List_Id := Discriminant_Specifications (Decl);
1692 RM_Siz_Expr : Node_Id := Empty;
1693 -- Expression for the evolving RM_Siz value. This is typically a
1694 -- conditional expression which involves tests of discriminant
1695 -- values that are formed as references to the entity V. At
1696 -- the end of scanning all the components, a suitable function
1697 -- is constructed in which V is the parameter.
1699 -----------------------
1700 -- Local Subprograms --
1701 -----------------------
1703 procedure Layout_Component_List
1706 RM_Siz_Expr : out Node_Id);
1707 -- Recursive procedure, called to layout one component list
1708 -- Esiz and RM_Siz_Expr are set to the Object_Size and Value_Size
1709 -- values respectively representing the record size up to and
1710 -- including the last component in the component list (including
1711 -- any variants in this component list). RM_Siz_Expr is returned
1712 -- as an expression which may in the general case involve some
1713 -- references to the discriminants of the current record value,
1714 -- referenced by selecting from the entity V.
1716 ---------------------------
1717 -- Layout_Component_List --
1718 ---------------------------
1720 procedure Layout_Component_List
1723 RM_Siz_Expr : out Node_Id)
1725 Citems : constant List_Id := Component_Items (Clist);
1726 Vpart : constant Node_Id := Variant_Part (Clist);
1730 RMS_Ent : Entity_Id;
1733 if Is_Non_Empty_List (Citems) then
1735 (From => Defining_Identifier (First (Citems)),
1736 To => Defining_Identifier (Last (Citems)),
1740 Layout_Components (Empty, Empty, Esiz, RM_Siz);
1743 -- Case where no variants are present in the component list
1747 -- The Esiz value has been correctly set by the call to
1748 -- Layout_Components, so there is nothing more to be done.
1750 -- For RM_Siz, we have an SO_Ref value, which we must convert
1751 -- to an appropriate expression.
1753 if Is_Static_SO_Ref (RM_Siz) then
1755 Make_Integer_Literal (Loc,
1759 RMS_Ent := Get_Dynamic_SO_Entity (RM_Siz);
1761 -- If the size is represented by a function, then we
1762 -- create an appropriate function call using V as
1763 -- the parameter to the call.
1765 if Is_Discrim_SO_Function (RMS_Ent) then
1767 Make_Function_Call (Loc,
1768 Name => New_Occurrence_Of (RMS_Ent, Loc),
1769 Parameter_Associations => New_List (
1770 Make_Identifier (Loc, Chars => Vname)));
1772 -- If the size is represented by a constant, then the
1773 -- expression we want is a reference to this constant
1776 RM_Siz_Expr := New_Occurrence_Of (RMS_Ent, Loc);
1780 -- Case where variants are present in this component list
1791 RM_Siz_Expr := Empty;
1794 Var := Last (Variants (Vpart));
1795 while Present (Var) loop
1797 Layout_Component_List
1798 (Component_List (Var), EsizV, RM_SizV);
1800 -- Set the Object_Size. If this is the first variant,
1801 -- we just set the size of this first variant.
1803 if Var = Last (Variants (Vpart)) then
1806 -- Otherwise the Object_Size is formed as a maximum
1807 -- of Esiz so far from previous variants, and the new
1808 -- Esiz value from the variant we just processed.
1810 -- If both values are static, we can just compute the
1811 -- maximum directly to save building junk nodes.
1813 elsif not Is_Dynamic_SO_Ref (Esiz)
1814 and then not Is_Dynamic_SO_Ref (EsizV)
1816 Esiz := UI_Max (Esiz, EsizV);
1818 -- If either value is dynamic, then we have to generate
1819 -- an appropriate Standard_Unsigned'Max attribute call.
1824 (Make_Attribute_Reference (Loc,
1825 Attribute_Name => Name_Max,
1827 New_Occurrence_Of (Standard_Unsigned, Loc),
1828 Expressions => New_List (
1829 Expr_From_SO_Ref (Loc, Esiz),
1830 Expr_From_SO_Ref (Loc, EsizV))),
1835 -- Now deal with Value_Size (RM_Siz). We are aiming at
1836 -- an expression that looks like:
1838 -- if xxDx (V.disc) then rmsiz1
1839 -- else if xxDx (V.disc) then rmsiz2
1842 -- Where rmsiz1, rmsiz2... are the RM_Siz values for the
1843 -- individual variants, and xxDx are the discriminant
1844 -- checking functions generated for the variant type.
1846 -- If this is the first variant, we simply set the
1847 -- result as the expression. Note that this takes
1848 -- care of the others case.
1850 if No (RM_Siz_Expr) then
1851 RM_Siz_Expr := RM_SizV;
1853 -- Otherwise construct the appropriate test
1856 -- Discriminant to be tested
1859 Make_Selected_Component (Loc,
1861 Make_Identifier (Loc, Chars => Vname),
1864 (Entity (Name (Vpart)), Loc));
1866 -- The test to be used in general is a call to the
1867 -- discriminant checking function. However, it is
1868 -- definitely worth special casing the very common
1869 -- case where a single value is involved.
1871 Dchoice := First (Discrete_Choices (Var));
1873 if No (Next (Dchoice))
1874 and then Nkind (Dchoice) /= N_Range
1878 Left_Opnd => Discrim,
1879 Right_Opnd => New_Copy (Dchoice));
1883 Make_Function_Call (Loc,
1886 (Dcheck_Function (Var), Loc),
1887 Parameter_Associations => New_List (Discrim));
1891 Make_Conditional_Expression (Loc,
1893 New_List (Dtest, RM_SizV, RM_Siz_Expr));
1900 end Layout_Component_List;
1902 -- Start of processing for Layout_Variant_Record
1905 -- We need the discriminant checking functions, since we generate
1906 -- calls to these functions for the RM_Size expression, so make
1907 -- sure that these functions have been constructed in time.
1909 Build_Discr_Checking_Funcs (Decl);
1911 -- Layout the discriminants
1914 (From => Defining_Identifier (First (Dlist)),
1915 To => Defining_Identifier (Last (Dlist)),
1919 -- Layout the main component list (this will make recursive calls
1920 -- to layout all component lists nested within variants).
1922 Layout_Component_List (Component_List (Tdef), Esiz, RM_Siz_Expr);
1923 Set_Esize (E, Esiz);
1925 -- If the RM_Size is a literal, set its value
1927 if Nkind (RM_Siz_Expr) = N_Integer_Literal then
1928 Set_RM_Size (E, Intval (RM_Siz_Expr));
1930 -- Otherwise we construct a dynamic SO_Ref
1939 end Layout_Variant_Record;
1941 -- Start of processing for Layout_Record_Type
1944 -- If this is a cloned subtype, just copy the size fields from the
1945 -- original, nothing else needs to be done in this case, since the
1946 -- components themselves are all shared.
1948 if (Ekind (E) = E_Record_Subtype
1949 or else Ekind (E) = E_Class_Wide_Subtype)
1950 and then Present (Cloned_Subtype (E))
1952 Set_Esize (E, Esize (Cloned_Subtype (E)));
1953 Set_RM_Size (E, RM_Size (Cloned_Subtype (E)));
1954 Set_Alignment (E, Alignment (Cloned_Subtype (E)));
1956 -- Another special case, class-wide types. The RM says that the size
1957 -- of such types is implementation defined (RM 13.3(48)). What we do
1958 -- here is to leave the fields set as unknown values, and the backend
1959 -- determines the actual behavior.
1961 elsif Ekind (E) = E_Class_Wide_Type then
1967 -- Initialize aligment conservatively to 1. This value will
1968 -- be increased as necessary during processing of the record.
1970 if Unknown_Alignment (E) then
1971 Set_Alignment (E, Uint_1);
1974 -- Initialize previous component. This is Empty unless there
1975 -- are components which have already been laid out by component
1976 -- clauses. If there are such components, we start our layout of
1977 -- the remaining components following the last such component
1981 Comp := First_Entity (E);
1982 while Present (Comp) loop
1983 if (Ekind (Comp) = E_Component
1984 or else Ekind (Comp) = E_Discriminant)
1985 and then Present (Component_Clause (Comp))
1989 Component_Bit_Offset (Comp) >
1990 Component_Bit_Offset (Prev_Comp)
1999 -- We have two separate circuits, one for non-variant records and
2000 -- one for variant records. For non-variant records, we simply go
2001 -- through the list of components. This handles all the non-variant
2002 -- cases including those cases of subtypes where there is no full
2003 -- type declaration, so the tree cannot be used to drive the layout.
2004 -- For variant records, we have to drive the layout from the tree
2005 -- since we need to understand the variant structure in this case.
2007 if Present (Full_View (E)) then
2008 Decl := Declaration_Node (Full_View (E));
2010 Decl := Declaration_Node (E);
2013 -- Scan all the components
2015 if Nkind (Decl) = N_Full_Type_Declaration
2016 and then Has_Discriminants (E)
2017 and then Nkind (Type_Definition (Decl)) = N_Record_Definition
2019 Present (Variant_Part (Component_List (Type_Definition (Decl))))
2021 Layout_Variant_Record;
2023 Layout_Non_Variant_Record;
2026 end Layout_Record_Type;
2032 procedure Layout_Type (E : Entity_Id) is
2034 -- For string literal types, for now, kill the size always, this
2035 -- is because gigi does not like or need the size to be set ???
2037 if Ekind (E) = E_String_Literal_Subtype then
2038 Set_Esize (E, Uint_0);
2039 Set_RM_Size (E, Uint_0);
2043 -- For access types, set size/alignment. This is system address
2044 -- size, except for fat pointers (unconstrained array access types),
2045 -- where the size is two times the address size, to accommodate the
2046 -- two pointers that are required for a fat pointer (data and
2047 -- template). Note that E_Access_Protected_Subprogram_Type is not
2048 -- an access type for this purpose since it is not a pointer but is
2049 -- equivalent to a record. For access subtypes, copy the size from
2050 -- the base type since Gigi represents them the same way.
2052 if Is_Access_Type (E) then
2054 -- If Esize already set (e.g. by a size clause), then nothing
2055 -- further to be done here.
2057 if Known_Esize (E) then
2060 -- Access to subprogram is a strange beast, and we let the
2061 -- backend figure out what is needed (it may be some kind
2062 -- of fat pointer, including the static link for example.
2064 elsif Ekind (E) = E_Access_Protected_Subprogram_Type then
2067 -- For access subtypes, copy the size information from base type
2069 elsif Ekind (E) = E_Access_Subtype then
2070 Set_Size_Info (E, Base_Type (E));
2071 Set_RM_Size (E, RM_Size (Base_Type (E)));
2073 -- For other access types, we use either address size, or, if
2074 -- a fat pointer is used (pointer-to-unconstrained array case),
2075 -- twice the address size to accommodate a fat pointer.
2079 Desig : Entity_Id := Designated_Type (E);
2082 if Is_Private_Type (Desig)
2083 and then Present (Full_View (Desig))
2085 Desig := Full_View (Desig);
2088 if (Is_Array_Type (Desig)
2089 and then not Is_Constrained (Desig)
2090 and then not Has_Completion_In_Body (Desig)
2091 and then not Debug_Flag_6)
2093 Init_Size (E, 2 * System_Address_Size);
2095 -- Check for bad convention set
2097 if Convention (E) = Convention_C
2099 Convention (E) = Convention_CPP
2102 ("?this access type does not " &
2103 "correspond to C pointer", E);
2107 Init_Size (E, System_Address_Size);
2112 Set_Prim_Alignment (E);
2114 -- Scalar types: set size and alignment
2116 elsif Is_Scalar_Type (E) then
2118 -- For discrete types, the RM_Size and Esize must be set
2119 -- already, since this is part of the earlier processing
2120 -- and the front end is always required to layout the
2121 -- sizes of such types (since they are available as static
2122 -- attributes). All we do is to check that this rule is
2125 if Is_Discrete_Type (E) then
2127 -- If the RM_Size is not set, then here is where we set it.
2129 -- Note: an RM_Size of zero looks like not set here, but this
2130 -- is a rare case, and we can simply reset it without any harm.
2132 if not Known_RM_Size (E) then
2133 Set_Discrete_RM_Size (E);
2136 -- If Esize for a discrete type is not set then set it
2138 if not Known_Esize (E) then
2144 -- If size is big enough, set it and exit
2146 if S >= RM_Size (E) then
2150 -- If the RM_Size is greater than 64 (happens only
2151 -- when strange values are specified by the user,
2152 -- then Esize is simply a copy of RM_Size, it will
2153 -- be further refined later on)
2156 Set_Esize (E, RM_Size (E));
2159 -- Otherwise double possible size and keep trying
2168 -- For non-discrete sclar types, if the RM_Size is not set,
2169 -- then set it now to a copy of the Esize if the Esize is set.
2172 if Known_Esize (E) and then Unknown_RM_Size (E) then
2173 Set_RM_Size (E, Esize (E));
2177 Set_Prim_Alignment (E);
2179 -- Non-primitive types
2182 -- If RM_Size is known, set Esize if not known
2184 if Known_RM_Size (E) and then Unknown_Esize (E) then
2186 -- If the alignment is known, we bump the Esize up to the
2187 -- next alignment boundary if it is not already on one.
2189 if Known_Alignment (E) then
2191 A : constant Uint := Alignment_In_Bits (E);
2192 S : constant SO_Ref := RM_Size (E);
2195 Set_Esize (E, (S * A + A - 1) / A);
2199 -- If Esize is set, and RM_Size is not, RM_Size is copied from
2200 -- Esize at least for now this seems reasonable, and is in any
2201 -- case needed for compatibility with old versions of gigi.
2202 -- look to be unknown.
2204 elsif Known_Esize (E) and then Unknown_RM_Size (E) then
2205 Set_RM_Size (E, Esize (E));
2208 -- For array base types, set component size if object size of
2209 -- the component type is known and is a small power of 2 (8,
2210 -- 16, 32, 64), since this is what will always be used.
2212 if Ekind (E) = E_Array_Type
2213 and then Unknown_Component_Size (E)
2216 CT : constant Entity_Id := Component_Type (E);
2219 -- For some reasons, access types can cause trouble,
2220 -- So let's just do this for discrete types ???
2223 and then Is_Discrete_Type (CT)
2224 and then Known_Static_Esize (CT)
2227 S : constant Uint := Esize (CT);
2235 Set_Component_Size (E, Esize (CT));
2243 -- Layout array and record types if front end layout set
2245 if Frontend_Layout_On_Target then
2246 if Is_Array_Type (E) and then not Is_Bit_Packed_Array (E) then
2247 Layout_Array_Type (E);
2248 elsif Is_Record_Type (E) then
2249 Layout_Record_Type (E);
2254 ---------------------
2255 -- Rewrite_Integer --
2256 ---------------------
2258 procedure Rewrite_Integer (N : Node_Id; V : Uint) is
2259 Loc : constant Source_Ptr := Sloc (N);
2260 Typ : constant Entity_Id := Etype (N);
2263 Rewrite (N, Make_Integer_Literal (Loc, Intval => V));
2265 end Rewrite_Integer;
2267 -------------------------------
2268 -- Set_And_Check_Static_Size --
2269 -------------------------------
2271 procedure Set_And_Check_Static_Size
2278 procedure Check_Size_Too_Small (Spec : Uint; Min : Uint);
2279 -- Spec is the number of bit specified in the size clause, and
2280 -- Min is the minimum computed size. An error is given that the
2281 -- specified size is too small if Spec < Min, and in this case
2282 -- both Esize and RM_Size are set to unknown in E. The error
2283 -- message is posted on node SC.
2285 procedure Check_Unused_Bits (Spec : Uint; Max : Uint);
2286 -- Spec is the number of bits specified in the size clause, and
2287 -- Max is the maximum computed size. A warning is given about
2288 -- unused bits if Spec > Max. This warning is posted on node SC.
2290 --------------------------
2291 -- Check_Size_Too_Small --
2292 --------------------------
2294 procedure Check_Size_Too_Small (Spec : Uint; Min : Uint) is
2297 Error_Msg_Uint_1 := Min;
2299 ("size for & too small, minimum allowed is ^", SC, E);
2303 end Check_Size_Too_Small;
2305 -----------------------
2306 -- Check_Unused_Bits --
2307 -----------------------
2309 procedure Check_Unused_Bits (Spec : Uint; Max : Uint) is
2312 Error_Msg_Uint_1 := Spec - Max;
2313 Error_Msg_NE ("?^ bits of & unused", SC, E);
2315 end Check_Unused_Bits;
2317 -- Start of processing for Set_And_Check_Static_Size
2320 -- Case where Object_Size (Esize) is already set by a size clause
2322 if Known_Static_Esize (E) then
2323 SC := Size_Clause (E);
2326 SC := Get_Attribute_Definition_Clause (E, Attribute_Object_Size);
2329 -- Perform checks on specified size against computed sizes
2331 if Present (SC) then
2332 Check_Unused_Bits (Esize (E), Esiz);
2333 Check_Size_Too_Small (Esize (E), RM_Siz);
2337 -- Case where Value_Size (RM_Size) is set by specific Value_Size
2338 -- clause (we do not need to worry about Value_Size being set by
2339 -- a Size clause, since that will have set Esize as well, and we
2340 -- already took care of that case).
2342 if Known_Static_RM_Size (E) then
2343 SC := Get_Attribute_Definition_Clause (E, Attribute_Value_Size);
2345 -- Perform checks on specified size against computed sizes
2347 if Present (SC) then
2348 Check_Unused_Bits (RM_Size (E), Esiz);
2349 Check_Size_Too_Small (RM_Size (E), RM_Siz);
2353 -- Set sizes if unknown
2355 if Unknown_Esize (E) then
2356 Set_Esize (E, Esiz);
2359 if Unknown_RM_Size (E) then
2360 Set_RM_Size (E, RM_Siz);
2362 end Set_And_Check_Static_Size;
2364 --------------------------
2365 -- Set_Discrete_RM_Size --
2366 --------------------------
2368 procedure Set_Discrete_RM_Size (Def_Id : Entity_Id) is
2369 FST : constant Entity_Id := First_Subtype (Def_Id);
2372 -- All discrete types except for the base types in standard
2373 -- are constrained, so indicate this by setting Is_Constrained.
2375 Set_Is_Constrained (Def_Id);
2377 -- We set generic types to have an unknown size, since the
2378 -- representation of a generic type is irrelevant, in view
2379 -- of the fact that they have nothing to do with code.
2381 if Is_Generic_Type (Root_Type (FST)) then
2382 Set_RM_Size (Def_Id, Uint_0);
2384 -- If the subtype statically matches the first subtype, then
2385 -- it is required to have exactly the same layout. This is
2386 -- required by aliasing considerations.
2388 elsif Def_Id /= FST and then
2389 Subtypes_Statically_Match (Def_Id, FST)
2391 Set_RM_Size (Def_Id, RM_Size (FST));
2392 Set_Size_Info (Def_Id, FST);
2394 -- In all other cases the RM_Size is set to the minimum size.
2395 -- Note that this routine is never called for subtypes for which
2396 -- the RM_Size is set explicitly by an attribute clause.
2399 Set_RM_Size (Def_Id, UI_From_Int (Minimum_Size (Def_Id)));
2401 end Set_Discrete_RM_Size;
2403 ------------------------
2404 -- Set_Prim_Alignment --
2405 ------------------------
2407 procedure Set_Prim_Alignment (E : Entity_Id) is
2409 -- Do not set alignment for packed array types, unless we are doing
2410 -- front end layout, because otherwise this is always handled in the
2413 if Is_Packed_Array_Type (E) and then not Frontend_Layout_On_Target then
2416 -- If there is an alignment clause, then we respect it
2418 elsif Has_Alignment_Clause (E) then
2421 -- If the size is not set, then don't attempt to set the alignment. This
2422 -- happens in the backend layout case for access to subprogram types.
2424 elsif not Known_Static_Esize (E) then
2427 -- For access types, do not set the alignment if the size is less than
2428 -- the allowed minimum size. This avoids cascaded error messages.
2430 elsif Is_Access_Type (E)
2431 and then Esize (E) < System_Address_Size
2436 -- Here we calculate the alignment as the largest power of two
2437 -- multiple of System.Storage_Unit that does not exceed either
2438 -- the actual size of the type, or the maximum allowed alignment.
2442 UI_To_Int (Esize (E)) / SSU;
2447 while 2 * A <= Ttypes.Maximum_Alignment
2453 -- Now we think we should set the alignment to A, but we
2454 -- skip this if an alignment is already set to a value
2455 -- greater than A (happens for derived types).
2457 -- However, if the alignment is known and too small it
2458 -- must be increased, this happens in a case like:
2460 -- type R is new Character;
2461 -- for R'Size use 16;
2463 -- Here the alignment inherited from Character is 1, but
2464 -- it must be increased to 2 to reflect the increased size.
2466 if Unknown_Alignment (E) or else Alignment (E) < A then
2467 Init_Alignment (E, A);
2470 end Set_Prim_Alignment;
2472 ----------------------
2473 -- SO_Ref_From_Expr --
2474 ----------------------
2476 function SO_Ref_From_Expr
2478 Ins_Type : Entity_Id;
2479 Vtype : Entity_Id := Empty)
2480 return Dynamic_SO_Ref
2482 Loc : constant Source_Ptr := Sloc (Ins_Type);
2484 K : constant Entity_Id :=
2485 Make_Defining_Identifier (Loc,
2486 Chars => New_Internal_Name ('K'));
2490 function Check_Node_V_Ref (N : Node_Id) return Traverse_Result;
2491 -- Function used to check one node for reference to V
2493 function Has_V_Ref is new Traverse_Func (Check_Node_V_Ref);
2494 -- Function used to traverse tree to check for reference to V
2496 ----------------------
2497 -- Check_Node_V_Ref --
2498 ----------------------
2500 function Check_Node_V_Ref (N : Node_Id) return Traverse_Result is
2502 if Nkind (N) = N_Identifier then
2503 if Chars (N) = Vname then
2512 end Check_Node_V_Ref;
2514 -- Start of processing for SO_Ref_From_Expr
2517 -- Case of expression is an integer literal, in this case we just
2518 -- return the value (which must always be non-negative, since size
2519 -- and offset values can never be negative).
2521 if Nkind (Expr) = N_Integer_Literal then
2522 pragma Assert (Intval (Expr) >= 0);
2523 return Intval (Expr);
2526 -- Case where there is a reference to V, create function
2528 if Has_V_Ref (Expr) = Abandon then
2530 pragma Assert (Present (Vtype));
2531 Set_Is_Discrim_SO_Function (K);
2534 Make_Subprogram_Body (Loc,
2537 Make_Function_Specification (Loc,
2538 Defining_Unit_Name => K,
2539 Parameter_Specifications => New_List (
2540 Make_Parameter_Specification (Loc,
2541 Defining_Identifier =>
2542 Make_Defining_Identifier (Loc, Chars => Vname),
2544 New_Occurrence_Of (Vtype, Loc))),
2546 New_Occurrence_Of (Standard_Unsigned, Loc)),
2548 Declarations => Empty_List,
2550 Handled_Statement_Sequence =>
2551 Make_Handled_Sequence_Of_Statements (Loc,
2552 Statements => New_List (
2553 Make_Return_Statement (Loc,
2554 Expression => Expr))));
2556 -- No reference to V, create constant
2560 Make_Object_Declaration (Loc,
2561 Defining_Identifier => K,
2562 Object_Definition =>
2563 New_Occurrence_Of (Standard_Unsigned, Loc),
2564 Constant_Present => True,
2565 Expression => Expr);
2568 Append_Freeze_Action (Ins_Type, Decl);
2570 return Create_Dynamic_SO_Ref (K);
2571 end SO_Ref_From_Expr;