FSF GCC merge 02/23/03
[official-gcc.git] / gcc / ada / inline.adb
blobcb589dba37d6c8b1df1166d1901e280e8a6f26d4
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- I N L I N E --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1992-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 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 -- --
26 ------------------------------------------------------------------------------
28 with Atree; use Atree;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Ch7; use Exp_Ch7;
33 with Exp_Ch11; use Exp_Ch11;
34 with Exp_Tss; use Exp_Tss;
35 with Fname; use Fname;
36 with Fname.UF; use Fname.UF;
37 with Lib; use Lib;
38 with Nlists; use Nlists;
39 with Opt; use Opt;
40 with Sem_Ch8; use Sem_Ch8;
41 with Sem_Ch10; use Sem_Ch10;
42 with Sem_Ch12; use Sem_Ch12;
43 with Sem_Util; use Sem_Util;
44 with Sinfo; use Sinfo;
45 with Snames; use Snames;
46 with Stand; use Stand;
47 with Uname; use Uname;
49 package body Inline is
51 --------------------
52 -- Inlined Bodies --
53 --------------------
55 -- Inlined functions are actually placed in line by the backend if the
56 -- corresponding bodies are available (i.e. compiled). Whenever we find
57 -- a call to an inlined subprogram, we add the name of the enclosing
58 -- compilation unit to a worklist. After all compilation, and after
59 -- expansion of generic bodies, we traverse the list of pending bodies
60 -- and compile them as well.
62 package Inlined_Bodies is new Table.Table (
63 Table_Component_Type => Entity_Id,
64 Table_Index_Type => Int,
65 Table_Low_Bound => 0,
66 Table_Initial => Alloc.Inlined_Bodies_Initial,
67 Table_Increment => Alloc.Inlined_Bodies_Increment,
68 Table_Name => "Inlined_Bodies");
70 -----------------------
71 -- Inline Processing --
72 -----------------------
74 -- For each call to an inlined subprogram, we make entries in a table
75 -- that stores caller and callee, and indicates a prerequisite from
76 -- one to the other. We also record the compilation unit that contains
77 -- the callee. After analyzing the bodies of all such compilation units,
78 -- we produce a list of subprograms in topological order, for use by the
79 -- back-end. If P2 is a prerequisite of P1, then P1 calls P2, and for
80 -- proper inlining the back-end must analyze the body of P2 before that of
81 -- P1. The code below guarantees that the transitive closure of inlined
82 -- subprograms called from the main compilation unit is made available to
83 -- the code generator.
85 Last_Inlined : Entity_Id := Empty;
87 -- For each entry in the table we keep a list of successors in topological
88 -- order, i.e. callers of the current subprogram.
90 type Subp_Index is new Nat;
91 No_Subp : constant Subp_Index := 0;
93 -- The subprogram entities are hashed into the Inlined table.
95 Num_Hash_Headers : constant := 512;
97 Hash_Headers : array (Subp_Index range 0 .. Num_Hash_Headers - 1)
98 of Subp_Index;
100 type Succ_Index is new Nat;
101 No_Succ : constant Succ_Index := 0;
103 type Succ_Info is record
104 Subp : Subp_Index;
105 Next : Succ_Index;
106 end record;
108 -- The following table stores list elements for the successor lists.
109 -- These lists cannot be chained directly through entries in the Inlined
110 -- table, because a given subprogram can appear in several such lists.
112 package Successors is new Table.Table (
113 Table_Component_Type => Succ_Info,
114 Table_Index_Type => Succ_Index,
115 Table_Low_Bound => 1,
116 Table_Initial => Alloc.Successors_Initial,
117 Table_Increment => Alloc.Successors_Increment,
118 Table_Name => "Successors");
120 type Subp_Info is record
121 Name : Entity_Id := Empty;
122 First_Succ : Succ_Index := No_Succ;
123 Count : Integer := 0;
124 Listed : Boolean := False;
125 Main_Call : Boolean := False;
126 Next : Subp_Index := No_Subp;
127 Next_Nopred : Subp_Index := No_Subp;
128 end record;
130 package Inlined is new Table.Table (
131 Table_Component_Type => Subp_Info,
132 Table_Index_Type => Subp_Index,
133 Table_Low_Bound => 1,
134 Table_Initial => Alloc.Inlined_Initial,
135 Table_Increment => Alloc.Inlined_Increment,
136 Table_Name => "Inlined");
138 -----------------------
139 -- Local Subprograms --
140 -----------------------
142 function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean;
143 -- Return True if Scop is in the main unit or its spec, or in a
144 -- parent of the main unit if it is a child unit.
146 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty);
147 -- Make two entries in Inlined table, for an inlined subprogram being
148 -- called, and for the inlined subprogram that contains the call. If
149 -- the call is in the main compilation unit, Caller is Empty.
151 function Add_Subp (E : Entity_Id) return Subp_Index;
152 -- Make entry in Inlined table for subprogram E, or return table index
153 -- that already holds E.
155 function Has_Initialized_Type (E : Entity_Id) return Boolean;
156 -- If a candidate for inlining contains type declarations for types with
157 -- non-trivial initialization procedures, they are not worth inlining.
159 function Is_Nested (E : Entity_Id) return Boolean;
160 -- If the function is nested inside some other function, it will
161 -- always be compiled if that function is, so don't add it to the
162 -- inline list. We cannot compile a nested function outside the
163 -- scope of the containing function anyway. This is also the case if
164 -- the function is defined in a task body or within an entry (for
165 -- example, an initialization procedure).
167 procedure Add_Inlined_Subprogram (Index : Subp_Index);
168 -- Add subprogram to Inlined List once all of its predecessors have been
169 -- placed on the list. Decrement the count of all its successors, and
170 -- add them to list (recursively) if count drops to zero.
172 ------------------------------
173 -- Deferred Cleanup Actions --
174 ------------------------------
176 -- The cleanup actions for scopes that contain instantiations is delayed
177 -- until after expansion of those instantiations, because they may
178 -- contain finalizable objects or tasks that affect the cleanup code.
179 -- A scope that contains instantiations only needs to be finalized once,
180 -- even if it contains more than one instance. We keep a list of scopes
181 -- that must still be finalized, and call cleanup_actions after all the
182 -- instantiations have been completed.
184 To_Clean : Elist_Id;
186 procedure Add_Scope_To_Clean (Inst : Entity_Id);
187 -- Build set of scopes on which cleanup actions must be performed.
189 procedure Cleanup_Scopes;
190 -- Complete cleanup actions on scopes that need it.
192 --------------
193 -- Add_Call --
194 --------------
196 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty) is
197 P1 : Subp_Index := Add_Subp (Called);
198 P2 : Subp_Index;
199 J : Succ_Index;
201 begin
202 if Present (Caller) then
203 P2 := Add_Subp (Caller);
205 -- Add P2 to the list of successors of P1, if not already there.
206 -- Note that P2 may contain more than one call to P1, and only
207 -- one needs to be recorded.
209 J := Inlined.Table (P1).First_Succ;
211 while J /= No_Succ loop
213 if Successors.Table (J).Subp = P2 then
214 return;
215 end if;
217 J := Successors.Table (J).Next;
218 end loop;
220 -- On exit, make a successor entry for P2.
222 Successors.Increment_Last;
223 Successors.Table (Successors.Last).Subp := P2;
224 Successors.Table (Successors.Last).Next :=
225 Inlined.Table (P1).First_Succ;
226 Inlined.Table (P1).First_Succ := Successors.Last;
228 Inlined.Table (P2).Count := Inlined.Table (P2).Count + 1;
230 else
231 Inlined.Table (P1).Main_Call := True;
232 end if;
233 end Add_Call;
235 ----------------------
236 -- Add_Inlined_Body --
237 ----------------------
239 procedure Add_Inlined_Body (E : Entity_Id) is
240 Pack : Entity_Id;
241 Comp_Unit : Node_Id;
243 function Must_Inline return Boolean;
244 -- Inlining is only done if the call statement N is in the main unit,
245 -- or within the body of another inlined subprogram.
247 function Must_Inline return Boolean is
248 Scop : Entity_Id := Current_Scope;
249 Comp : Node_Id;
251 begin
252 -- Check if call is in main unit.
254 while Scope (Scop) /= Standard_Standard
255 and then not Is_Child_Unit (Scop)
256 loop
257 Scop := Scope (Scop);
258 end loop;
260 Comp := Parent (Scop);
262 while Nkind (Comp) /= N_Compilation_Unit loop
263 Comp := Parent (Comp);
264 end loop;
266 if (Comp = Cunit (Main_Unit)
267 or else Comp = Library_Unit (Cunit (Main_Unit)))
268 then
269 Add_Call (E);
270 return True;
271 end if;
273 -- Call is not in main unit. See if it's in some inlined
274 -- subprogram.
276 Scop := Current_Scope;
277 while Scope (Scop) /= Standard_Standard
278 and then not Is_Child_Unit (Scop)
279 loop
280 if Is_Overloadable (Scop)
281 and then Is_Inlined (Scop)
282 then
283 Add_Call (E, Scop);
284 return True;
285 end if;
287 Scop := Scope (Scop);
288 end loop;
290 return False;
292 end Must_Inline;
294 -- Start of processing for Add_Inlined_Body
296 begin
297 -- Find unit containing E, and add to list of inlined bodies if needed.
298 -- If the body is already present, no need to load any other unit. This
299 -- is the case for an initialization procedure, which appears in the
300 -- package declaration that contains the type. It is also the case if
301 -- the body has already been analyzed. Finally, if the unit enclosing
302 -- E is an instance, the instance body will be analyzed in any case,
303 -- and there is no need to add the enclosing unit (whose body might not
304 -- be available).
306 -- Library-level functions must be handled specially, because there is
307 -- no enclosing package to retrieve. In this case, it is the body of
308 -- the function that will have to be loaded.
310 if not Is_Abstract (E) and then not Is_Nested (E)
311 and then Convention (E) /= Convention_Protected
312 then
313 Pack := Scope (E);
315 if Must_Inline
316 and then Ekind (Pack) = E_Package
317 then
318 Set_Is_Called (E);
319 Comp_Unit := Parent (Pack);
321 if Pack = Standard_Standard then
323 -- Library-level inlined function. Add function iself to
324 -- list of needed units.
326 Inlined_Bodies.Increment_Last;
327 Inlined_Bodies.Table (Inlined_Bodies.Last) := E;
329 elsif Is_Generic_Instance (Pack) then
330 null;
332 elsif not Is_Inlined (Pack)
333 and then not Has_Completion (E)
334 and then not Scope_In_Main_Unit (Pack)
335 then
336 Set_Is_Inlined (Pack);
337 Inlined_Bodies.Increment_Last;
338 Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
339 end if;
340 end if;
341 end if;
342 end Add_Inlined_Body;
344 ----------------------------
345 -- Add_Inlined_Subprogram --
346 ----------------------------
348 procedure Add_Inlined_Subprogram (Index : Subp_Index) is
349 E : constant Entity_Id := Inlined.Table (Index).Name;
350 Succ : Succ_Index;
351 Subp : Subp_Index;
353 begin
354 -- Insert the current subprogram in the list of inlined subprograms
356 if not Scope_In_Main_Unit (E)
357 and then Is_Inlined (E)
358 and then not Is_Nested (E)
359 and then not Has_Initialized_Type (E)
360 then
361 if No (Last_Inlined) then
362 Set_First_Inlined_Subprogram (Cunit (Main_Unit), E);
363 else
364 Set_Next_Inlined_Subprogram (Last_Inlined, E);
365 end if;
367 Last_Inlined := E;
368 end if;
370 Inlined.Table (Index).Listed := True;
371 Succ := Inlined.Table (Index).First_Succ;
373 while Succ /= No_Succ loop
374 Subp := Successors.Table (Succ).Subp;
375 Inlined.Table (Subp).Count := Inlined.Table (Subp).Count - 1;
377 if Inlined.Table (Subp).Count = 0 then
378 Add_Inlined_Subprogram (Subp);
379 end if;
381 Succ := Successors.Table (Succ).Next;
382 end loop;
383 end Add_Inlined_Subprogram;
385 ------------------------
386 -- Add_Scope_To_Clean --
387 ------------------------
389 procedure Add_Scope_To_Clean (Inst : Entity_Id) is
390 Elmt : Elmt_Id;
391 Scop : Entity_Id := Enclosing_Dynamic_Scope (Inst);
393 begin
394 -- If the instance appears in a library-level package declaration,
395 -- all finalization is global, and nothing needs doing here.
397 if Scop = Standard_Standard then
398 return;
399 end if;
401 Elmt := First_Elmt (To_Clean);
403 while Present (Elmt) loop
405 if Node (Elmt) = Scop then
406 return;
407 end if;
409 Elmt := Next_Elmt (Elmt);
410 end loop;
412 Append_Elmt (Scop, To_Clean);
413 end Add_Scope_To_Clean;
415 --------------
416 -- Add_Subp --
417 --------------
419 function Add_Subp (E : Entity_Id) return Subp_Index is
420 Index : Subp_Index := Subp_Index (E) mod Num_Hash_Headers;
421 J : Subp_Index;
423 procedure New_Entry;
424 -- Initialize entry in Inlined table.
426 procedure New_Entry is
427 begin
428 Inlined.Increment_Last;
429 Inlined.Table (Inlined.Last).Name := E;
430 Inlined.Table (Inlined.Last).First_Succ := No_Succ;
431 Inlined.Table (Inlined.Last).Count := 0;
432 Inlined.Table (Inlined.Last).Listed := False;
433 Inlined.Table (Inlined.Last).Main_Call := False;
434 Inlined.Table (Inlined.Last).Next := No_Subp;
435 Inlined.Table (Inlined.Last).Next_Nopred := No_Subp;
436 end New_Entry;
438 -- Start of processing for Add_Subp
440 begin
441 if Hash_Headers (Index) = No_Subp then
442 New_Entry;
443 Hash_Headers (Index) := Inlined.Last;
444 return Inlined.Last;
446 else
447 J := Hash_Headers (Index);
449 while J /= No_Subp loop
451 if Inlined.Table (J).Name = E then
452 return J;
453 else
454 Index := J;
455 J := Inlined.Table (J).Next;
456 end if;
457 end loop;
459 -- On exit, subprogram was not found. Enter in table. Index is
460 -- the current last entry on the hash chain.
462 New_Entry;
463 Inlined.Table (Index).Next := Inlined.Last;
464 return Inlined.Last;
465 end if;
466 end Add_Subp;
468 ----------------------------
469 -- Analyze_Inlined_Bodies --
470 ----------------------------
472 procedure Analyze_Inlined_Bodies is
473 Comp_Unit : Node_Id;
474 J : Int;
475 Pack : Entity_Id;
476 S : Succ_Index;
478 begin
479 Analyzing_Inlined_Bodies := False;
481 if Serious_Errors_Detected = 0 then
482 New_Scope (Standard_Standard);
484 J := 0;
485 while J <= Inlined_Bodies.Last
486 and then Serious_Errors_Detected = 0
487 loop
488 Pack := Inlined_Bodies.Table (J);
490 while Present (Pack)
491 and then Scope (Pack) /= Standard_Standard
492 and then not Is_Child_Unit (Pack)
493 loop
494 Pack := Scope (Pack);
495 end loop;
497 Comp_Unit := Parent (Pack);
499 while Present (Comp_Unit)
500 and then Nkind (Comp_Unit) /= N_Compilation_Unit
501 loop
502 Comp_Unit := Parent (Comp_Unit);
503 end loop;
505 -- Load the body, unless it the main unit, or is an instance
506 -- whose body has already been analyzed.
508 if Present (Comp_Unit)
509 and then Comp_Unit /= Cunit (Main_Unit)
510 and then Body_Required (Comp_Unit)
511 and then (Nkind (Unit (Comp_Unit)) /= N_Package_Declaration
512 or else No (Corresponding_Body (Unit (Comp_Unit))))
513 then
514 declare
515 Bname : constant Unit_Name_Type :=
516 Get_Body_Name (Get_Unit_Name (Unit (Comp_Unit)));
518 OK : Boolean;
520 begin
521 if not Is_Loaded (Bname) then
522 Load_Needed_Body (Comp_Unit, OK);
524 if not OK then
525 Error_Msg_Unit_1 := Bname;
526 Error_Msg_N
527 ("one or more inlined subprograms accessed in $!",
528 Comp_Unit);
529 Error_Msg_Name_1 :=
530 Get_File_Name (Bname, Subunit => False);
531 Error_Msg_N ("\but file{ was not found!", Comp_Unit);
532 raise Unrecoverable_Error;
533 end if;
534 end if;
535 end;
536 end if;
538 J := J + 1;
539 end loop;
541 -- The analysis of required bodies may have produced additional
542 -- generic instantiations. To obtain further inlining, we perform
543 -- another round of generic body instantiations. Establishing a
544 -- fully recursive loop between inlining and generic instantiations
545 -- is unlikely to yield more than this one additional pass.
547 Instantiate_Bodies;
549 -- The list of inlined subprograms is an overestimate, because
550 -- it includes inlined functions called from functions that are
551 -- compiled as part of an inlined package, but are not themselves
552 -- called. An accurate computation of just those subprograms that
553 -- are needed requires that we perform a transitive closure over
554 -- the call graph, starting from calls in the main program. Here
555 -- we do one step of the inverse transitive closure, and reset
556 -- the Is_Called flag on subprograms all of whose callers are not.
558 for Index in Inlined.First .. Inlined.Last loop
559 S := Inlined.Table (Index).First_Succ;
561 if S /= No_Succ
562 and then not Inlined.Table (Index).Main_Call
563 then
564 Set_Is_Called (Inlined.Table (Index).Name, False);
566 while S /= No_Succ loop
568 if Is_Called
569 (Inlined.Table (Successors.Table (S).Subp).Name)
570 or else Inlined.Table (Successors.Table (S).Subp).Main_Call
571 then
572 Set_Is_Called (Inlined.Table (Index).Name);
573 exit;
574 end if;
576 S := Successors.Table (S).Next;
577 end loop;
578 end if;
579 end loop;
581 -- Now that the units are compiled, chain the subprograms within
582 -- that are called and inlined. Produce list of inlined subprograms
583 -- sorted in topological order. Start with all subprograms that
584 -- have no prerequisites, i.e. inlined subprograms that do not call
585 -- other inlined subprograms.
587 for Index in Inlined.First .. Inlined.Last loop
589 if Is_Called (Inlined.Table (Index).Name)
590 and then Inlined.Table (Index).Count = 0
591 and then not Inlined.Table (Index).Listed
592 then
593 Add_Inlined_Subprogram (Index);
594 end if;
595 end loop;
597 -- Because Add_Inlined_Subprogram treats recursively nodes that have
598 -- no prerequisites left, at the end of the loop all subprograms
599 -- must have been listed. If there are any unlisted subprograms
600 -- left, there must be some recursive chains that cannot be inlined.
602 for Index in Inlined.First .. Inlined.Last loop
603 if Is_Called (Inlined.Table (Index).Name)
604 and then Inlined.Table (Index).Count /= 0
605 and then not Is_Predefined_File_Name
606 (Unit_File_Name
607 (Get_Source_Unit (Inlined.Table (Index).Name)))
608 then
609 Error_Msg_N
610 ("& cannot be inlined?", Inlined.Table (Index).Name);
611 -- A warning on the first one might be sufficient.
612 end if;
613 end loop;
615 Pop_Scope;
616 end if;
617 end Analyze_Inlined_Bodies;
619 --------------------------------
620 -- Check_Body_For_Inlining --
621 --------------------------------
623 procedure Check_Body_For_Inlining (N : Node_Id; P : Entity_Id) is
624 Bname : Unit_Name_Type;
625 E : Entity_Id;
626 OK : Boolean;
628 begin
629 if Is_Compilation_Unit (P)
630 and then not Is_Generic_Instance (P)
631 then
632 Bname := Get_Body_Name (Get_Unit_Name (Unit (N)));
633 E := First_Entity (P);
635 while Present (E) loop
636 if Has_Pragma_Inline (E) then
637 if not Is_Loaded (Bname) then
638 Load_Needed_Body (N, OK);
640 if not OK
641 and then Ineffective_Inline_Warnings
642 then
643 Error_Msg_Unit_1 := Bname;
644 Error_Msg_N
645 ("unable to inline subprograms defined in $?", P);
646 Error_Msg_N ("\body not found?", P);
647 return;
648 end if;
649 end if;
651 return;
652 end if;
654 Next_Entity (E);
655 end loop;
656 end if;
657 end Check_Body_For_Inlining;
659 --------------------
660 -- Cleanup_Scopes --
661 --------------------
663 procedure Cleanup_Scopes is
664 Elmt : Elmt_Id;
665 Decl : Node_Id;
666 Scop : Entity_Id;
668 begin
669 Elmt := First_Elmt (To_Clean);
671 while Present (Elmt) loop
672 Scop := Node (Elmt);
674 if Ekind (Scop) = E_Entry then
675 Scop := Protected_Body_Subprogram (Scop);
676 end if;
678 if Ekind (Scop) = E_Block then
679 Decl := Parent (Block_Node (Scop));
681 else
682 Decl := Unit_Declaration_Node (Scop);
684 if Nkind (Decl) = N_Subprogram_Declaration
685 or else Nkind (Decl) = N_Task_Type_Declaration
686 or else Nkind (Decl) = N_Subprogram_Body_Stub
687 then
688 Decl := Unit_Declaration_Node (Corresponding_Body (Decl));
689 end if;
690 end if;
692 New_Scope (Scop);
693 Expand_Cleanup_Actions (Decl);
694 End_Scope;
696 Elmt := Next_Elmt (Elmt);
697 end loop;
698 end Cleanup_Scopes;
700 --------------------------
701 -- Has_Initialized_Type --
702 --------------------------
704 function Has_Initialized_Type (E : Entity_Id) return Boolean is
705 E_Body : constant Node_Id := Get_Subprogram_Body (E);
706 Decl : Node_Id;
708 begin
709 if No (E_Body) then -- imported subprogram
710 return False;
712 else
713 Decl := First (Declarations (E_Body));
715 while Present (Decl) loop
717 if Nkind (Decl) = N_Full_Type_Declaration
718 and then Present (Init_Proc (Defining_Identifier (Decl)))
719 then
720 return True;
721 end if;
723 Next (Decl);
724 end loop;
725 end if;
727 return False;
728 end Has_Initialized_Type;
730 ----------------
731 -- Initialize --
732 ----------------
734 procedure Initialize is
735 begin
736 Analyzing_Inlined_Bodies := False;
737 Pending_Descriptor.Init;
738 Pending_Instantiations.Init;
739 Inlined_Bodies.Init;
740 Successors.Init;
741 Inlined.Init;
743 for J in Hash_Headers'Range loop
744 Hash_Headers (J) := No_Subp;
745 end loop;
746 end Initialize;
748 ------------------------
749 -- Instantiate_Bodies --
750 ------------------------
752 -- Generic bodies contain all the non-local references, so an
753 -- instantiation does not need any more context than Standard
754 -- itself, even if the instantiation appears in an inner scope.
755 -- Generic associations have verified that the contract model is
756 -- satisfied, so that any error that may occur in the analysis of
757 -- the body is an internal error.
759 procedure Instantiate_Bodies is
760 J : Int;
761 Info : Pending_Body_Info;
763 begin
764 if Serious_Errors_Detected = 0 then
766 Expander_Active := (Operating_Mode = Opt.Generate_Code);
767 New_Scope (Standard_Standard);
768 To_Clean := New_Elmt_List;
770 if Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
771 Start_Generic;
772 end if;
774 -- A body instantiation may generate additional instantiations, so
775 -- the following loop must scan to the end of a possibly expanding
776 -- set (that's why we can't simply use a FOR loop here).
778 J := 0;
780 while J <= Pending_Instantiations.Last
781 and then Serious_Errors_Detected = 0
782 loop
784 Info := Pending_Instantiations.Table (J);
786 -- If the instantiation node is absent, it has been removed
787 -- as part of unreachable code.
789 if No (Info.Inst_Node) then
790 null;
792 elsif Nkind (Info. Act_Decl) = N_Package_Declaration then
793 Instantiate_Package_Body (Info);
794 Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl));
796 else
797 Instantiate_Subprogram_Body (Info);
798 end if;
800 J := J + 1;
801 end loop;
803 -- Reset the table of instantiations. Additional instantiations
804 -- may be added through inlining, when additional bodies are
805 -- analyzed.
807 Pending_Instantiations.Init;
809 -- We can now complete the cleanup actions of scopes that contain
810 -- pending instantiations (skipped for generic units, since we
811 -- never need any cleanups in generic units).
812 -- pending instantiations.
814 if Expander_Active
815 and then not Is_Generic_Unit (Main_Unit_Entity)
816 then
817 Cleanup_Scopes;
819 -- Also generate subprogram descriptors that were delayed
821 for J in Pending_Descriptor.First .. Pending_Descriptor.Last loop
822 declare
823 Ent : constant Entity_Id := Pending_Descriptor.Table (J);
825 begin
826 if Is_Subprogram (Ent) then
827 Generate_Subprogram_Descriptor_For_Subprogram
828 (Get_Subprogram_Body (Ent), Ent);
830 elsif Ekind (Ent) = E_Package then
831 Generate_Subprogram_Descriptor_For_Package
832 (Parent (Declaration_Node (Ent)), Ent);
834 elsif Ekind (Ent) = E_Package_Body then
835 Generate_Subprogram_Descriptor_For_Package
836 (Declaration_Node (Ent), Ent);
837 end if;
838 end;
839 end loop;
841 elsif Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
842 End_Generic;
843 end if;
845 Pop_Scope;
846 end if;
847 end Instantiate_Bodies;
849 ---------------
850 -- Is_Nested --
851 ---------------
853 function Is_Nested (E : Entity_Id) return Boolean is
854 Scop : Entity_Id := Scope (E);
856 begin
857 while Scop /= Standard_Standard loop
858 if Ekind (Scop) in Subprogram_Kind then
859 return True;
861 elsif Ekind (Scop) = E_Task_Type
862 or else Ekind (Scop) = E_Entry
863 or else Ekind (Scop) = E_Entry_Family then
864 return True;
865 end if;
867 Scop := Scope (Scop);
868 end loop;
870 return False;
871 end Is_Nested;
873 ----------
874 -- Lock --
875 ----------
877 procedure Lock is
878 begin
879 Pending_Instantiations.Locked := True;
880 Inlined_Bodies.Locked := True;
881 Successors.Locked := True;
882 Inlined.Locked := True;
883 Pending_Instantiations.Release;
884 Inlined_Bodies.Release;
885 Successors.Release;
886 Inlined.Release;
887 end Lock;
889 --------------------------
890 -- Remove_Dead_Instance --
891 --------------------------
893 procedure Remove_Dead_Instance (N : Node_Id) is
894 J : Int;
896 begin
897 J := 0;
899 while J <= Pending_Instantiations.Last loop
901 if Pending_Instantiations.Table (J).Inst_Node = N then
902 Pending_Instantiations.Table (J).Inst_Node := Empty;
903 return;
904 end if;
906 J := J + 1;
907 end loop;
908 end Remove_Dead_Instance;
910 ------------------------
911 -- Scope_In_Main_Unit --
912 ------------------------
914 function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean is
915 Comp : Node_Id;
916 S : Entity_Id := Scop;
917 Ent : Entity_Id := Cunit_Entity (Main_Unit);
919 begin
920 -- The scope may be within the main unit, or it may be an ancestor
921 -- of the main unit, if the main unit is a child unit. In both cases
922 -- it makes no sense to process the body before the main unit. In
923 -- the second case, this may lead to circularities if a parent body
924 -- depends on a child spec, and we are analyzing the child.
926 while Scope (S) /= Standard_Standard
927 and then not Is_Child_Unit (S)
928 loop
929 S := Scope (S);
930 end loop;
932 Comp := Parent (S);
934 while Present (Comp)
935 and then Nkind (Comp) /= N_Compilation_Unit
936 loop
937 Comp := Parent (Comp);
938 end loop;
940 if Is_Child_Unit (Ent) then
942 while Present (Ent)
943 and then Is_Child_Unit (Ent)
944 loop
945 if Scope (Ent) = S then
946 return True;
947 end if;
949 Ent := Scope (Ent);
950 end loop;
951 end if;
953 return
954 Comp = Cunit (Main_Unit)
955 or else Comp = Library_Unit (Cunit (Main_Unit));
956 end Scope_In_Main_Unit;
958 end Inline;