------------------------------------------------------------------------------ -- -- -- GNAT COMPILER COMPONENTS -- -- -- -- S E M _ M A P S -- -- -- -- S p e c -- -- -- -- -- -- Copyright (C) 1996-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. -- -- -- -- 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 operations on the renaming maps used for -- generic analysis and instantiation. Renaming maps are created when -- a generic unit is analyzed, in order to capture all references to -- global variables within the unit. The renaming map of a generic unit -- copied prior to each instantiation, and then updated by mapping the -- formals into the actuals and the local entities into entities local to -- the instance. When the generic tree is copied to produce the instance, -- all references are updated by means of the renaming map. -- Map composition of renaming maps takes place for nested instantiations, -- for generic child units, and for formal packages. -- For additional details, see the documentation in sem_ch12. with Table; with Types; use Types; package Sem_Maps is type Map is new Int; type Assoc is private; type Scope_Kind is (S_Global, S_Formal, S_Local); function New_Map (Num_Assoc : Int) return Map; -- Build empty map with the given number of associations, and a -- headers table of the appropriate size. function Compose (Orig_Map : Map; New_Map : Map) return Map; -- Update the associations in Orig_Map, so that if Orig_Map (e1) = e2 -- and New_Map (e2) = e3, then the image of e1 under the result is e3. function Copy (M : Map) return Map; -- Full copy of contents and headers. function Lookup (M : Map; E : Entity_Id) return Entity_Id; -- Retrieve image of E under M, Empty if undefined. procedure Add_Association (M : in out Map; O_Id : Entity_Id; N_Id : Entity_Id; Kind : Scope_Kind := S_Local); -- Update M in place. On entry M (O_Id) must not be defined. procedure Update_Association (M : in out Map; O_Id : Entity_Id; N_Id : Entity_Id; Kind : Scope_Kind := S_Local); -- Update the entry in M for O_Id. function Build_Instance_Map (M : Map) return Map; -- Copy renaming map of generic, and create new entities for all the -- local entities within. private -- New maps are created when a generic is analyzed, and for each of -- its instantiations. Maps are also updated for nested generics, for -- child units, and for formal packages. As a result we need to allocate -- maps dynamically. -- When analyzing a generic, we do not know how many references are -- in it. We build an initial map after generic analysis, using a static -- structure that relies on the compiler's extensible table mechanism. -- After constructing this initial map, all subsequent uses and updates -- of this map do not modify its domain, so that dynamically allocated -- maps have a fixed size and never need to be reallocated. Furthermore, -- the headers of the hash table of a dynamically allocated map can be -- chosen according to the total number of entries in the map, to -- accommodate efficiently generic units of different sizes (Unchecked_ -- Conversion vs. Generic_Elementary_Functions, for example). So in -- fact both components of a map have fixed size, and can be allocated -- using the standard table mechanism. A Maps_Table holds records that -- contain indices into the global Headers table and the Associations -- table, and a Map is an index into the Maps_Table. -- -- Maps_Table Headers_Table Associations_Table -- -- |_____| |___________ | -- |_____| | | | | -- ------>|Map |------------------------------>|Associations| -- |Info |------------->| |=========>| for one | -- |_____| | |====| | unit | -- | | | | |====>| | -- |_____| |____________| -- | | | | type Header_Index is new Int; type Assoc_Index is new Int; No_Assoc : constant Assoc_Index := -1; type Map_Info is record Header_Offset : Header_Index; Header_Num : Header_Index; Assoc_Offset : Assoc_Index; Assoc_Num : Assoc_Index; Assoc_Next : Assoc_Index; end record; type Assoc is record Old_Id : Entity_Id := Empty; New_Id : Entity_Id := Empty; Kind : Scope_Kind := S_Local; Next : Assoc_Index := No_Assoc; end record; -- All maps are accessed through the following table. The map attribute -- of a generic unit or an instance is an index into this table. package Maps_Table is new Table.Table ( Table_Component_Type => Map_Info, Table_Index_Type => Map, Table_Low_Bound => 0, Table_Initial => 100, Table_Increment => 10, Table_Name => "Maps_Table"); -- All headers for hash tables are allocated in one global table. Each -- map stores the offset into this table at which its own headers start. package Headers_Table is new Table.Table ( Table_Component_Type => Assoc_Index, Table_Index_Type => Header_Index, Table_Low_Bound => 0, Table_Initial => 1000, Table_Increment => 10, Table_Name => "Headers_Table"); -- All associations are allocated in one global table. Each map stores -- the offset into this table at which its own associations start. package Associations_Table is new Table.Table ( Table_Component_Type => Assoc, Table_Index_Type => Assoc_Index, Table_Low_Bound => 1, Table_Initial => 1000, Table_Increment => 10, Table_Name => "Associations_Table"); end Sem_Maps;