* rtl.h (struct rtx_def): Update comments.
[official-gcc.git] / gcc / ada / live.adb
blobf21ccc9ce85c22c7f4566671a9cca9fe1f8f9ede
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- L I V E --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 2000-2001 Free Software Foundation, Inc. --
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- GNAT was originally developed by the GNAT team at New York University. --
24 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
25 -- --
26 ------------------------------------------------------------------------------
28 with Atree; use Atree;
29 with Einfo; use Einfo;
30 with Lib; use Lib;
31 with Nlists; use Nlists;
32 with Sem_Util; use Sem_Util;
33 with Sinfo; use Sinfo;
34 with Types; use Types;
36 package body Live is
38 -- Name_Set
40 -- The Name_Set type is used to store the temporary mark bits
41 -- used by the garbage collection of entities. Using a separate
42 -- array prevents using up any valuable per-node space and possibly
43 -- results in better locality and cache usage.
45 type Name_Set is array (Node_Id range <>) of Boolean;
46 pragma Pack (Name_Set);
48 function Marked (Marks : Name_Set; Name : Node_Id) return Boolean;
49 pragma Inline (Marked);
51 procedure Set_Marked
52 (Marks : in out Name_Set;
53 Name : Node_Id;
54 Mark : Boolean := True);
55 pragma Inline (Set_Marked);
57 -- Algorithm
59 -- The problem of finding live entities is solved in two steps:
61 procedure Mark (Root : Node_Id; Marks : out Name_Set);
62 -- Mark all live entities in Root as Marked.
64 procedure Sweep (Root : Node_Id; Marks : Name_Set);
65 -- For all unmarked entities in Root set Is_Eliminated to true
67 -- The Mark phase is split into two phases:
69 procedure Init_Marked (Root : Node_Id; Marks : out Name_Set);
70 -- For all subprograms, reset Is_Public flag if a pragma Eliminate
71 -- applies to the entity, and set the Marked flag to Is_Public
73 procedure Trace_Marked (Root : Node_Id; Marks : in out Name_Set);
74 -- Traverse the tree skipping any unmarked subprogram bodies.
75 -- All visited entities are marked, as well as entities denoted
76 -- by a visited identifier or operator. When an entity is first
77 -- marked it is traced as well.
79 -- Local functions
81 function Body_Of (E : Entity_Id) return Node_Id;
82 -- Returns subprogram body corresponding to entity E
84 function Spec_Of (N : Node_Id) return Entity_Id;
85 -- Given a subprogram body N, return defining identifier of its declaration
87 -- ??? the body of this package contains no comments at all, this
88 -- should be fixed!
90 -------------
91 -- Body_Of --
92 -------------
94 function Body_Of (E : Entity_Id) return Node_Id is
95 Decl : Node_Id := Unit_Declaration_Node (E);
96 Result : Node_Id;
97 Kind : Node_Kind := Nkind (Decl);
99 begin
100 if Kind = N_Subprogram_Body then
101 Result := Decl;
103 elsif Kind /= N_Subprogram_Declaration
104 and Kind /= N_Subprogram_Body_Stub
105 then
106 Result := Empty;
108 else
109 Result := Corresponding_Body (Decl);
111 if Result /= Empty then
112 Result := Unit_Declaration_Node (Result);
113 end if;
114 end if;
116 return Result;
117 end Body_Of;
119 ------------------------------
120 -- Collect_Garbage_Entities --
121 ------------------------------
123 procedure Collect_Garbage_Entities is
124 Root : constant Node_Id := Cunit (Main_Unit);
125 Marks : Name_Set (0 .. Last_Node_Id);
127 begin
128 Mark (Root, Marks);
129 Sweep (Root, Marks);
130 end Collect_Garbage_Entities;
132 -----------------
133 -- Init_Marked --
134 -----------------
136 procedure Init_Marked (Root : Node_Id; Marks : out Name_Set) is
138 function Process (N : Node_Id) return Traverse_Result;
139 procedure Traverse is new Traverse_Proc (Process);
141 function Process (N : Node_Id) return Traverse_Result is
142 begin
143 case Nkind (N) is
144 when N_Entity'Range =>
145 if Is_Eliminated (N) then
146 Set_Is_Public (N, False);
147 end if;
149 Set_Marked (Marks, N, Is_Public (N));
151 when N_Subprogram_Body =>
152 Traverse (Spec_Of (N));
154 when N_Package_Body_Stub =>
155 if Present (Library_Unit (N)) then
156 Traverse (Proper_Body (Unit (Library_Unit (N))));
157 end if;
159 when N_Package_Body =>
160 declare
161 Elmt : Node_Id := First (Declarations (N));
162 begin
163 while Present (Elmt) loop
164 Traverse (Elmt);
165 Next (Elmt);
166 end loop;
167 end;
169 when others =>
170 null;
171 end case;
173 return OK;
174 end Process;
176 -- Start of processing for Init_Marked
178 begin
179 Marks := (others => False);
180 Traverse (Root);
181 end Init_Marked;
183 ----------
184 -- Mark --
185 ----------
187 procedure Mark (Root : Node_Id; Marks : out Name_Set) is
188 begin
189 Init_Marked (Root, Marks);
190 Trace_Marked (Root, Marks);
191 end Mark;
193 ------------
194 -- Marked --
195 ------------
197 function Marked (Marks : Name_Set; Name : Node_Id) return Boolean is
198 begin
199 return Marks (Name);
200 end Marked;
202 ----------------
203 -- Set_Marked --
204 ----------------
206 procedure Set_Marked
207 (Marks : in out Name_Set;
208 Name : Node_Id;
209 Mark : Boolean := True)
211 begin
212 Marks (Name) := Mark;
213 end Set_Marked;
215 -------------
216 -- Spec_Of --
217 -------------
219 function Spec_Of (N : Node_Id) return Entity_Id is
220 begin
221 if Acts_As_Spec (N) then
222 return Defining_Entity (N);
223 else
224 return Corresponding_Spec (N);
225 end if;
226 end Spec_Of;
228 -----------
229 -- Sweep --
230 -----------
232 procedure Sweep (Root : Node_Id; Marks : Name_Set) is
234 function Process (N : Node_Id) return Traverse_Result;
235 procedure Traverse is new Traverse_Proc (Process);
237 function Process (N : Node_Id) return Traverse_Result is
238 begin
239 case Nkind (N) is
240 when N_Entity'Range =>
241 Set_Is_Eliminated (N, not Marked (Marks, N));
243 when N_Subprogram_Body =>
244 Traverse (Spec_Of (N));
246 when N_Package_Body_Stub =>
247 if Present (Library_Unit (N)) then
248 Traverse (Proper_Body (Unit (Library_Unit (N))));
249 end if;
251 when N_Package_Body =>
252 declare
253 Elmt : Node_Id := First (Declarations (N));
254 begin
255 while Present (Elmt) loop
256 Traverse (Elmt);
257 Next (Elmt);
258 end loop;
259 end;
261 when others =>
262 null;
263 end case;
264 return OK;
265 end Process;
267 begin
268 Traverse (Root);
269 end Sweep;
271 ------------------
272 -- Trace_Marked --
273 ------------------
275 procedure Trace_Marked (Root : Node_Id; Marks : in out Name_Set) is
277 function Process (N : Node_Id) return Traverse_Result;
278 procedure Process (N : Node_Id);
279 procedure Traverse is new Traverse_Proc (Process);
281 procedure Process (N : Node_Id) is
282 Result : Traverse_Result;
283 begin
284 Result := Process (N);
285 end Process;
287 function Process (N : Node_Id) return Traverse_Result is
288 Result : Traverse_Result := OK;
289 B : Node_Id;
290 E : Entity_Id;
292 begin
293 case Nkind (N) is
294 when N_Pragma | N_Generic_Declaration'Range |
295 N_Subprogram_Declaration | N_Subprogram_Body_Stub =>
296 Result := Skip;
298 when N_Subprogram_Body =>
299 if not Marked (Marks, Spec_Of (N)) then
300 Result := Skip;
301 end if;
303 when N_Package_Body_Stub =>
304 if Present (Library_Unit (N)) then
305 Traverse (Proper_Body (Unit (Library_Unit (N))));
306 end if;
308 when N_Identifier | N_Operator_Symbol | N_Expanded_Name =>
309 E := Entity (N);
311 if E /= Empty and then not Marked (Marks, E) then
312 Process (E);
314 if Is_Subprogram (E) then
315 B := Body_Of (E);
317 if B /= Empty then
318 Traverse (B);
319 end if;
320 end if;
321 end if;
323 when N_Entity'Range =>
324 if (Ekind (N) = E_Component) and then not Marked (Marks, N) then
325 if Present (Discriminant_Checking_Func (N)) then
326 Process (Discriminant_Checking_Func (N));
327 end if;
328 end if;
330 Set_Marked (Marks, N);
332 when others =>
333 null;
334 end case;
336 return Result;
337 end Process;
339 -- Start of processing for Trace_Marked
341 begin
342 Traverse (Root);
343 end Trace_Marked;
345 end Live;