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