blob: 346d43799bc0316f43c906d4efc85ab243785058 [file] [log] [blame]
-- --
-- --
-- R E P I N F O --
-- --
-- S p e c --
-- --
-- Copyright (C) 1999-2018, 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 3, 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 --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <>. --
-- --
-- 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 case 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_Discriminant entities, the Esize (size
-- of component) and Component_Bit_Offset fields. Note that gigi
-- does not 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 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.
-- 3. The value depends on variables other than discriminants of the
-- current record. In this case, gigi also back annotates the field
-- with a representation of the expression for computing the value
-- in terms of the variables represented symbolically.
-- Note: the extended back annotation for the dynamic case is needed only
-- for -gnatR3 output, and for proper operation of the ASIS DDA. Since it
-- can be expensive to do this back annotation (for discriminated records
-- with many variable length arrays), we only do the full back annotation
-- in -gnatR3 mode, or ASIS mode. In any other mode, the back-end just sets
-- the value to Uint_Minus_1, indicating that the value of the attribute
-- depends on discriminant information, but not giving further details.
-- 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). Again, the full annotation of
-- this field is done only in -gnatR3 mode or in ASIS mode, and in other
-- modes, the value is set to Uint_Minus_1.
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 .. 29;
-- 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; -- comparison < 2
Le_Expr : constant TCode := 23; -- comparison <= 2
Gt_Expr : constant TCode := 24; -- comparison > 2
Ge_Expr : constant TCode := 25; -- comparison >= 2
Eq_Expr : constant TCode := 26; -- comparison = 2
Ne_Expr : constant TCode := 27; -- comparison /= 2
Bit_And_Expr : constant TCode := 28; -- Binary and 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 index number
-- of the discriminant in the record (1 = first discriminant).
Discrim_Val : constant TCode := 0; -- discriminant value 1
-- The following entry is used to represent a value not known at
-- compile time in the tree, other than a discriminant value. It
-- has a special tree code that does not correspond directly to
-- a GCC node. The single operand is an arbitrary index number.
Dynamic_Val : constant TCode := 29; -- dynamic 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 using the tree code defined by Expr and from one to three
-- 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 reference 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 appropriate 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 retrieve 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;
-- Initializes internal tables from current tree file using the relevant
-- Table.Tree_Read routines.
-- Compiler Interface --
procedure List_Rep_Info (Bytes_Big_Endian : Boolean);
-- Procedure to list representation information. Bytes_Big_Endian is the
-- value from Ttypes (Repinfo cannot have a dependency on Ttypes).
procedure Tree_Write;
-- Writes out internal tables to current tree file using the relevant
-- Table.Tree_Write routines.
-- 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;