OSDN Git Service

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