1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1999-2002 Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
34 with Alloc
; use Alloc
;
35 with Atree
; use Atree
;
36 with Casing
; use Casing
;
37 with Debug
; use Debug
;
38 with Einfo
; use Einfo
;
40 with Namet
; use Namet
;
42 with Output
; use Output
;
43 with Sinfo
; use Sinfo
;
44 with Sinput
; use Sinput
;
45 with Table
; use Table
;
46 with Uname
; use Uname
;
47 with Urealp
; use Urealp
;
49 package body Repinfo
is
52 -- Value for Storage_Unit, we do not want to get this from TTypes, since
53 -- this introduces problematic dependencies in ASIS, and in any case this
54 -- value is assumed to be 8 for the implementation of the DDA.
55 -- This is wrong for AAMP???
57 ---------------------------------------
58 -- Representation of gcc Expressions --
59 ---------------------------------------
61 -- This table is used only if Frontend_Layout_On_Target is False,
62 -- so that gigi lays out dynamic size/offset fields using encoded
65 -- A table internal to this unit is used to hold the values of
66 -- back annotated expressions. This table is written out by -gnatt
67 -- and read back in for ASIS processing.
69 -- Node values are stored as Uint values which are the negative of
70 -- the node index in this table. Constants appear as non-negative
73 type Exp_Node
is record
75 Op1
: Node_Ref_Or_Val
;
76 Op2
: Node_Ref_Or_Val
;
77 Op3
: Node_Ref_Or_Val
;
80 package Rep_Table
is new Table
.Table
(
81 Table_Component_Type
=> Exp_Node
,
82 Table_Index_Type
=> Nat
,
84 Table_Initial
=> Alloc
.Rep_Table_Initial
,
85 Table_Increment
=> Alloc
.Rep_Table_Increment
,
86 Table_Name
=> "BE_Rep_Table");
88 --------------------------------------------------------------
89 -- Representation of Front-End Dynamic Size/Offset Entities --
90 --------------------------------------------------------------
92 package Dynamic_SO_Entity_Table
is new Table
.Table
(
93 Table_Component_Type
=> Entity_Id
,
94 Table_Index_Type
=> Nat
,
96 Table_Initial
=> Alloc
.Rep_Table_Initial
,
97 Table_Increment
=> Alloc
.Rep_Table_Increment
,
98 Table_Name
=> "FE_Rep_Table");
100 -----------------------
101 -- Local Subprograms --
102 -----------------------
104 Unit_Casing
: Casing_Type
;
105 -- Identifier casing for current unit
107 procedure Spaces
(N
: Natural);
108 -- Output given number of spaces
110 function Back_End_Layout
return Boolean;
111 -- Test for layout mode, True = back end, False = front end. This
112 -- function is used rather than checking the configuration parameter
113 -- because we do not want Repinfo to depend on Targparm (for ASIS)
115 procedure List_Entities
(Ent
: Entity_Id
);
116 -- This procedure lists the entities associated with the entity E,
117 -- starting with the First_Entity and using the Next_Entity link.
118 -- If a nested package is found, entities within the package are
119 -- recursively processed.
121 procedure List_Name
(Ent
: Entity_Id
);
122 -- List name of entity Ent in appropriate case. The name is listed with
123 -- full qualification up to but not including the compilation unit name.
125 procedure List_Array_Info
(Ent
: Entity_Id
);
126 -- List representation info for array type Ent
128 procedure List_Object_Info
(Ent
: Entity_Id
);
129 -- List representation info for object Ent
131 procedure List_Record_Info
(Ent
: Entity_Id
);
132 -- List representation info for record type Ent
134 procedure List_Type_Info
(Ent
: Entity_Id
);
135 -- List type info for type Ent
137 function Rep_Not_Constant
(Val
: Node_Ref_Or_Val
) return Boolean;
138 -- Returns True if Val represents a variable value, and False if it
139 -- represents a value that is fixed at compile time.
141 procedure Write_Info_Line
(S
: String);
142 -- Routine to write a line to Repinfo output file. This routine is
143 -- passed as a special output procedure to Output.Set_Special_Output.
144 -- Note that Write_Info_Line is called with an EOL character at the
145 -- end of each line, as per the Output spec, but the internal call
146 -- to the appropriate routine in Osint requires that the end of line
147 -- sequence be stripped off.
149 procedure Write_Val
(Val
: Node_Ref_Or_Val
; Paren
: Boolean := False);
150 -- Given a representation value, write it out. No_Uint values or values
151 -- dependent on discriminants are written as two question marks. If the
152 -- flag Paren is set, then the output is surrounded in parentheses if
153 -- it is other than a simple value.
155 ---------------------
156 -- Back_End_Layout --
157 ---------------------
159 function Back_End_Layout
return Boolean is
161 -- We have back end layout if the back end has made any entries in
162 -- the table of GCC expressions, otherwise we have front end layout.
164 return Rep_Table
.Last
> 0;
167 ------------------------
168 -- Create_Discrim_Ref --
169 ------------------------
171 function Create_Discrim_Ref
175 N
: constant Uint
:= Discriminant_Number
(Discr
);
179 Rep_Table
.Increment_Last
;
181 Rep_Table
.Table
(T
).Expr
:= Discrim_Val
;
182 Rep_Table
.Table
(T
).Op1
:= N
;
183 Rep_Table
.Table
(T
).Op2
:= No_Uint
;
184 Rep_Table
.Table
(T
).Op3
:= No_Uint
;
185 return UI_From_Int
(-T
);
186 end Create_Discrim_Ref
;
188 ---------------------------
189 -- Create_Dynamic_SO_Ref --
190 ---------------------------
192 function Create_Dynamic_SO_Ref
194 return Dynamic_SO_Ref
199 Dynamic_SO_Entity_Table
.Increment_Last
;
200 T
:= Dynamic_SO_Entity_Table
.Last
;
201 Dynamic_SO_Entity_Table
.Table
(T
) := E
;
202 return UI_From_Int
(-T
);
203 end Create_Dynamic_SO_Ref
;
211 Op1
: Node_Ref_Or_Val
;
212 Op2
: Node_Ref_Or_Val
:= No_Uint
;
213 Op3
: Node_Ref_Or_Val
:= No_Uint
)
219 Rep_Table
.Increment_Last
;
221 Rep_Table
.Table
(T
).Expr
:= Expr
;
222 Rep_Table
.Table
(T
).Op1
:= Op1
;
223 Rep_Table
.Table
(T
).Op2
:= Op2
;
224 Rep_Table
.Table
(T
).Op3
:= Op3
;
226 return UI_From_Int
(-T
);
229 ---------------------------
230 -- Get_Dynamic_SO_Entity --
231 ---------------------------
233 function Get_Dynamic_SO_Entity
238 return Dynamic_SO_Entity_Table
.Table
(-UI_To_Int
(U
));
239 end Get_Dynamic_SO_Entity
;
241 -----------------------
242 -- Is_Dynamic_SO_Ref --
243 -----------------------
245 function Is_Dynamic_SO_Ref
(U
: SO_Ref
) return Boolean is
248 end Is_Dynamic_SO_Ref
;
250 ----------------------
251 -- Is_Static_SO_Ref --
252 ----------------------
254 function Is_Static_SO_Ref
(U
: SO_Ref
) return Boolean is
257 end Is_Static_SO_Ref
;
263 procedure lgx
(U
: Node_Ref_Or_Val
) is
265 List_GCC_Expression
(U
);
269 ----------------------
270 -- List_Array_Info --
271 ----------------------
273 procedure List_Array_Info
(Ent
: Entity_Id
) is
275 List_Type_Info
(Ent
);
279 Write_Str
("'Component_Size use ");
280 Write_Val
(Component_Size
(Ent
));
288 procedure List_Entities
(Ent
: Entity_Id
) is
292 if Present
(Ent
) then
293 E
:= First_Entity
(Ent
);
294 while Present
(E
) loop
296 -- We list entities that come from source (excluding private
297 -- types, where we will list the info for the full view). If
298 -- debug flag A is set, all entities are listed
300 if (Comes_From_Source
(E
) and then not Is_Private_Type
(E
))
301 or else Debug_Flag_AA
303 if Is_Record_Type
(E
) then
304 List_Record_Info
(E
);
306 elsif Is_Array_Type
(E
) then
309 elsif List_Representation_Info
>= 2 then
313 elsif Ekind
(E
) = E_Variable
315 Ekind
(E
) = E_Constant
317 Ekind
(E
) = E_Loop_Parameter
321 List_Object_Info
(E
);
325 -- Recurse into nested package, but not if they are
326 -- package renamings (in particular renamings of the
327 -- enclosing package, as for some Java bindings and
328 -- for generic instances).
330 if Ekind
(E
) = E_Package
then
331 if No
(Renamed_Object
(E
)) then
335 -- Recurse into bodies
337 elsif Ekind
(E
) = E_Protected_Type
339 Ekind
(E
) = E_Task_Type
341 Ekind
(E
) = E_Subprogram_Body
343 Ekind
(E
) = E_Package_Body
345 Ekind
(E
) = E_Task_Body
347 Ekind
(E
) = E_Protected_Body
351 -- Recurse into blocks
353 elsif Ekind
(E
) = E_Block
then
358 E
:= Next_Entity
(E
);
363 -------------------------
364 -- List_GCC_Expression --
365 -------------------------
367 procedure List_GCC_Expression
(U
: Node_Ref_Or_Val
) is
369 procedure P
(Val
: Node_Ref_Or_Val
);
370 -- Internal recursive procedure to print expression
372 procedure P
(Val
: Node_Ref_Or_Val
) is
375 UI_Write
(Val
, Decimal
);
379 Node
: Exp_Node
renames Rep_Table
.Table
(-UI_To_Int
(Val
));
381 procedure Binop
(S
: String);
382 -- Output text for binary operator with S being operator name
384 procedure Binop
(S
: String) is
393 -- Start of processing for P
400 Write_Str
(" then ");
402 Write_Str
(" else ");
415 when Trunc_Div_Expr
=>
418 when Ceil_Div_Expr
=>
421 when Floor_Div_Expr
=>
424 when Trunc_Mod_Expr
=>
427 when Floor_Mod_Expr
=>
430 when Ceil_Mod_Expr
=>
433 when Exact_Div_Expr
=>
450 when Truth_Andif_Expr
=>
453 when Truth_Orif_Expr
=>
456 when Truth_And_Expr
=>
459 when Truth_Or_Expr
=>
462 when Truth_Xor_Expr
=>
465 when Truth_Not_Expr
=>
496 -- Start of processing for List_GCC_Expression
504 end List_GCC_Expression
;
510 procedure List_Name
(Ent
: Entity_Id
) is
512 if not Is_Compilation_Unit
(Scope
(Ent
)) then
513 List_Name
(Scope
(Ent
));
517 Get_Unqualified_Decoded_Name_String
(Chars
(Ent
));
518 Set_Casing
(Unit_Casing
);
519 Write_Str
(Name_Buffer
(1 .. Name_Len
));
522 ---------------------
523 -- List_Object_Info --
524 ---------------------
526 procedure List_Object_Info
(Ent
: Entity_Id
) is
532 Write_Str
("'Size use ");
533 Write_Val
(Esize
(Ent
));
538 Write_Str
("'Alignment use ");
539 Write_Val
(Alignment
(Ent
));
541 end List_Object_Info
;
543 ----------------------
544 -- List_Record_Info --
545 ----------------------
547 procedure List_Record_Info
(Ent
: Entity_Id
) is
553 Max_Name_Length
: Natural;
554 Max_Suni_Length
: Natural;
557 List_Type_Info
(Ent
);
561 Write_Line
(" use record");
563 -- First loop finds out max line length and max starting position
564 -- length, for the purpose of lining things up nicely.
566 Max_Name_Length
:= 0;
567 Max_Suni_Length
:= 0;
569 Comp
:= First_Entity
(Ent
);
570 while Present
(Comp
) loop
571 if Ekind
(Comp
) = E_Component
572 or else Ekind
(Comp
) = E_Discriminant
574 Get_Decoded_Name_String
(Chars
(Comp
));
575 Max_Name_Length
:= Natural'Max (Max_Name_Length
, Name_Len
);
577 Cfbit
:= Component_Bit_Offset
(Comp
);
579 if Rep_Not_Constant
(Cfbit
) then
580 UI_Image_Length
:= 2;
583 -- Complete annotation in case not done
585 Set_Normalized_Position
(Comp
, Cfbit
/ SSU
);
586 Set_Normalized_First_Bit
(Comp
, Cfbit
mod SSU
);
588 Esiz
:= Esize
(Comp
);
589 Sunit
:= Cfbit
/ SSU
;
593 -- If the record is not packed, then we know that all
594 -- fields whose position is not specified have a starting
595 -- normalized bit position of zero
597 if Unknown_Normalized_First_Bit
(Comp
)
598 and then not Is_Packed
(Ent
)
600 Set_Normalized_First_Bit
(Comp
, Uint_0
);
604 Natural'Max (Max_Suni_Length
, UI_Image_Length
);
607 Comp
:= Next_Entity
(Comp
);
610 -- Second loop does actual output based on those values
612 Comp
:= First_Entity
(Ent
);
613 while Present
(Comp
) loop
614 if Ekind
(Comp
) = E_Component
615 or else Ekind
(Comp
) = E_Discriminant
618 Esiz
: constant Uint
:= Esize
(Comp
);
619 Bofs
: constant Uint
:= Component_Bit_Offset
(Comp
);
620 Npos
: constant Uint
:= Normalized_Position
(Comp
);
621 Fbit
: constant Uint
:= Normalized_First_Bit
(Comp
);
626 Get_Decoded_Name_String
(Chars
(Comp
));
627 Set_Casing
(Unit_Casing
);
628 Write_Str
(Name_Buffer
(1 .. Name_Len
));
630 for J
in 1 .. Max_Name_Length
- Name_Len
loop
636 if Known_Static_Normalized_Position
(Comp
) then
638 Spaces
(Max_Suni_Length
- UI_Image_Length
);
639 Write_Str
(UI_Image_Buffer
(1 .. UI_Image_Length
));
641 elsif Known_Component_Bit_Offset
(Comp
)
642 and then List_Representation_Info
= 3
644 Spaces
(Max_Suni_Length
- 2);
645 Write_Str
("bit offset");
646 Write_Val
(Bofs
, Paren
=> True);
647 Write_Str
(" size in bits = ");
648 Write_Val
(Esiz
, Paren
=> True);
652 elsif Known_Normalized_Position
(Comp
)
653 and then List_Representation_Info
= 3
655 Spaces
(Max_Suni_Length
- 2);
659 -- For the packed case, we don't know the bit positions
660 -- if we don't know the starting position!
662 if Is_Packed
(Ent
) then
663 Write_Line
("?? range ? .. ??;");
666 -- Otherwise we can continue
673 Write_Str
(" range ");
677 -- Allowing Uint_0 here is a kludge, really this should be
678 -- a fine Esize value but currently it means unknown, except
679 -- that we know after gigi has back annotated that a size of
680 -- zero is real, since otherwise gigi back annotates using
681 -- No_Uint as the value to indicate unknown).
683 if (Esize
(Comp
) = Uint_0
or else Known_Static_Esize
(Comp
))
684 and then Known_Static_Normalized_First_Bit
(Comp
)
686 Lbit
:= Fbit
+ Esiz
- 1;
694 -- The test for Esize (Comp) not being Uint_0 here is a kludge.
695 -- Officially a value of zero for Esize means unknown, but here
696 -- we use the fact that we know that gigi annotates Esize with
697 -- No_Uint, not Uint_0. Really everyone should use No_Uint???
699 elsif List_Representation_Info
< 3
700 or else (Esize
(Comp
) /= Uint_0
and then Unknown_Esize
(Comp
))
704 else -- List_Representation >= 3 and Known_Esize (Comp)
706 Write_Val
(Esiz
, Paren
=> True);
708 -- If in front end layout mode, then dynamic size is
709 -- stored in storage units, so renormalize for output
711 if not Back_End_Layout
then
716 -- Add appropriate first bit offset
726 Write_Int
(UI_To_Int
(Fbit
) - 1);
735 Comp
:= Next_Entity
(Comp
);
738 Write_Line
("end record;");
739 end List_Record_Info
;
745 procedure List_Rep_Info
is
749 for U
in Main_Unit
.. Last_Unit
loop
750 if In_Extended_Main_Source_Unit
(Cunit_Entity
(U
)) then
752 -- Normal case, list to standard output
754 if not List_Representation_Info_To_File
then
755 Unit_Casing
:= Identifier_Casing
(Source_Index
(U
));
757 Write_Str
("Representation information for unit ");
758 Write_Unit_Name
(Unit_Name
(U
));
762 for J
in 1 .. Col
- 1 loop
767 List_Entities
(Cunit_Entity
(U
));
769 -- List representation information to file
772 Creat_Repinfo_File_Access
.all (File_Name
(Source_Index
(U
)));
773 Set_Special_Output
(Write_Info_Line
'Access);
774 List_Entities
(Cunit_Entity
(U
));
775 Set_Special_Output
(null);
776 Close_Repinfo_File_Access
.all;
782 ---------------------
783 -- Write_Info_Line --
784 ---------------------
786 procedure Write_Info_Line
(S
: String) is
788 Write_Repinfo_Line_Access
.all (S
(S
'First .. S
'Last - 1));
795 procedure List_Type_Info
(Ent
: Entity_Id
) is
799 -- Do not list size info for unconstrained arrays, not meaningful
801 if Is_Array_Type
(Ent
) and then not Is_Constrained
(Ent
) then
805 -- If Esize and RM_Size are the same and known, list as Size. This
806 -- is a common case, which we may as well list in simple form.
808 if Esize
(Ent
) = RM_Size
(Ent
) then
811 Write_Str
("'Size use ");
812 Write_Val
(Esize
(Ent
));
815 -- For now, temporary case, to be removed when gigi properly back
816 -- annotates RM_Size, if RM_Size is not set, then list Esize as
817 -- Size. This avoids odd Object_Size output till we fix things???
819 elsif Unknown_RM_Size
(Ent
) then
822 Write_Str
("'Size use ");
823 Write_Val
(Esize
(Ent
));
826 -- Otherwise list size values separately if they are set
831 Write_Str
("'Object_Size use ");
832 Write_Val
(Esize
(Ent
));
835 -- Note on following check: The RM_Size of a discrete type can
836 -- legitimately be set to zero, so a special check is needed.
840 Write_Str
("'Value_Size use ");
841 Write_Val
(RM_Size
(Ent
));
848 Write_Str
("'Alignment use ");
849 Write_Val
(Alignment
(Ent
));
853 ----------------------
854 -- Rep_Not_Constant --
855 ----------------------
857 function Rep_Not_Constant
(Val
: Node_Ref_Or_Val
) return Boolean is
859 if Val
= No_Uint
or else Val
< 0 then
864 end Rep_Not_Constant
;
871 (Val
: Node_Ref_Or_Val
;
875 function B
(Val
: Boolean) return Uint
;
876 -- Returns Uint_0 for False, Uint_1 for True
878 function T
(Val
: Node_Ref_Or_Val
) return Boolean;
879 -- Returns True for 0, False for any non-zero (i.e. True)
881 function V
(Val
: Node_Ref_Or_Val
) return Uint
;
882 -- Internal recursive routine to evaluate tree
888 function B
(Val
: Boolean) return Uint
is
901 function T
(Val
: Node_Ref_Or_Val
) return Boolean is
914 function V
(Val
: Node_Ref_Or_Val
) return Uint
is
923 Node
: Exp_Node
renames Rep_Table
.Table
(-UI_To_Int
(Val
));
935 return V
(Node
.Op1
) + V
(Node
.Op2
);
938 return V
(Node
.Op1
) - V
(Node
.Op2
);
941 return V
(Node
.Op1
) * V
(Node
.Op2
);
943 when Trunc_Div_Expr
=>
944 return V
(Node
.Op1
) / V
(Node
.Op2
);
946 when Ceil_Div_Expr
=>
949 (V
(Node
.Op1
) / UR_From_Uint
(V
(Node
.Op2
)));
951 when Floor_Div_Expr
=>
954 (V
(Node
.Op1
) / UR_From_Uint
(V
(Node
.Op2
)));
956 when Trunc_Mod_Expr
=>
957 return V
(Node
.Op1
) rem V
(Node
.Op2
);
959 when Floor_Mod_Expr
=>
960 return V
(Node
.Op1
) mod V
(Node
.Op2
);
962 when Ceil_Mod_Expr
=>
965 Q
:= UR_Ceiling
(L
/ UR_From_Uint
(R
));
968 when Exact_Div_Expr
=>
969 return V
(Node
.Op1
) / V
(Node
.Op2
);
972 return -V
(Node
.Op1
);
975 return UI_Min
(V
(Node
.Op1
), V
(Node
.Op2
));
978 return UI_Max
(V
(Node
.Op1
), V
(Node
.Op2
));
981 return UI_Abs
(V
(Node
.Op1
));
983 when Truth_Andif_Expr
=>
984 return B
(T
(Node
.Op1
) and then T
(Node
.Op2
));
986 when Truth_Orif_Expr
=>
987 return B
(T
(Node
.Op1
) or else T
(Node
.Op2
));
989 when Truth_And_Expr
=>
990 return B
(T
(Node
.Op1
) and T
(Node
.Op2
));
992 when Truth_Or_Expr
=>
993 return B
(T
(Node
.Op1
) or T
(Node
.Op2
));
995 when Truth_Xor_Expr
=>
996 return B
(T
(Node
.Op1
) xor T
(Node
.Op2
));
998 when Truth_Not_Expr
=>
999 return B
(not T
(Node
.Op1
));
1002 return B
(V
(Node
.Op1
) < V
(Node
.Op2
));
1005 return B
(V
(Node
.Op1
) <= V
(Node
.Op2
));
1008 return B
(V
(Node
.Op1
) > V
(Node
.Op2
));
1011 return B
(V
(Node
.Op1
) >= V
(Node
.Op2
));
1014 return B
(V
(Node
.Op1
) = V
(Node
.Op2
));
1017 return B
(V
(Node
.Op1
) /= V
(Node
.Op2
));
1021 Sub
: constant Int
:= UI_To_Int
(Node
.Op1
);
1024 pragma Assert
(Sub
in D
'Range);
1033 -- Start of processing for Rep_Value
1036 if Val
= No_Uint
then
1048 procedure Spaces
(N
: Natural) is
1050 for J
in 1 .. N
loop
1059 procedure Tree_Read
is
1061 Rep_Table
.Tree_Read
;
1068 procedure Tree_Write
is
1070 Rep_Table
.Tree_Write
;
1077 procedure Write_Val
(Val
: Node_Ref_Or_Val
; Paren
: Boolean := False) is
1079 if Rep_Not_Constant
(Val
) then
1080 if List_Representation_Info
< 3 or else Val
= No_Uint
then
1084 if Back_End_Layout
then
1089 List_GCC_Expression
(Val
);
1092 List_GCC_Expression
(Val
);
1100 Write_Name_Decoded
(Chars
(Get_Dynamic_SO_Entity
(Val
)));
1103 Write_Name_Decoded
(Chars
(Get_Dynamic_SO_Entity
(Val
)));