| 1 |
706 |
jeremybenn |
------------------------------------------------------------------------------
|
| 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-2009, 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 |
|
|
|
| 38 |
|
|
with Types; use Types;
|
| 39 |
|
|
with Uintp; use Uintp;
|
| 40 |
|
|
|
| 41 |
|
|
package 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 (yet ???) 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 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.
|
| 103 |
|
|
|
| 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.
|
| 110 |
|
|
|
| 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.
|
| 113 |
|
|
|
| 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).
|
| 121 |
|
|
|
| 122 |
|
|
subtype Node_Ref is Uint;
|
| 123 |
|
|
-- Subtype used for negative Uint values used to represent nodes
|
| 124 |
|
|
|
| 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)
|
| 128 |
|
|
|
| 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.
|
| 133 |
|
|
|
| 134 |
|
|
-- name code description operands
|
| 135 |
|
|
|
| 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
|
| 164 |
|
|
|
| 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).
|
| 169 |
|
|
|
| 170 |
|
|
Discrim_Val : constant TCode := 0; -- discriminant value 1
|
| 171 |
|
|
|
| 172 |
|
|
------------------------
|
| 173 |
|
|
-- The gigi Interface --
|
| 174 |
|
|
------------------------
|
| 175 |
|
|
|
| 176 |
|
|
-- The following declarations are for use by gigi for back annotation
|
| 177 |
|
|
|
| 178 |
|
|
function Create_Node
|
| 179 |
|
|
(Expr : TCode;
|
| 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).
|
| 187 |
|
|
|
| 188 |
|
|
function Create_Discrim_Ref (Discr : Entity_Id) return Node_Ref;
|
| 189 |
|
|
-- Creates a reference to the discriminant whose entity is Discr
|
| 190 |
|
|
|
| 191 |
|
|
--------------------------------------------------------
|
| 192 |
|
|
-- Front-End Interface for Dynamic Size/Offset Values --
|
| 193 |
|
|
--------------------------------------------------------
|
| 194 |
|
|
|
| 195 |
|
|
-- If Backend_Layout is False, then the front-end deals with all
|
| 196 |
|
|
-- dynamic size and offset fields. There are two cases:
|
| 197 |
|
|
|
| 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.
|
| 203 |
|
|
|
| 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.
|
| 217 |
|
|
|
| 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.
|
| 221 |
|
|
|
| 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.
|
| 228 |
|
|
|
| 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).
|
| 233 |
|
|
|
| 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.
|
| 237 |
|
|
|
| 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).
|
| 242 |
|
|
|
| 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).
|
| 247 |
|
|
|
| 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.
|
| 253 |
|
|
|
| 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.
|
| 260 |
|
|
|
| 261 |
|
|
--------------------
|
| 262 |
|
|
-- ASIS_Interface --
|
| 263 |
|
|
--------------------
|
| 264 |
|
|
|
| 265 |
|
|
type Discrim_List is array (Pos range <>) of Uint;
|
| 266 |
|
|
-- Type used to represent list of discriminant values
|
| 267 |
|
|
|
| 268 |
|
|
function Rep_Value
|
| 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.
|
| 277 |
|
|
|
| 278 |
|
|
procedure Tree_Read;
|
| 279 |
|
|
-- Initializes internal tables from current tree file using the relevant
|
| 280 |
|
|
-- Table.Tree_Read routines.
|
| 281 |
|
|
|
| 282 |
|
|
------------------------
|
| 283 |
|
|
-- Compiler Interface --
|
| 284 |
|
|
------------------------
|
| 285 |
|
|
|
| 286 |
|
|
procedure List_Rep_Info;
|
| 287 |
|
|
-- Procedure to list representation information
|
| 288 |
|
|
|
| 289 |
|
|
procedure Tree_Write;
|
| 290 |
|
|
-- Writes out internal tables to current tree file using the relevant
|
| 291 |
|
|
-- Table.Tree_Write routines.
|
| 292 |
|
|
|
| 293 |
|
|
--------------------------
|
| 294 |
|
|
-- Debugging Procedures --
|
| 295 |
|
|
--------------------------
|
| 296 |
|
|
|
| 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.
|
| 304 |
|
|
|
| 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.
|
| 310 |
|
|
|
| 311 |
|
|
end Repinfo;
|