------------------------------------------------------------------------------ -- -- -- GNAT COMPILER COMPONENTS -- -- -- -- B I N D O . E L A B O R A T O R S -- -- -- -- B o d y -- -- -- -- Copyright (C) 2019-2024, 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. -- -- -- ------------------------------------------------------------------------------ with Butil; use Butil; with Debug; use Debug; with Output; use Output; with Types; use Types; with Bindo.Augmentors; use Bindo.Augmentors; use Bindo.Augmentors.Library_Graph_Augmentors; with Bindo.Builders; use Bindo.Builders; use Bindo.Builders.Invocation_Graph_Builders; use Bindo.Builders.Library_Graph_Builders; with Bindo.Diagnostics; use Bindo.Diagnostics; with Bindo.Units; use Bindo.Units; with Bindo.Validators; use Bindo.Validators; use Bindo.Validators.Elaboration_Order_Validators; with Bindo.Writers; use Bindo.Writers; use Bindo.Writers.ALI_Writers; use Bindo.Writers.Dependency_Writers; use Bindo.Writers.Elaboration_Order_Writers; use Bindo.Writers.Invocation_Graph_Writers; use Bindo.Writers.Library_Graph_Writers; use Bindo.Writers.Phase_Writers; use Bindo.Writers.Unit_Closure_Writers; with GNAT; use GNAT; with GNAT.Graphs; use GNAT.Graphs; package body Bindo.Elaborators is -- The following type defines the advancement of the elaboration order -- algorithm in terms of steps. type Elaboration_Order_Step is new Natural; Initial_Step : constant Elaboration_Order_Step := Elaboration_Order_Step'First; ---------------------------------------------- -- Invocation_And_Library_Graph_Elaborators -- ---------------------------------------------- package body Invocation_And_Library_Graph_Elaborators is ----------------------- -- Local subprograms -- ----------------------- procedure Create_Component_Vertex_Sets (G : Library_Graph; Comp : Component_Id; Elaborable_Vertices : out LGV_Sets.Membership_Set; Waiting_Vertices : out LGV_Sets.Membership_Set; Step : Elaboration_Order_Step); pragma Inline (Create_Component_Vertex_Sets); -- Split all vertices of component Comp of library graph G as follows: -- -- * Elaborable vertices are added to set Elaborable_Vertices. -- -- * Vertices that are still waiting on their predecessors to be -- elaborated are added to set Waiting_Vertices. -- -- Step is the current step in the elaboration order. procedure Create_Vertex_Sets (G : Library_Graph; Elaborable_Vertices : out LGV_Sets.Membership_Set; Waiting_Vertices : out LGV_Sets.Membership_Set; Step : Elaboration_Order_Step); pragma Inline (Create_Vertex_Sets); -- Split all vertices of library graph G as follows: -- -- * Elaborable vertices are added to set Elaborable_Vertices. -- -- * Vertices that are still waiting on their predecessors to be -- elaborated are added to set Waiting_Vertices. -- -- Step is the current step in the elaboration order. procedure Elaborate_Component (G : Library_Graph; Comp : Component_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step); pragma Inline (Elaborate_Component); -- Elaborate as many vertices as possible that appear in component Comp -- of library graph G. The sets contain vertices arranged as follows: -- -- * All_Elaborable_Vertices - all elaborable vertices in the library -- graph. -- -- * All_Waiting_Vertices - all vertices in the library graph that are -- waiting on predecessors to be elaborated. -- -- Order is the elaboration order. Step denotes the current step in the -- elaboration order. procedure Elaborate_Library_Graph (G : Library_Graph; Order : out Unit_Id_Table; Status : out Elaboration_Order_Status); pragma Inline (Elaborate_Library_Graph); -- Elaborate as many vertices as possible of library graph G. Order is -- the elaboration order. Status is the condition of the elaboration -- order. procedure Elaborate_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Elaborate_Vertex); -- Elaborate vertex Vertex of library graph G by adding its unit to -- elaboration order Order. The routine updates awaiting successors -- where applicable. The sets contain vertices arranged as follows: -- -- * All_Elaborable_Vertices - all elaborable vertices in the library -- graph. -- -- * All_Waiting_Vertices - all vertices in the library graph that are -- waiting on predecessors to be elaborated. -- -- * Comp_Elaborable_Vertices - all elaborable vertices found in the -- component of Vertex. -- -- * Comp_Waiting_Vertices - all vertices found in the component of -- Vertex that are still waiting on predecessors to be elaborated. -- -- Order denotes the elaboration order. Step is the current step in the -- elaboration order. Indent denotes the desired indentation level for -- tracing. function Find_Best_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id; pragma Inline (Find_Best_Elaborable_Vertex); -- Find the best vertex of library graph G from membership set S that -- can be elaborated. Step is the current step in the elaboration order. -- Indent is the desired indentation level for tracing. function Find_Best_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Is_Suitable_Vertex : LGV_Predicate_Ptr; Compare_Vertices : LGV_Comparator_Ptr; Initial_Best_Msg : String; Subsequent_Best_Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id; pragma Inline (Find_Best_Vertex); -- Find the best vertex of library graph G from membership set S which -- satisfies predicate Is_Suitable_Vertex and is preferred by comparator -- Compare_Vertices. Initial_Best_Msg is emitted on the first candidate -- vertex. Subsequent_Best_Msg is emitted whenever a better vertex is -- discovered. Step is the current step in the elaboration order. Indent -- is the desired indentation level for tracing. function Find_Best_Weakly_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id; pragma Inline (Find_Best_Weakly_Elaborable_Vertex); -- Find the best vertex of library graph G from membership set S that -- can be weakly elaborated. Step is the current step in the elaboration -- order. Indent is the desired indentation level for tracing. function Has_Elaborable_Body (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Has_Elaborable_Body); -- Determine whether vertex Vertex of library graph G has a body that is -- elaborable. It is assumed that the vertex has been elaborated. procedure Insert_Elaborable_Successor (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Insert_Elaborable_Successor); -- Add elaborable successor Vertex of library graph G to membership set -- Elaborable_Vertices and remove it from both All_Waiting_Vertices and -- Comp_Waiting_Vertices. Msg is a message emitted for tracing purposes. -- Step is the current step in the elaboration order. Indent denotes the -- desired indentation level for tracing. procedure Insert_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Insert_Vertex); -- Add vertex Vertex of library graph G to membership set Set. Msg is -- a message emitted for tracing purposes. Step is the current step in -- the elaboration order. Indent is the desired indentation level for -- tracing. function Is_Better_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; pragma Inline (Is_Better_Elaborable_Vertex); -- Determine whether vertex Vertex of library graph G is a better choice -- for elaboration compared to vertex Compared_To. function Is_Better_Weakly_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; pragma Inline (Is_Better_Weakly_Elaborable_Vertex); -- Determine whether vertex Vertex of library graph G is a better choice -- for weak elaboration compared to vertex Compared_To. function Is_Suitable_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Suitable_Elaborable_Vertex); -- Determine whether vertex Vertex of library graph G is suitable for -- elaboration. function Is_Suitable_Weakly_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Suitable_Weakly_Elaborable_Vertex); -- Determine whether vertex Vertex of library graph G is suitable for -- weak elaboration. procedure Set_Unit_Elaboration_Positions (Order : Unit_Id_Table); pragma Inline (Set_Unit_Elaboration_Positions); -- Set the ALI.Units positions of all elaboration units in order Order procedure Trace_Component (G : Library_Graph; Comp : Component_Id; Msg : String; Step : Elaboration_Order_Step); pragma Inline (Trace_Component); -- Write elaboration-related information for component Comp of library -- graph G to standard output, starting with message Msg. Step is the -- current step in the elaboration order. procedure Trace_Step (Step : Elaboration_Order_Step); pragma Inline (Trace_Step); -- Write current step Step of the elaboration order to standard output procedure Trace_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Trace_Vertex); -- Write elaboration-related information for vertex Vertex of library -- graph G to standard output, starting with message Msg. Step is the -- current step in the elaboration order. Indent denotes the desired -- indentation level for tracing. procedure Trace_Vertices (G : Library_Graph; Set : LGV_Sets.Membership_Set; Set_Msg : String; Vertex_Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Trace_Vertices); -- Write the candidate vertices of library graph G present in membership -- set Set to standard output, starting with message Set_Msg. Vertex_Msg -- is the message emitted prior to each vertex. Step denotes the current -- step in the elaboration order. Indent denotes the desired indentation -- level for tracing. procedure Update_Successor (G : Library_Graph; Edge : Library_Graph_Edge_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Update_Successor); -- Notify the successor of edge Edge of library graph G along with its -- component that their predecessor has just been elaborated. This may -- cause new vertices to become elaborable. The sets contain vertices -- arranged as follows: -- -- * All_Elaborable_Vertices - all elaborable vertices in the library -- graph. -- -- * All_Waiting_Vertices - all vertices in the library graph that are -- waiting on predecessors to be elaborated. -- -- * Comp_Elaborable_Vertices - all elaborable vertices found in the -- component of Vertex. -- -- * Comp_Waiting_Vertices - all vertices found in the component of -- Vertex that are still waiting on predecessors to be elaborated. -- -- Step is the current step in the elaboration order. Indent denotes the -- desired indentation level for tracing. procedure Update_Successors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Update_Successors); -- Notify all successors of vertex Vertex of library graph G along with -- their components that their predecessor has just been elaborated. -- This may cause new vertices to become elaborable. The sets contain -- vertices arranged as follows: -- -- * All_Elaborable_Vertices - all elaborable vertices in the library -- graph. -- -- * All_Waiting_Vertices - all vertices in the library graph that are -- waiting on predecessors to be elaborated. -- -- * Comp_Elaborable_Vertices - all elaborable vertices found in the -- component of Vertex. -- -- * Comp_Waiting_Vertices - all vertices found in the component of -- Vertex that are still waiting on predecessors to be elaborated. -- -- Step is the current step in the elaboration order. Indent denotes the -- desired indentation level for tracing. ---------------------------------- -- Create_Component_Vertex_Sets -- ---------------------------------- procedure Create_Component_Vertex_Sets (G : Library_Graph; Comp : Component_Id; Elaborable_Vertices : out LGV_Sets.Membership_Set; Waiting_Vertices : out LGV_Sets.Membership_Set; Step : Elaboration_Order_Step) is pragma Assert (Present (G)); pragma Assert (Present (Comp)); Num_Of_Vertices : constant Natural := Number_Of_Component_Vertices (G, Comp); Iter : Component_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id; begin Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices); Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices); Iter := Iterate_Component_Vertices (G, Comp); while Has_Next (Iter) loop Next (Iter, Vertex); -- Add the vertex to the proper set depending on whether it can be -- elaborated. if Is_Elaborable_Vertex (G, Vertex) then Insert_Vertex (G => G, Vertex => Vertex, Set => Elaborable_Vertices, Msg => "add elaborable component vertex", Step => Step, Indent => No_Indentation); else Insert_Vertex (G => G, Vertex => Vertex, Set => Waiting_Vertices, Msg => "add waiting component vertex", Step => Step, Indent => No_Indentation); end if; end loop; end Create_Component_Vertex_Sets; ------------------------ -- Create_Vertex_Sets -- ------------------------ procedure Create_Vertex_Sets (G : Library_Graph; Elaborable_Vertices : out LGV_Sets.Membership_Set; Waiting_Vertices : out LGV_Sets.Membership_Set; Step : Elaboration_Order_Step) is pragma Assert (Present (G)); Num_Of_Vertices : constant Natural := Number_Of_Vertices (G); Iter : Library_Graphs.All_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id; begin Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices); Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop Next (Iter, Vertex); -- Add the vertex to the proper set depending on whether it can be -- elaborated. if Is_Elaborable_Vertex (G, Vertex) then Insert_Vertex (G => G, Vertex => Vertex, Set => Elaborable_Vertices, Msg => "add elaborable vertex", Step => Step, Indent => No_Indentation); else Insert_Vertex (G => G, Vertex => Vertex, Set => Waiting_Vertices, Msg => "add waiting vertex", Step => Step, Indent => No_Indentation); end if; end loop; end Create_Vertex_Sets; ------------------------- -- Elaborate_Component -- ------------------------- procedure Elaborate_Component (G : Library_Graph; Comp : Component_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step) is Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); pragma Assert (Present (Comp)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); Trace_Component (G => G, Comp => Comp, Msg => "elaborating component", Step => Step); -- Divide all vertices of the component into an elaborable and -- waiting vertex set. Create_Component_Vertex_Sets (G => G, Comp => Comp, Elaborable_Vertices => Comp_Elaborable_Vertices, Waiting_Vertices => Comp_Waiting_Vertices, Step => Step); loop Trace_Vertices (G => G, Set => Comp_Elaborable_Vertices, Set_Msg => "elaborable component vertices", Vertex_Msg => "elaborable component vertex", Step => Step, Indent => Nested_Indentation); Trace_Vertices (G => G, Set => Comp_Waiting_Vertices, Set_Msg => "waiting component vertices", Vertex_Msg => "waiting component vertex", Step => Step, Indent => Nested_Indentation); Vertex := Find_Best_Elaborable_Vertex (G => G, Set => Comp_Elaborable_Vertices, Step => Step, Indent => Nested_Indentation); -- The component lacks an elaborable vertex. This indicates that -- either all vertices of the component have been elaborated or -- the graph has a circularity. Locate the best weak vertex that -- was compiled with the dynamic model to elaborate from the set -- waiting vertices. This action assumes that certain invocations -- will not take place at elaboration time. An order produced in -- this fashion may fail an ABE check at run time. if not Present (Vertex) then Vertex := Find_Best_Weakly_Elaborable_Vertex (G => G, Set => Comp_Waiting_Vertices, Step => Step, Indent => Nested_Indentation); end if; -- Stop the elaboration when either all vertices of the component -- have been elaborated, or the graph contains a circularity. exit when not Present (Vertex); -- Try to elaborate as many vertices within the component as -- possible. Each successful elaboration signals the appropriate -- successors and components that they have one less predecessor -- to wait on. Elaborate_Vertex (G => G, Vertex => Vertex, All_Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Order => Order, Step => Step, Indent => Nested_Indentation); end loop; LGV_Sets.Destroy (Comp_Elaborable_Vertices); LGV_Sets.Destroy (Comp_Waiting_Vertices); end Elaborate_Component; ----------------------------- -- Elaborate_Library_Graph -- ----------------------------- procedure Elaborate_Library_Graph (G : Library_Graph; Order : out Unit_Id_Table; Status : out Elaboration_Order_Status) is Elaborable_Vertices : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Vertex : Library_Graph_Vertex_Id; Waiting_Vertices : LGV_Sets.Membership_Set; begin pragma Assert (Present (G)); Step := Initial_Step; -- Divide all vertices of the library graph into an elaborable and -- waiting vertex set. Create_Vertex_Sets (G => G, Elaborable_Vertices => Elaborable_Vertices, Waiting_Vertices => Waiting_Vertices, Step => Step); loop Step := Step + 1; Trace_Vertices (G => G, Set => Elaborable_Vertices, Set_Msg => "elaborable vertices", Vertex_Msg => "elaborable vertex", Step => Step, Indent => No_Indentation); Trace_Vertices (G => G, Set => Waiting_Vertices, Set_Msg => "waiting vertices", Vertex_Msg => "waiting vertex", Step => Step, Indent => No_Indentation); Vertex := Find_Best_Elaborable_Vertex (G => G, Set => Elaborable_Vertices, Step => Step, Indent => No_Indentation); -- The graph lacks an elaborable vertex. This indicates that -- either all vertices have been elaborated or the graph has a -- circularity. Find the best weak vertex that was compiled with -- the dynamic model to elaborate from set of waiting vertices. -- This action assumes that certain invocations will not take -- place at elaboration time. An order produced in this fashion -- may fail an ABE check at run time. if not Present (Vertex) then Vertex := Find_Best_Weakly_Elaborable_Vertex (G => G, Set => Waiting_Vertices, Step => Step, Indent => No_Indentation); end if; -- Stop the elaboration when either all vertices of the graph have -- been elaborated, or the graph contains a circularity. exit when not Present (Vertex); -- Elaborate the component of the vertex by trying to elaborate as -- many vertices within the component as possible. Each successful -- elaboration signals the appropriate successors and components -- that they have one less predecessor to wait on. Elaborate_Component (G => G, Comp => Component (G, Vertex), All_Elaborable_Vertices => Elaborable_Vertices, All_Waiting_Vertices => Waiting_Vertices, Order => Order, Step => Step); end loop; -- The graph contains an Elaborate_All circularity when at least one -- edge subject to the related pragma appears in a component. if Has_Elaborate_All_Cycle (G) then Status := Order_Has_Elaborate_All_Circularity; -- The graph contains a circularity when at least one vertex failed -- to elaborate. elsif LGV_Sets.Size (Waiting_Vertices) /= 0 then Status := Order_Has_Circularity; -- Otherwise the elaboration order is satisfactory else Status := Order_OK; end if; LGV_Sets.Destroy (Elaborable_Vertices); LGV_Sets.Destroy (Waiting_Vertices); end Elaborate_Library_Graph; --------------------- -- Elaborate_Units -- --------------------- procedure Elaborate_Units (Order : out Unit_Id_Table; Main_Lib_File : File_Name_Type) is pragma Unreferenced (Main_Lib_File); Inv_Graph : Invocation_Graph; Lib_Graph : Library_Graph; Status : Elaboration_Order_Status; begin Start_Phase (Unit_Elaboration); -- Initialize all unit-related data structures and gather all units -- that need elaboration. Initialize_Units; Collect_Elaborable_Units; -- Create the library graph that captures the dependencies between -- library items. Lib_Graph := Build_Library_Graph; -- Create the invocation graph that represents the flow of execution Inv_Graph := Build_Invocation_Graph (Lib_Graph); -- Traverse the invocation graph starting from elaboration code in -- order to discover transitions of the execution flow from a unit -- to a unit that result in extra edges within the library graph. Augment_Library_Graph (Inv_Graph); -- Create the component graph by collapsing all library items into -- library units and traversing the library graph. Find_Components (Lib_Graph); -- Output the contents of the ALI tables and both graphs to standard -- output now that they have been fully decorated. Write_ALI_Tables; Write_Invocation_Graph (Inv_Graph); Write_Library_Graph (Lib_Graph); -- Traverse the library graph to determine the elaboration order of -- units. Elaborate_Library_Graph (Lib_Graph, Order, Status); -- The elaboration order is satisfactory if Status = Order_OK then Validate_Elaboration_Order (Order); -- Set attribute Elab_Position of table ALI.Units for all units in -- the elaboration order. Set_Unit_Elaboration_Positions (Order); -- Output the dependencies among units when switch -e (output -- complete list of elaboration order dependencies) is active. Write_Dependencies (Lib_Graph); -- Output the elaboration order when switch -l (output chosen -- elaboration order) is in effect. Write_Elaboration_Order (Order); -- Output the sources referenced in the closure of the order when -- switch -R (list sources referenced in closure) is in effect. Write_Unit_Closure (Order); -- Otherwise the library graph contains at least one circularity else Diagnose_Circularities (Inv_Graph); end if; Destroy (Inv_Graph); Destroy (Lib_Graph); -- Destroy all unit-related data structures Finalize_Units; End_Phase (Unit_Elaboration); -- Halt the bind when there is no satisfactory elaboration order if Status /= Order_OK then raise Unrecoverable_Error; end if; end Elaborate_Units; ---------------------- -- Elaborate_Vertex -- ---------------------- procedure Elaborate_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step; Indent : Indentation_Level) is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Needs_Elaboration (G, Vertex)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); Trace_Vertex (G => G, Vertex => Vertex, Msg => "elaborating vertex", Step => Step, Indent => Indent); -- Remove the vertex from both elaborable sets. This is needed when -- the vertex is both an overall best candidate among all vertices, -- and the best candidate within the component. LGV_Sets.Delete (All_Elaborable_Vertices, Vertex); LGV_Sets.Delete (Comp_Elaborable_Vertices, Vertex); -- Remove the vertex from both waiting sets. This is needed when a -- weakly elaborable vertex is both an overall best candidate among -- all waiting vertices and the best waiting candidate within the -- component. LGV_Sets.Delete (All_Waiting_Vertices, Vertex); LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex); -- Mark the vertex as elaborated in order to prevent further attempts -- to re-elaborate it. Set_In_Elaboration_Order (G, Vertex); -- Add the unit represented by the vertex to the elaboration order Unit_Id_Tables.Append (Order, Unit (G, Vertex)); -- Notify all successors and their components that they have one -- fewer predecessor to wait on. This may cause some successors to -- be included in one of the sets. Update_Successors (G => G, Vertex => Vertex, All_Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Step => Step, Indent => Indent + Nested_Indentation); -- Elaborate an eligible completing body immediately after its spec. -- This action satisfies the semantics of pragma Elaborate_Body. In -- addition, it ensures that a body will not "drift" too far from its -- spec in case invocation edges are removed from the library graph. if Has_Elaborable_Body (G, Vertex) then Elaborate_Vertex (G => G, Vertex => Proper_Body (G, Vertex), All_Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Order => Order, Step => Step, Indent => Indent); end if; end Elaborate_Vertex; --------------------------------- -- Find_Best_Elaborable_Vertex -- --------------------------------- function Find_Best_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); pragma Assert (LGV_Sets.Present (Set)); return Find_Best_Vertex (G => G, Set => Set, Is_Suitable_Vertex => Is_Suitable_Elaborable_Vertex'Access, Compare_Vertices => Is_Better_Elaborable_Vertex'Access, Initial_Best_Msg => "initial best elaborable vertex", Subsequent_Best_Msg => "better elaborable vertex", Step => Step, Indent => Indent); end Find_Best_Elaborable_Vertex; ---------------------- -- Find_Best_Vertex -- ---------------------- function Find_Best_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Is_Suitable_Vertex : LGV_Predicate_Ptr; Compare_Vertices : LGV_Comparator_Ptr; Initial_Best_Msg : String; Subsequent_Best_Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id is Best_Vertex : Library_Graph_Vertex_Id; Current_Vertex : Library_Graph_Vertex_Id; Iter : LGV_Sets.Iterator; begin pragma Assert (Present (G)); pragma Assert (LGV_Sets.Present (Set)); pragma Assert (Is_Suitable_Vertex /= null); pragma Assert (Compare_Vertices /= null); -- Assume that there is no candidate Best_Vertex := No_Library_Graph_Vertex; -- Inspect all vertices in the set, looking for the best candidate -- according to the comparator. Iter := LGV_Sets.Iterate (Set); while LGV_Sets.Has_Next (Iter) loop LGV_Sets.Next (Iter, Current_Vertex); pragma Assert (Needs_Elaboration (G, Current_Vertex)); if Is_Suitable_Vertex.all (G, Current_Vertex) then -- A previous iteration already picked the best candidate. -- Update the best candidate when the current vertex is a -- better choice. if Present (Best_Vertex) then if Compare_Vertices.all (G => G, Vertex => Current_Vertex, Compared_To => Best_Vertex) = Higher_Precedence then Best_Vertex := Current_Vertex; Trace_Vertex (G => G, Vertex => Best_Vertex, Msg => Subsequent_Best_Msg, Step => Step, Indent => Indent); end if; -- Otherwise this is the first candidate else Best_Vertex := Current_Vertex; Trace_Vertex (G => G, Vertex => Best_Vertex, Msg => Initial_Best_Msg, Step => Step, Indent => Indent); end if; end if; end loop; return Best_Vertex; end Find_Best_Vertex; ---------------------------------------- -- Find_Best_Weakly_Elaborable_Vertex -- ---------------------------------------- function Find_Best_Weakly_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); pragma Assert (LGV_Sets.Present (Set)); return Find_Best_Vertex (G => G, Set => Set, Is_Suitable_Vertex => Is_Suitable_Weakly_Elaborable_Vertex'Access, Compare_Vertices => Is_Better_Weakly_Elaborable_Vertex'Access, Initial_Best_Msg => "initial best weakly elaborable vertex", Subsequent_Best_Msg => "better weakly elaborable vertex", Step => Step, Indent => Indent); end Find_Best_Weakly_Elaborable_Vertex; ------------------------- -- Has_Elaborable_Body -- ------------------------- function Has_Elaborable_Body (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); -- The body of an already-elaborated spec subject to Elaborate_Body -- is always elaborable. if Is_Spec_With_Elaborate_Body (G, Vertex) then return True; elsif Is_Spec_With_Body (G, Vertex) then return Is_Elaborable_Vertex (G, Proper_Body (G, Vertex)); end if; return False; end Has_Elaborable_Body; --------------------------------- -- Insert_Elaborable_Successor -- --------------------------------- procedure Insert_Elaborable_Successor (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (LGV_Sets.Present (Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); Complement : constant Library_Graph_Vertex_Id := Complementary_Vertex (G => G, Vertex => Vertex, Force_Complement => False); begin -- Remove the successor from both waiting vertex sets because it may -- be the best vertex to elaborate across the whole graph and within -- its component. LGV_Sets.Delete (All_Waiting_Vertices, Vertex); LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex); Insert_Vertex (G => G, Vertex => Vertex, Set => Elaborable_Vertices, Msg => Msg, Step => Step, Indent => Indent); if Present (Complement) then -- Remove the complement of the successor from both waiting vertex -- sets because it may be the best vertex to elaborate across the -- whole graph and within its component. LGV_Sets.Delete (All_Waiting_Vertices, Complement); LGV_Sets.Delete (Comp_Waiting_Vertices, Complement); Insert_Vertex (G => G, Vertex => Complement, Set => Elaborable_Vertices, Msg => Msg, Step => Step, Indent => Indent); end if; end Insert_Elaborable_Successor; ------------------- -- Insert_Vertex -- ------------------- procedure Insert_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Needs_Elaboration (G, Vertex)); pragma Assert (LGV_Sets.Present (Set)); -- Nothing to do when the vertex is already present in the set if LGV_Sets.Contains (Set, Vertex) then return; end if; Trace_Vertex (G => G, Vertex => Vertex, Msg => Msg, Step => Step, Indent => Indent); -- Add the vertex to the set LGV_Sets.Insert (Set, Vertex); end Insert_Vertex; --------------------------------- -- Is_Better_Elaborable_Vertex -- --------------------------------- function Is_Better_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Present (Compared_To)); -- Prefer a spec with Elaborate_Body over its corresponding body if Is_Elaborate_Body_Pair (G => G, Spec_Vertex => Vertex, Body_Vertex => Compared_To) then return Higher_Precedence; elsif Is_Elaborate_Body_Pair (G => G, Spec_Vertex => Compared_To, Body_Vertex => Vertex) then return Lower_Precedence; -- Prefer a predefined unit over a non-predefined unit elsif Is_Predefined_Unit (G, Vertex) and then not Is_Predefined_Unit (G, Compared_To) then return Higher_Precedence; elsif not Is_Predefined_Unit (G, Vertex) and then Is_Predefined_Unit (G, Compared_To) then return Lower_Precedence; -- Prefer an internal unit over a non-internal unit elsif Is_Internal_Unit (G, Vertex) and then not Is_Internal_Unit (G, Compared_To) then return Higher_Precedence; elsif not Is_Internal_Unit (G, Vertex) and then Is_Internal_Unit (G, Compared_To) then return Lower_Precedence; -- Prefer a preelaborated unit over a non-preelaborated unit elsif Is_Preelaborated_Unit (G, Vertex) and then not Is_Preelaborated_Unit (G, Compared_To) then return Higher_Precedence; elsif not Is_Preelaborated_Unit (G, Vertex) and then Is_Preelaborated_Unit (G, Compared_To) then return Lower_Precedence; -- Otherwise default to lexicographical order to ensure deterministic -- behavior. elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then return Higher_Precedence; else return Lower_Precedence; end if; end Is_Better_Elaborable_Vertex; ---------------------------------------- -- Is_Better_Weakly_Elaborable_Vertex -- ---------------------------------------- function Is_Better_Weakly_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind is Comp_Strong_Preds : Natural; Comp_Weak_Preds : Natural; Vertex_Strong_Preds : Natural; Vertex_Weak_Preds : Natural; begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Present (Compared_To)); -- Obtain the number of pending predecessors for both candidates, -- taking into account Elaborate_Body pairs. Pending_Predecessors_For_Elaboration (G => G, Vertex => Vertex, Strong_Preds => Vertex_Strong_Preds, Weak_Preds => Vertex_Weak_Preds); Pending_Predecessors_For_Elaboration (G => G, Vertex => Compared_To, Strong_Preds => Comp_Strong_Preds, Weak_Preds => Comp_Weak_Preds); -- Neither candidate should be waiting on strong predecessors, -- otherwise the candidate cannot be weakly elaborated. pragma Assert (Vertex_Strong_Preds = 0); pragma Assert (Comp_Strong_Preds = 0); -- Prefer a unit with fewer weak predecessors over a unit with more -- weak predecessors. if Vertex_Weak_Preds < Comp_Weak_Preds then return Higher_Precedence; elsif Vertex_Weak_Preds > Comp_Weak_Preds then return Lower_Precedence; -- Otherwise default to lexicographical order to ensure deterministic -- behavior. elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then return Higher_Precedence; else return Lower_Precedence; end if; end Is_Better_Weakly_Elaborable_Vertex; ----------------------------------- -- Is_Suitable_Elaborable_Vertex -- ----------------------------------- function Is_Suitable_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); -- A vertex is suitable for elaboration as long it is not waiting on -- any predecessors, ignoring the static or dynamic model. return Is_Elaborable_Vertex (G, Vertex); end Is_Suitable_Elaborable_Vertex; ------------------------------------------ -- Is_Suitable_Weakly_Elaborable_Vertex -- ------------------------------------------ function Is_Suitable_Weakly_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); -- A vertex is suitable for weak elaboration when it is waiting on -- weak predecessors only, and the unit it represents was compiled -- using the dynamic model. return Is_Dynamically_Elaborated (G, Vertex) and then Is_Weakly_Elaborable_Vertex (G, Vertex); end Is_Suitable_Weakly_Elaborable_Vertex; ------------------------------------ -- Set_Unit_Elaboration_Positions -- ------------------------------------ procedure Set_Unit_Elaboration_Positions (Order : Unit_Id_Table) is U_Id : Unit_Id; begin for Position in Unit_Id_Tables.First .. Unit_Id_Tables.Last (Order) loop U_Id := Order.Table (Position); ALI.Units.Table (U_Id).Elab_Position := Position; end loop; end Set_Unit_Elaboration_Positions; --------------------- -- Trace_Component -- --------------------- procedure Trace_Component (G : Library_Graph; Comp : Component_Id; Msg : String; Step : Elaboration_Order_Step) is begin pragma Assert (Present (G)); pragma Assert (Present (Comp)); -- Nothing to do when switch -d_T (output elaboration order and cycle -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; end if; Trace_Step (Step); Write_Str (Msg); Write_Str (" (Comp_Id_"); Write_Int (Int (Comp)); Write_Str (")"); Write_Eol; Trace_Step (Step); Indent_By (Nested_Indentation); Write_Str ("pending strong predecessors: "); Write_Num (Int (Pending_Strong_Predecessors (G, Comp))); Write_Eol; Trace_Step (Step); Indent_By (Nested_Indentation); Write_Str ("pending weak predecessors : "); Write_Num (Int (Pending_Weak_Predecessors (G, Comp))); Write_Eol; end Trace_Component; ---------------- -- Trace_Step -- ---------------- procedure Trace_Step (Step : Elaboration_Order_Step) is begin -- Nothing to do when switch -d_T (output elaboration order and cycle -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; end if; Write_Num (Val => Int (Step), Val_Indent => Step_Column); Write_Str (": "); end Trace_Step; ------------------ -- Trace_Vertex -- ------------------ procedure Trace_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is pragma Assert (Present (G)); pragma Assert (Present (Vertex)); Attr_Indent : constant Indentation_Level := Indent + Nested_Indentation; Comp : constant Component_Id := Component (G, Vertex); begin -- Nothing to do when switch -d_T (output elaboration order and cycle -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; end if; Trace_Step (Step); Indent_By (Indent); Write_Str (Msg); Write_Str (" (LGV_Id_"); Write_Int (Int (Vertex)); Write_Str (")"); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("name = "); Write_Name (Name (G, Vertex)); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("Component (Comp_Id_"); Write_Int (Int (Comp)); Write_Str (")"); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("pending strong predecessors: "); Write_Num (Int (Pending_Strong_Predecessors (G, Vertex))); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("pending weak predecessors : "); Write_Num (Int (Pending_Weak_Predecessors (G, Vertex))); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("pending strong components : "); Write_Num (Int (Pending_Strong_Predecessors (G, Comp))); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); Write_Str ("pending weak components : "); Write_Num (Int (Pending_Weak_Predecessors (G, Comp))); Write_Eol; end Trace_Vertex; -------------------- -- Trace_Vertices -- -------------------- procedure Trace_Vertices (G : Library_Graph; Set : LGV_Sets.Membership_Set; Set_Msg : String; Vertex_Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is Vertex_Indent : constant Indentation_Level := Indent + Nested_Indentation; Iter : LGV_Sets.Iterator; Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); pragma Assert (LGV_Sets.Present (Set)); -- Nothing to do when switch -d_T (output elaboration order and cycle -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; end if; Trace_Step (Step); Indent_By (Indent); Write_Str (Set_Msg); Write_Str (": "); Write_Int (Int (LGV_Sets.Size (Set))); Write_Eol; Iter := LGV_Sets.Iterate (Set); while LGV_Sets.Has_Next (Iter) loop LGV_Sets.Next (Iter, Vertex); Trace_Vertex (G => G, Vertex => Vertex, Msg => Vertex_Msg, Step => Step, Indent => Vertex_Indent); end loop; end Trace_Vertices; ---------------------- -- Update_Successor -- ---------------------- procedure Update_Successor (G : Library_Graph; Edge : Library_Graph_Edge_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) is pragma Assert (Present (G)); pragma Assert (Present (Edge)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); pragma Assert (Needs_Elaboration (G, Pred)); pragma Assert (Needs_Elaboration (G, Succ)); In_Different_Components : constant Boolean := not In_Same_Component (G => G, Left => Pred, Right => Succ); Succ_Comp : constant Component_Id := Component (G, Succ); Vertex_Indent : constant Indentation_Level := Indent + Nested_Indentation; Iter : Component_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id; begin Trace_Vertex (G => G, Vertex => Succ, Msg => "updating successor", Step => Step, Indent => Indent); -- Notify the successor that it has one less predecessor to wait on. -- This effectively eliminates the edge that links the two. Decrement_Pending_Predecessors (G => G, Vertex => Succ, Edge => Edge); -- The predecessor and successor reside in different components. -- Notify the successor component it has one fewer components to -- wait on. if In_Different_Components then Decrement_Pending_Predecessors (G => G, Comp => Succ_Comp, Edge => Edge); end if; -- At this point the successor may become elaborable when its final -- predecessor or final predecessor component has been elaborated. if Is_Elaborable_Vertex (G, Succ) then -- The predecessor and successor reside in different components. -- The successor must not be added to the candidates of Pred's -- component because this will mix units from the two components. -- Instead, the successor is added to the set of all elaborable -- vertices. if In_Different_Components then Insert_Elaborable_Successor (G => G, Vertex => Succ, Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Msg => "add elaborable successor", Step => Step, Indent => Vertex_Indent); -- Otherwise the predecessor and successor reside within the same -- component. Pred's component gains another elaborable vertex. else Insert_Elaborable_Successor (G => G, Vertex => Succ, Elaborable_Vertices => Comp_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Msg => "add elaborable component successor", Step => Step, Indent => Vertex_Indent); end if; end if; -- At this point the successor component may become elaborable when -- its final predecessor component is elaborated. This in turn may -- allow vertices of the successor component to be elaborated. if In_Different_Components and then Is_Elaborable_Component (G, Succ_Comp) then Iter := Iterate_Component_Vertices (G, Succ_Comp); while Has_Next (Iter) loop Next (Iter, Vertex); if Is_Elaborable_Vertex (G, Vertex) then Insert_Elaborable_Successor (G => G, Vertex => Vertex, Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Msg => "add elaborable vertex", Step => Step, Indent => Vertex_Indent); end if; end loop; end if; end Update_Successor; ----------------------- -- Update_Successors -- ----------------------- procedure Update_Successors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) is Edge : Library_Graph_Edge_Id; Iter : Edges_To_Successors_Iterator; begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Needs_Elaboration (G, Vertex)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); Iter := Iterate_Edges_To_Successors (G, Vertex); while Has_Next (Iter) loop Next (Iter, Edge); pragma Assert (Predecessor (G, Edge) = Vertex); Update_Successor (G => G, Edge => Edge, All_Elaborable_Vertices => All_Elaborable_Vertices, All_Waiting_Vertices => All_Waiting_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, Comp_Waiting_Vertices => Comp_Waiting_Vertices, Step => Step, Indent => Indent); end loop; end Update_Successors; end Invocation_And_Library_Graph_Elaborators; end Bindo.Elaborators;