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