1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1999-2009, 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 3, 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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This package contains the routines to handle back annotation of the
33 -- tree to fill in representation information, and also the routine used
34 -- by -gnatR to print this information. This unit is used both in the
35 -- compiler and in ASIS (it is used in ASIS as part of the implementation
36 -- of the data decomposition annex).
38 with Types
; use Types
;
39 with Uintp
; use Uintp
;
43 --------------------------------
44 -- Representation Information --
45 --------------------------------
47 -- The representation information of interest here is size and
48 -- component information for arrays and records. For primitive
49 -- types, the front end computes the Esize and RM_Size fields of
50 -- the corresponding entities as constant non-negative integers,
51 -- and the Uint values are stored directly in these fields.
53 -- For composite types, there are three cases:
55 -- 1. In some cases the front end knows the values statically,
56 -- for example in the case where representation clauses or
57 -- pragmas specify the values.
59 -- 2. If Backend_Layout is True, then the backend is responsible
60 -- for layout of all types and objects not laid out by the
61 -- front end. This includes all dynamic values, and also
62 -- static values (e.g. record sizes) when not set by the
65 -- 3. If Backend_Layout is False, then the front end lays out
66 -- all data, according to target dependent size and alignment
67 -- information, creating dynamic inlinable functions where
68 -- needed in the case of sizes not known till runtime.
70 -----------------------------
71 -- Back-Annotation by Gigi --
72 -----------------------------
74 -- The following interface is used by gigi if Backend_Layout is True
76 -- As part of the processing in gigi, the types are laid out and
77 -- appropriate values computed for the sizes and component positions
78 -- and sizes of records and arrays.
80 -- The back-annotation circuit in gigi is responsible for updating the
81 -- relevant fields in the tree to reflect these computations, as follows:
83 -- For E_Array_Type entities, the Component_Size field
85 -- For all record and array types and subtypes, the Esize field,
86 -- which contains the Size (more accurately the Object_SIze) value
87 -- for the type or subtype.
89 -- For E_Component and E_Discriminant entities, the Esize (size
90 -- of component) and Component_Bit_Offset fields. Note that gigi
91 -- does not (yet ???) back annotate Normalized_Position/First_Bit.
93 -- There are three cases to consider:
95 -- 1. The value is constant. In this case, the back annotation works
96 -- by simply storing the non-negative universal integer value in
97 -- the appropriate field corresponding to this constant size.
99 -- 2. The value depends on variables other than discriminants of the
100 -- current record. In this case, the value is not known, even if
101 -- the complete data of the record is available, and gigi marks
102 -- this situation by storing the special value No_Uint.
104 -- 3. The value depends on the discriminant values for the current
105 -- record. In this case, gigi back annotates the field with a
106 -- representation of the expression for computing the value in
107 -- terms of the discriminants. A negative Uint value is used to
108 -- represent the value of such an expression, as explained in
109 -- the following section.
111 -- GCC expressions are represented with a Uint value that is negative.
112 -- See the body of this package for details on the representation used.
114 -- One other case in which gigi back annotates GCC expressions is in
115 -- the Present_Expr field of an N_Variant node. This expression which
116 -- will always depend on discriminants, and hence always be represented
117 -- as a negative Uint value, provides an expression which, when evaluated
118 -- with a given set of discriminant values, indicates whether the variant
119 -- is present for that set of values (result is True, i.e. non-zero) or
120 -- not present (result is False, i.e. zero).
122 subtype Node_Ref
is Uint
;
123 -- Subtype used for negative Uint values used to represent nodes
125 subtype Node_Ref_Or_Val
is Uint
;
126 -- Subtype used for values that can either be a Node_Ref (negative)
127 -- or a value (non-negative)
129 type TCode
is range 0 .. 28;
130 -- Type used on Ada side to represent DEFTREECODE values defined in
131 -- tree.def. Only a subset of these tree codes can actually appear.
132 -- The names are the names from tree.def in Ada casing.
134 -- name code description operands
136 Cond_Expr
: constant TCode
:= 1; -- conditional 3
137 Plus_Expr
: constant TCode
:= 2; -- addition 2
138 Minus_Expr
: constant TCode
:= 3; -- subtraction 2
139 Mult_Expr
: constant TCode
:= 4; -- multiplication 2
140 Trunc_Div_Expr
: constant TCode
:= 5; -- truncating division 2
141 Ceil_Div_Expr
: constant TCode
:= 6; -- division rounding up 2
142 Floor_Div_Expr
: constant TCode
:= 7; -- division rounding down 2
143 Trunc_Mod_Expr
: constant TCode
:= 8; -- mod for trunc_div 2
144 Ceil_Mod_Expr
: constant TCode
:= 9; -- mod for ceil_div 2
145 Floor_Mod_Expr
: constant TCode
:= 10; -- mod for floor_div 2
146 Exact_Div_Expr
: constant TCode
:= 11; -- exact div 2
147 Negate_Expr
: constant TCode
:= 12; -- negation 1
148 Min_Expr
: constant TCode
:= 13; -- minimum 2
149 Max_Expr
: constant TCode
:= 14; -- maximum 2
150 Abs_Expr
: constant TCode
:= 15; -- absolute value 1
151 Truth_Andif_Expr
: constant TCode
:= 16; -- Boolean and then 2
152 Truth_Orif_Expr
: constant TCode
:= 17; -- Boolean or else 2
153 Truth_And_Expr
: constant TCode
:= 18; -- Boolean and 2
154 Truth_Or_Expr
: constant TCode
:= 19; -- Boolean or 2
155 Truth_Xor_Expr
: constant TCode
:= 20; -- Boolean xor 2
156 Truth_Not_Expr
: constant TCode
:= 21; -- Boolean not 1
157 Lt_Expr
: constant TCode
:= 22; -- comparison < 2
158 Le_Expr
: constant TCode
:= 23; -- comparison <= 2
159 Gt_Expr
: constant TCode
:= 24; -- comparison > 2
160 Ge_Expr
: constant TCode
:= 25; -- comparison >= 2
161 Eq_Expr
: constant TCode
:= 26; -- comparison = 2
162 Ne_Expr
: constant TCode
:= 27; -- comparison /= 2
163 Bit_And_Expr
: constant TCode
:= 28; -- Binary and 2
165 -- The following entry is used to represent a discriminant value in
166 -- the tree. It has a special tree code that does not correspond
167 -- directly to a gcc node. The single operand is the number of the
168 -- discriminant in the record (1 = first discriminant).
170 Discrim_Val
: constant TCode
:= 0; -- discriminant value 1
172 ------------------------
173 -- The gigi Interface --
174 ------------------------
176 -- The following declarations are for use by gigi for back annotation
180 Op1
: Node_Ref_Or_Val
;
181 Op2
: Node_Ref_Or_Val
:= No_Uint
;
182 Op3
: Node_Ref_Or_Val
:= No_Uint
) return Node_Ref
;
183 -- Creates a node using the tree code defined by Expr and from one to three
184 -- operands as required (unused operands set as shown to No_Uint) Note that
185 -- this call can be used to create a discriminant reference by using (Expr
186 -- => Discrim_Val, Op1 => discriminant_number).
188 function Create_Discrim_Ref
(Discr
: Entity_Id
) return Node_Ref
;
189 -- Creates a reference to the discriminant whose entity is Discr
191 --------------------------------------------------------
192 -- Front-End Interface for Dynamic Size/Offset Values --
193 --------------------------------------------------------
195 -- If Backend_Layout is False, then the front-end deals with all
196 -- dynamic size and offset fields. There are two cases:
198 -- 1. The value can be computed at the time of type freezing, and
199 -- is stored in a run-time constant. In this case, the field
200 -- contains a reference to this entity. In the case of sizes
201 -- the value stored is the size in storage units, since dynamic
202 -- sizes are always a multiple of storage units.
204 -- 2. The size/offset depends on the value of discriminants at
205 -- run-time. In this case, the front end builds a function to
206 -- compute the value. This function has a single parameter
207 -- which is the discriminated record object in question. Any
208 -- references to discriminant values are simply references to
209 -- the appropriate discriminant in this single argument, and
210 -- to compute the required size/offset value at run time, the
211 -- code generator simply constructs a call to the function
212 -- with the appropriate argument. The size/offset field in
213 -- this case contains a reference to the function entity.
214 -- Note that as for case 1, if such a function is used to
215 -- return a size, then the size in storage units is returned,
216 -- not the size in bits.
218 -- The interface here allows these created entities to be referenced
219 -- using negative Unit values, so that they can be stored in the
220 -- appropriate size and offset fields in the tree.
222 -- In the case of components, if the location of the component is static,
223 -- then all four fields (Component_Bit_Offset, Normalized_Position, Esize,
224 -- and Normalized_First_Bit) are set to appropriate values. In the case of
225 -- a non-static component location, Component_Bit_Offset is not used and
226 -- is left set to Unknown. Normalized_Position and Normalized_First_Bit
227 -- are set appropriately.
229 subtype SO_Ref
is Uint
;
230 -- Type used to represent a Uint value that represents a static or
231 -- dynamic size/offset value (non-negative if static, negative if
232 -- the size value is dynamic).
234 subtype Dynamic_SO_Ref
is Uint
;
235 -- Type used to represent a negative Uint value used to store
236 -- a dynamic size/offset value.
238 function Is_Dynamic_SO_Ref
(U
: SO_Ref
) return Boolean;
239 pragma Inline
(Is_Dynamic_SO_Ref
);
240 -- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
241 -- represents a dynamic Size/Offset value (i.e. it is negative).
243 function Is_Static_SO_Ref
(U
: SO_Ref
) return Boolean;
244 pragma Inline
(Is_Static_SO_Ref
);
245 -- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
246 -- represents a static Size/Offset value (i.e. it is non-negative).
248 function Create_Dynamic_SO_Ref
(E
: Entity_Id
) return Dynamic_SO_Ref
;
249 -- Given the Entity_Id for a constant (case 1), the Node_Id for an
250 -- expression (case 2), or the Entity_Id for a function (case 3),
251 -- this function returns a (negative) Uint value that can be used
252 -- to retrieve the entity or expression for later use.
254 function Get_Dynamic_SO_Entity
(U
: Dynamic_SO_Ref
) return Entity_Id
;
255 -- Retrieve the Node_Id or Entity_Id stored by a previous call to
256 -- Create_Dynamic_SO_Ref. The approach is that the front end makes
257 -- the necessary Create_Dynamic_SO_Ref calls to associate the node
258 -- and entity id values and the back end makes Get_Dynamic_SO_Ref
259 -- calls to retrieve them.
265 type Discrim_List
is array (Pos
range <>) of Uint
;
266 -- Type used to represent list of discriminant values
269 (Val
: Node_Ref_Or_Val
;
270 D
: Discrim_List
) return Uint
;
271 -- Given the contents of a First_Bit_Position or Esize field containing
272 -- a node reference (i.e. a negative Uint value) and D, the list of
273 -- discriminant values, returns the interpreted value of this field.
274 -- For convenience, Rep_Value will take a non-negative Uint value
275 -- as an argument value, and return it unmodified. A No_Uint value is
276 -- also returned unmodified.
279 -- Initializes internal tables from current tree file using the relevant
280 -- Table.Tree_Read routines.
282 ------------------------
283 -- Compiler Interface --
284 ------------------------
286 procedure List_Rep_Info
;
287 -- Procedure to list representation information
289 procedure Tree_Write
;
290 -- Writes out internal tables to current tree file using the relevant
291 -- Table.Tree_Write routines.
293 --------------------------
294 -- Debugging Procedures --
295 --------------------------
297 procedure List_GCC_Expression
(U
: Node_Ref_Or_Val
);
298 -- Prints out given expression in symbolic form. Constants are listed
299 -- in decimal numeric form, Discriminants are listed with a # followed
300 -- by the discriminant number, and operators are output in appropriate
301 -- symbolic form No_Uint displays as two question marks. The output is
302 -- on a single line but has no line return after it. This procedure is
303 -- useful only if operating in backend layout mode.
305 procedure lgx
(U
: Node_Ref_Or_Val
);
306 -- In backend layout mode, this is like List_GCC_Expression, but
307 -- includes a line return at the end. If operating in front end
308 -- layout mode, then the name of the entity for the size (either
309 -- a function of a variable) is listed followed by a line return.