| ------------------------------------------------------------------------------ |
| -- -- |
| -- 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; |