------------------------------------------------------------------------------ | |

-- -- | |

-- GNAT COMPILER COMPONENTS -- | |

-- -- | |

-- R E P I N F O -- | |

-- -- | |

-- S p e c -- | |

-- -- | |

-- Copyright (C) 1999-2001 Free Software Foundation, Inc. -- | |

-- -- | |

-- GNAT is free software; you can redistribute it and/or modify it under -- | |

-- terms of the GNU General Public License as published by the Free Soft- -- | |

-- ware Foundation; either version 2, or (at your option) any later ver- -- | |

-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- | |

-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- | |

-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- | |

-- for more details. You should have received a copy of the GNU General -- | |

-- Public License distributed with GNAT; see file COPYING. If not, write -- | |

-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, -- | |

-- MA 02111-1307, USA. -- | |

-- -- | |

-- As a special exception, if other files instantiate generics from this -- | |

-- unit, or you link this unit with other files to produce an executable, -- | |

-- this unit does not by itself cause the resulting executable to be -- | |

-- covered by the GNU General Public License. This exception does not -- | |

-- however invalidate any other reasons why the executable file might be -- | |

-- covered by the GNU Public License. -- | |

-- -- | |

-- GNAT was originally developed by the GNAT team at New York University. -- | |

-- Extensive contributions were provided by Ada Core Technologies Inc. -- | |

-- -- | |

------------------------------------------------------------------------------ | |

-- This package contains the routines to handle back annotation of the | |

-- tree to fill in representation information, and also the routine used | |

-- by -gnatR to print this information. This unit is used both in the | |

-- compiler and in ASIS (it is used in ASIS as part of the implementation | |

-- of the data decomposition annex. | |

with Types; use Types; | |

with Uintp; use Uintp; | |

package Repinfo is | |

-------------------------------- | |

-- Representation Information -- | |

-------------------------------- | |

-- The representation information of interest here is size and | |

-- component information for arrays and records. For primitive | |

-- types, the front end computes the Esize and RM_Size fields of | |

-- the corresponding entities as constant non-negative integers, | |

-- and the Uint values are stored directly in these fields. | |

-- For composite types, there are three cases: | |

-- 1. In some cases the front end knows the values statically, | |

-- for example in the ase where representation clauses or | |

-- pragmas specify the values. | |

-- 2. If Backend_Layout is True, then the backend is responsible | |

-- for layout of all types and objects not laid out by the | |

-- front end. This includes all dynamic values, and also | |

-- static values (e.g. record sizes) when not set by the | |

-- front end. | |

-- 3. If Backend_Layout is False, then the front end lays out | |

-- all data, according to target dependent size and alignment | |

-- information, creating dynamic inlinable functions where | |

-- needed in the case of sizes not known till runtime. | |

----------------------------- | |

-- Back-Annotation by Gigi -- | |

----------------------------- | |

-- The following interface is used by gigi if Backend_Layout is True. | |

-- As part of the processing in gigi, the types are laid out and | |

-- appropriate values computed for the sizes and component positions | |

-- and sizes of records and arrays. | |

-- The back-annotation circuit in gigi is responsible for updating the | |

-- relevant fields in the tree to reflect these computations, as follows: | |

-- For E_Array_Type entities, the Component_Size field | |

-- For all record and array types and subtypes, the Esize field, | |

-- which contains the Size (more accurately the Object_SIze) value | |

-- for the type or subtype. | |

-- For E_Component and E_Distriminant entities, the Esize (size | |

-- of component) and Component_Bit_Offset fields. Note that gigi | |

-- does not (yet ???) back annotate Normalized_Position/First_Bit. | |

-- There are three cases to consider: | |

-- 1. The value is constant. In this case, the back annotation works | |

-- by simply storing the non-negative universal integer value in | |

-- the appropriate field corresponding to this constant size. | |

-- 2. The value depends on variables other than discriminants of the | |

-- current record. In this case, the value is not known, even if | |

-- the complete data of the record is available, and gigi marks | |

-- this situation by storing the special value No_Uint. | |

-- 3. The value depends on the discriminant values for the current | |

-- record. In this case, gigi back annotates the field with a | |

-- representation of the expression for computing the value in | |

-- terms of the discriminants. A negative Uint value is used to | |

-- represent the value of such an expression, as explained in | |

-- the following section. | |

-- GCC expressions are represented with a Uint value that is negative. | |

-- See the body of this package for details on the representation used. | |

-- One other case in which gigi back annotates GCC expressions is in | |

-- the Present_Expr field of an N_Variant node. This expression which | |

-- will always depend on discriminants, and hence always be represented | |

-- as a negative Uint value, provides an expression which, when evaluated | |

-- with a given set of discriminant values, indicates whether the variant | |

-- is present for that set of values (result is True, i.e. non-zero) or | |

-- not present (result is False, i.e. zero). | |

subtype Node_Ref is Uint; | |

-- Subtype used for negative Uint values used to represent nodes | |

subtype Node_Ref_Or_Val is Uint; | |

-- Subtype used for values that can either be a Node_Ref (negative) | |

-- or a value (non-negative) | |

type TCode is range 0 .. 27; | |

-- Type used on Ada side to represent DEFTREECODE values defined in | |

-- tree.def. Only a subset of these tree codes can actually appear. | |

-- The names are the names from tree.def in Ada casing. | |

-- name code description operands | |

Cond_Expr : constant TCode := 1; -- conditional 3 | |

Plus_Expr : constant TCode := 2; -- addition 2 | |

Minus_Expr : constant TCode := 3; -- subtraction 2 | |

Mult_Expr : constant TCode := 4; -- multiplication 2 | |

Trunc_Div_Expr : constant TCode := 5; -- truncating division 2 | |

Ceil_Div_Expr : constant TCode := 6; -- division rounding up 2 | |

Floor_Div_Expr : constant TCode := 7; -- division rounding down 2 | |

Trunc_Mod_Expr : constant TCode := 8; -- mod for trunc_div 2 | |

Ceil_Mod_Expr : constant TCode := 9; -- mod for ceil_div 2 | |

Floor_Mod_Expr : constant TCode := 10; -- mod for floor_div 2 | |

Exact_Div_Expr : constant TCode := 11; -- exact div 2 | |

Negate_Expr : constant TCode := 12; -- negation 1 | |

Min_Expr : constant TCode := 13; -- minimum 2 | |

Max_Expr : constant TCode := 14; -- maximum 2 | |

Abs_Expr : constant TCode := 15; -- absolute value 1 | |

Truth_Andif_Expr : constant TCode := 16; -- Boolean and then 2 | |

Truth_Orif_Expr : constant TCode := 17; -- Boolean or else 2 | |

Truth_And_Expr : constant TCode := 18; -- Boolean and 2 | |

Truth_Or_Expr : constant TCode := 19; -- Boolean or 2 | |

Truth_Xor_Expr : constant TCode := 20; -- Boolean xor 2 | |

Truth_Not_Expr : constant TCode := 21; -- Boolean not 1 | |

Lt_Expr : constant TCode := 22; -- comparision < 2 | |

Le_Expr : constant TCode := 23; -- comparision <= 2 | |

Gt_Expr : constant TCode := 24; -- comparision > 2 | |

Ge_Expr : constant TCode := 25; -- comparision >= 2 | |

Eq_Expr : constant TCode := 26; -- comparision = 2 | |

Ne_Expr : constant TCode := 27; -- comparision /= 2 | |

-- The following entry is used to represent a discriminant value in | |

-- the tree. It has a special tree code that does not correspond | |

-- directly to a gcc node. The single operand is the number of the | |

-- discriminant in the record (1 = first discriminant). | |

Discrim_Val : constant TCode := 0; -- discriminant value 1 | |

------------------------ | |

-- The gigi Interface -- | |

------------------------ | |

-- The following declarations are for use by gigi for back annotation | |

function Create_Node | |

(Expr : TCode; | |

Op1 : Node_Ref_Or_Val; | |

Op2 : Node_Ref_Or_Val := No_Uint; | |

Op3 : Node_Ref_Or_Val := No_Uint) | |

return Node_Ref; | |

-- Creates a node with using the tree code defined by Expr and from | |

-- 1-3 operands as required (unused operands set as shown to No_Uint) | |

-- Note that this call can be used to create a discriminant reference | |

-- by using (Expr => Discrim_Val, Op1 => discriminant_number). | |

function Create_Discrim_Ref | |

(Discr : Entity_Id) | |

return Node_Ref; | |

-- Creates a refrerence to the discriminant whose entity is Discr. | |

-------------------------------------------------------- | |

-- Front-End Interface for Dynamic Size/Offset Values -- | |

-------------------------------------------------------- | |

-- If Backend_Layout is False, then the front-end deals with all | |

-- dynamic size and offset fields. There are two cases: | |

-- 1. The value can be computed at the time of type freezing, and | |

-- is stored in a run-time constant. In this case, the field | |

-- contains a reference to this entity. In the case of sizes | |

-- the value stored is the size in storage units, since dynamic | |

-- sizes are always a multiple of storage units. | |

-- 2. The size/offset depends on the value of discriminants at | |

-- run-time. In this case, the front end builds a function to | |

-- compute the value. This function has a single parameter | |

-- which is the discriminated record object in question. Any | |

-- references to discriminant values are simply references to | |

-- the appropriate discriminant in this single argument, and | |

-- to compute the required size/offset value at run time, the | |

-- code generator simply constructs a call to the function | |

-- with the appropriate argument. The size/offset field in | |

-- this case contains a reference to the function entity. | |

-- Note that as for case 1, if such a function is used to | |

-- return a size, then the size in storage units is returned, | |

-- not the size in bits. | |

-- The interface here allows these created entities to be referenced | |

-- using negative Unit values, so that they can be stored in the | |

-- appropriate size and offset fields in the tree. | |

-- In the case of components, if the location of the component is static, | |

-- then all four fields (Component_Bit_Offset, Normalized_Position, Esize, | |

-- and Normalized_First_Bit) are set to appropraite values. In the case of | |

-- a non-static component location, Component_Bit_Offset is not used and | |

-- is left set to Unknown. Normalized_Position and Normalized_First_Bit | |

-- are set appropriately. | |

subtype SO_Ref is Uint; | |

-- Type used to represent a Uint value that represents a static or | |

-- dynamic size/offset value (non-negative if static, negative if | |

-- the size value is dynamic). | |

subtype Dynamic_SO_Ref is Uint; | |

-- Type used to represent a negative Uint value used to store | |

-- a dynamic size/offset value. | |

function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean; | |

pragma Inline (Is_Dynamic_SO_Ref); | |

-- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value | |

-- represents a dynamic Size/Offset value (i.e. it is negative). | |

function Is_Static_SO_Ref (U : SO_Ref) return Boolean; | |

pragma Inline (Is_Static_SO_Ref); | |

-- Given a SO_Ref (Uint) value, returns True iff the SO_Ref value | |

-- represents a static Size/Offset value (i.e. it is non-negative). | |

function Create_Dynamic_SO_Ref | |

(E : Entity_Id) | |

return Dynamic_SO_Ref; | |

-- Given the Entity_Id for a constant (case 1), the Node_Id for an | |

-- expression (case 2), or the Entity_Id for a function (case 3), | |

-- this function returns a (negative) Uint value that can be used | |

-- to retrieve the entity or expression for later use. | |

function Get_Dynamic_SO_Entity | |

(U : Dynamic_SO_Ref) | |

return Entity_Id; | |

-- Retrieve the Node_Id or Entity_Id stored by a previous call to | |

-- Create_Dynamic_SO_Ref. The approach is that the front end makes | |

-- the necessary Create_Dynamic_SO_Ref calls to associate the node | |

-- and entity id values and the back end makes Get_Dynamic_SO_Ref | |

-- calls to retrive them. | |

-------------------- | |

-- ASIS_Interface -- | |

-------------------- | |

type Discrim_List is array (Pos range <>) of Uint; | |

-- Type used to represent list of discriminant values | |

function Rep_Value | |

(Val : Node_Ref_Or_Val; | |

D : Discrim_List) | |

return Uint; | |

-- Given the contents of a First_Bit_Position or Esize field containing | |

-- a node reference (i.e. a negative Uint value) and D, the list of | |

-- discriminant values, returns the interpreted value of this field. | |

-- For convenience, Rep_Value will take a non-negative Uint value | |

-- as an argument value, and return it unmodified. A No_Uint value is | |

-- also returned unmodified. | |

procedure Tree_Read; | |

-- Read in the value of the Rep_Table | |

------------------------ | |

-- Compiler Interface -- | |

------------------------ | |

procedure List_Rep_Info; | |

-- Procedure to list representation information | |

procedure Tree_Write; | |

-- Write out the value of the Rep_Table | |

-------------------------- | |

-- Debugging Procedures -- | |

-------------------------- | |

procedure List_GCC_Expression (U : Node_Ref_Or_Val); | |

-- Prints out given expression in symbolic form. Constants are listed | |

-- in decimal numeric form, Discriminants are listed with a # followed | |

-- by the discriminant number, and operators are output in appropriate | |

-- symbolic form No_Uint displays as two question marks. The output is | |

-- on a single line but has no line return after it. This procedure is | |

-- useful only if operating in backend layout mode. | |

procedure lgx (U : Node_Ref_Or_Val); | |

-- In backend layout mode, this is like List_GCC_Expression, but | |

-- includes a line return at the end. If operating in front end | |

-- layout mode, then the name of the entity for the size (either | |

-- a function of a variable) is listed followed by a line return. | |

end Repinfo; |