aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_maps.ads
blob: 713999f92cc0306581a2d07d748666342b17b0d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                             S E M _ M A P S                              --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 1996-2007, 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 --
-- 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 COPYING3.  If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the 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 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    : 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    : 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      => 100,
      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      => 100,
      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      => 100,
      Table_Name           => "Associations_Table");

end Sem_Maps;