with Bindo.Validators;
use Bindo.Validators;
use Bindo.Validators.Elaboration_Order_Validators;
-use Bindo.Validators.Invocation_Graph_Validators;
-use Bindo.Validators.Library_Graph_Validators;
with Bindo.Writers;
use Bindo.Writers;
----------------------------------------------
package body Invocation_And_Library_Graph_Elaborators is
- Add_To_All_Candidates_Msg : aliased String :=
- "add vertex to all candidates";
- Add_To_Comp_Candidates_Msg : aliased String :=
- "add vertex to component candidates";
-
- -----------
- -- Types --
- -----------
-
- type String_Ptr is access all String;
-----------------------
-- Local subprograms --
-----------------------
- procedure Add_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 (Add_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.
-
- procedure Add_Vertex_If_Elaborable
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Set : LGV_Sets.Membership_Set;
- Msg : String;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level);
- pragma Inline (Add_Vertex_If_Elaborable);
- -- Add vertex Vertex of library graph G to membership set Set if it can
- -- be elaborated. 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 Create_All_Candidates_Set
- (G : Library_Graph;
- Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set;
- pragma Inline (Create_All_Candidates_Set);
- -- Collect all elaborable candidate vertices of library graph G in a
- -- set. Step is the current step in the elaboration order.
-
- function Create_Component_Candidates_Set
- (G : Library_Graph;
- Comp : Component_Id;
- Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set;
- pragma Inline (Create_Component_Candidates_Set);
- -- Collect all elaborable candidate vertices that appear in component
- -- Comp of library graph G in a set. Step is the current step in the
- -- elaboration order.
+ 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_Candidates : LGV_Sets.Membership_Set;
- Remaining_Vertices : in out Natural;
- Order : in out Unit_Id_Table;
- Step : Elaboration_Order_Step);
+ (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. All_Candidates is the set of all elaborable
- -- vertices across the whole library graph. Remaining_Vertices is the
- -- number of vertices that remain to be elaborated. Order denotes the
- -- elaboration order. Step is the current step in the elaboration order.
+ -- 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;
-- the elaboration order. Status is the condition of the elaboration
-- order.
- procedure Elaborate_Units_Common
- (Use_Inv_Graph : Boolean;
- Is_Dyn_Elab : Boolean;
- Inv_Graph : out Invocation_Graph;
- Lib_Graph : out Library_Graph;
- Order : out Unit_Id_Table;
- Status : out Elaboration_Order_Status);
- pragma Inline (Elaborate_Units_Common);
- -- Find the elaboration order of all units in the bind. Use_Inv_Graph
- -- should be set when library graph Lib_Graph is to be augmented with
- -- information from invocation graph Inv_Graph. Is_Dyn_Elab should be
- -- set when the main library unit was compiled using the dynamic model.
- -- Order is the elaboration order. Status is the condition of the
- -- elaboration order.
-
- procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table);
- pragma Inline (Elaborate_Units_Dynamic);
- -- Find the elaboration order of all units in the bind using the dynamic
- -- model. Order is the elaboration order. In the event where no ordering
- -- is possible, this routine diagnoses the issue(s) and raises exception
- -- Unrecoverable_Error.
-
- procedure Elaborate_Units_Static (Order : out Unit_Id_Table);
- pragma Inline (Elaborate_Units_Static);
- -- Find the elaboration order of all units in the bind using the static
- -- model. Order is the elaboration order. In the event where no ordering
- -- is possible, this routine diagnoses the issue(s) and raises exception
- -- Unrecoverable_Error.
-
procedure Elaborate_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Remaining_Vertices : in out Natural;
- Order : in out Unit_Id_Table;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level);
+ (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. All_Candidates denotes the set of all elaborable
- -- vertices across the whole library graph. Comp_Candidates is the set
- -- of all elaborable vertices in the component of Vertex. Parameter
- -- Remaining_Vertices denotes the number of vertices that remain to
- -- be elaborated. Step is the current step in the elaboration order.
+ -- 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_Candidate
+ type Comparator_Ptr is access function
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id;
+ Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind;
+
+ type Predicate_Ptr is access function
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id) return Boolean;
+
+ function Find_Best_Vertex
+ (G : Library_Graph;
+ Set : LGV_Sets.Membership_Set;
+ Is_Suitable_Vertex : Predicate_Ptr;
+ Compare_Vertices : 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_Candidate);
- -- Find the most suitable vertex of library graph G for elaboration from
- -- membership set Set. Step denotes the current step in the elaboration
+ 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 Is_Better_Candidate
- (G : Library_Graph;
- Best_Candidate : Library_Graph_Vertex_Id;
- New_Candidate : Library_Graph_Vertex_Id) return Boolean;
- pragma Inline (Is_Better_Candidate);
- -- Determine whether new candidate vertex New_Candidate of library graph
- -- G is a more suitable choice for elaboration compared to the current
- -- best candidate Best_Candidate.
+ 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.
- procedure Trace_Candidate_Vertices
- (G : Library_Graph;
- Set : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step);
- pragma Inline (Trace_Candidate_Vertices);
- -- Write the candidate vertices of library graph G present in membership
- -- set Set to standard output. Formal Step denotes the current step in
- -- the elaboration order.
+ 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 Trace_Component
(G : Library_Graph;
pragma Inline (Trace_Step);
-- Write current step Step of the elaboration order to standard output
- procedure Trace_Unelaborated_Vertices
- (G : Library_Graph;
- Count : Natural;
- Step : Elaboration_Order_Step);
- pragma Inline (Trace_Unelaborated_Vertices);
- -- Write the remaining unelaborated vertices of library graph G to
- -- standard output. Count is the number of vertices that remain to
- -- be elaborated. Step is the current step in the elaboration order.
-
procedure Trace_Vertex
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id;
-- 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;
- Pred : Library_Graph_Vertex_Id;
- Succ : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level);
+ (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 successor vertex Succ of library graph G along with its
- -- component that their predecessor Pred has just been elaborated.
- -- This may cause new vertices to become elaborable, and thus be added
- -- to one of the two sets. All_Candidates is the set of all elaborable
- -- vertices across the whole library graph. Comp_Candidates is the set
- -- of all elaborable vertices in the component of Pred. Step is the
- -- current step in the elaboration order. Indent denotes the desired
- -- indentation level for tracing.
+ -- 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;
- Pred : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level);
+ (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 along with their components that their
- -- predecessor vertex Pred of ligrary graph G has just been elaborated.
- -- This may cause new vertices to become elaborable, and thus be added
- -- to one of the two sets. All_Candidates is the set of all elaborable
- -- vertices across the whole library graph. Comp_Candidates is the set
- -- of all elaborable vertices in the component of Pred. Step is the
- -- current step in the elaboration order. Indent denotes the desired
- -- indentation level for tracing.
-
- ----------------
- -- Add_Vertex --
- ----------------
-
- procedure Add_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Set : LGV_Sets.Membership_Set;
- Msg : String;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level)
+ -- 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
- begin
- pragma Assert (Present (Vertex));
- pragma Assert (Needs_Elaboration (G, Vertex));
- pragma Assert (LGV_Sets.Present (Set));
-
- -- Add vertex only when it is not present in the set. This is not
- -- strictly necessary because the set implementation handles this
- -- case, however the check eliminates spurious traces.
-
- if not LGV_Sets.Contains (Set, Vertex) then
- Trace_Vertex
- (G => G,
- Vertex => Vertex,
- Msg => Msg,
- Step => Step,
- Indent => Indent);
-
- LGV_Sets.Insert (Set, Vertex);
- end if;
- end Add_Vertex;
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
- ------------------------------
- -- Add_Vertex_If_Elaborable --
- ------------------------------
+ Num_Of_Vertices : constant Natural :=
+ Number_Of_Component_Vertices (G, Comp);
- procedure Add_Vertex_If_Elaborable
- (G : Library_Graph;
+ Iter : Component_Vertex_Iterator;
Vertex : Library_Graph_Vertex_Id;
- Set : LGV_Sets.Membership_Set;
- Msg : String;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level)
- is
- Extra_Vertex : Library_Graph_Vertex_Id;
begin
- pragma Assert (Present (G));
- pragma Assert (Present (Vertex));
- pragma Assert (Needs_Elaboration (G, Vertex));
- pragma Assert (LGV_Sets.Present (Set));
-
- if Is_Elaborable_Vertex (G, Vertex) then
- Add_Vertex
- (G => G,
- Vertex => Vertex,
- Set => Set,
- Msg => Msg,
- Step => Step,
- Indent => Indent);
-
- -- Assume that there is no extra vertex that needs to be added
+ Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices);
+ Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices);
- Extra_Vertex := No_Library_Graph_Vertex;
-
- -- A spec-body pair where the spec carries pragma Elaborate_Body
- -- must be treated as one vertex for elaboration purposes. If one
- -- of them is elaborable, then the other is also elaborable. This
- -- property is guaranteed by predicate Is_Elaborable_Vertex.
-
- if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then
- Extra_Vertex := Proper_Spec (G, Vertex);
- pragma Assert (Present (Extra_Vertex));
+ Iter := Iterate_Component_Vertices (G, Comp);
+ while Has_Next (Iter) loop
+ Next (Iter, Vertex);
- elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
- Extra_Vertex := Proper_Body (G, Vertex);
- pragma Assert (Present (Extra_Vertex));
- end if;
+ -- Add the vertex to the proper set depending on whether it can be
+ -- elaborated.
- if Present (Extra_Vertex) then
- pragma Assert (Needs_Elaboration (G, Extra_Vertex));
+ 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);
- Add_Vertex
+ else
+ Insert_Vertex
(G => G,
- Vertex => Extra_Vertex,
- Set => Set,
- Msg => Msg,
+ Vertex => Vertex,
+ Set => Waiting_Vertices,
+ Msg => "add waiting component vertex",
Step => Step,
- Indent => Indent);
+ Indent => No_Indentation);
end if;
- end if;
- end Add_Vertex_If_Elaborable;
+ end loop;
+ end Create_Component_Vertex_Sets;
- -------------------------------
- -- Create_All_Candidates_Set --
- -------------------------------
+ ------------------------
+ -- Create_Vertex_Sets --
+ ------------------------
- function Create_All_Candidates_Set
- (G : Library_Graph;
- Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set
+ 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;
- Set : LGV_Sets.Membership_Set;
Vertex : Library_Graph_Vertex_Id;
begin
- pragma Assert (Present (G));
+ Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices);
+ Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices);
- Set := LGV_Sets.Create (Number_Of_Vertices (G));
Iter := Iterate_All_Vertices (G);
while Has_Next (Iter) loop
Next (Iter, Vertex);
- Add_Vertex_If_Elaborable
- (G => G,
- Vertex => Vertex,
- Set => Set,
- Msg => Add_To_All_Candidates_Msg,
- Step => Step,
- Indent => No_Indentation);
- end loop;
-
- return Set;
- end Create_All_Candidates_Set;
-
- -------------------------------------
- -- Create_Component_Candidates_Set --
- -------------------------------------
-
- function Create_Component_Candidates_Set
- (G : Library_Graph;
- Comp : Component_Id;
- Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set
- is
- Iter : Component_Vertex_Iterator;
- Set : LGV_Sets.Membership_Set;
- Vertex : Library_Graph_Vertex_Id;
-
- begin
- pragma Assert (Present (G));
- pragma Assert (Present (Comp));
+ -- Add the vertex to the proper set depending on whether it can be
+ -- elaborated.
- Set := LGV_Sets.Create (Number_Of_Component_Vertices (G, Comp));
- Iter := Iterate_Component_Vertices (G, Comp);
- while Has_Next (Iter) loop
- Next (Iter, Vertex);
+ 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);
- Add_Vertex_If_Elaborable
- (G => G,
- Vertex => Vertex,
- Set => Set,
- Msg => Add_To_Comp_Candidates_Msg,
- 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;
-
- return Set;
- end Create_Component_Candidates_Set;
+ end Create_Vertex_Sets;
-------------------------
-- Elaborate_Component --
-------------------------
procedure Elaborate_Component
- (G : Library_Graph;
- Comp : Component_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Remaining_Vertices : in out Natural;
- Order : in out Unit_Id_Table;
- Step : Elaboration_Order_Step)
+ (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
- Candidate : Library_Graph_Vertex_Id;
- Comp_Candidates : LGV_Sets.Membership_Set;
+ 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_Candidates));
+ pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
+ pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
Trace_Component
(G => G,
Msg => "elaborating component",
Step => Step);
- Comp_Candidates := Create_Component_Candidates_Set (G, Comp, 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
- Candidate :=
- Find_Best_Candidate
+ 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_Candidates,
+ Set => Comp_Elaborable_Vertices,
Step => Step,
Indent => Nested_Indentation);
- -- Stop the elaboration of the component when there is no suitable
- -- candidate. This indicates that either all vertices within the
- -- component have been elaborated, or the library graph contains a
- -- circularity.
+ -- 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);
- exit when not Present (Candidate);
+ -- 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 => Candidate,
- All_Candidates => All_Candidates,
- Comp_Candidates => Comp_Candidates,
- Remaining_Vertices => Remaining_Vertices,
- Order => Order,
- Step => Step,
- Indent => Nested_Indentation);
+ (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_Candidates);
+ LGV_Sets.Destroy (Comp_Elaborable_Vertices);
+ LGV_Sets.Destroy (Comp_Waiting_Vertices);
end Elaborate_Component;
-----------------------------
Order : out Unit_Id_Table;
Status : out Elaboration_Order_Status)
is
- All_Candidates : LGV_Sets.Membership_Set;
- Candidate : Library_Graph_Vertex_Id;
- Remaining_Vertices : Natural;
- Step : Elaboration_Order_Step;
+ 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;
- All_Candidates := Create_All_Candidates_Set (G, Step);
- Remaining_Vertices := Number_Of_Vertices (G);
+ -- 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_Candidate_Vertices
- (G => G,
- Set => All_Candidates,
- Step => Step);
-
- Trace_Unelaborated_Vertices
- (G => G,
- Count => Remaining_Vertices,
- Step => Step);
-
- Candidate :=
- Find_Best_Candidate
+ 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 => All_Candidates,
+ Set => Elaborable_Vertices,
Step => Step,
Indent => No_Indentation);
- -- Stop the elaboration when there is no suitable candidate. This
- -- indicates that either all units were elaborated or the library
- -- graph contains a circularity.
+ -- 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 (Candidate);
+ exit when not Present (Vertex);
- -- Elaborate the component of the candidate vertex by trying to
- -- elaborate as many vertices within the component as possible.
- -- Each successful elaboration signals the appropriate successors
- -- and their components that they have one less predecessor to
- -- wait on. This may add new candidates to set All_Candidates.
+ -- 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, Candidate),
- All_Candidates => All_Candidates,
- Remaining_Vertices => Remaining_Vertices,
- Order => Order,
- Step => Step);
+ (G => G,
+ Comp => Component (G, Vertex),
+ All_Elaborable_Vertices => Elaborable_Vertices,
+ All_Waiting_Vertices => Waiting_Vertices,
+ Order => Order,
+ Step => Step);
end loop;
- LGV_Sets.Destroy (All_Candidates);
-
- -- The library graph contains an Elaborate_All circularity when
- -- at least one edge subject to the related pragma appears in a
- -- component.
+ -- 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 library contains a circularity when at least one vertex failed
+ -- The graph contains a circularity when at least one vertex failed
-- to elaborate.
- elsif Remaining_Vertices /= 0 then
+ 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;
---------------------
(Order : out Unit_Id_Table;
Main_Lib_File : File_Name_Type)
is
- Main_Lib_Unit : constant Unit_Id :=
- Corresponding_Unit (Unit_Name_Type (Main_Lib_File));
+ pragma Unreferenced (Main_Lib_File);
- begin
- pragma Assert (Present (Main_Lib_Unit));
+ Inv_Graph : Invocation_Graph;
+ Lib_Graph : Library_Graph;
+ Status : Elaboration_Order_Status;
+ begin
-- Initialize all unit-related data structures and gather all units
-- that need elaboration.
Initialize_Units;
Collect_Elaborable_Units;
- Write_ALI_Tables;
-
- -- Choose the proper elaboration strategy based on whether the main
- -- library unit was compiled using the dynamic model.
-
- if Is_Dynamically_Elaborated (Main_Lib_Unit) then
- Elaborate_Units_Dynamic (Order);
- else
- Elaborate_Units_Static (Order);
- end if;
-
- Validate_Elaboration_Order (Order);
- Write_Elaboration_Order (Order);
-
- -- Enumerate the sources referenced in the closure of the order
-
- Write_Unit_Closure (Order);
-
- -- Destroy all unit-delated data structures
-
- Finalize_Units;
-
- exception
- when others =>
- Finalize_Units;
- raise;
- end Elaborate_Units;
-
- ----------------------------
- -- Elaborate_Units_Common --
- ----------------------------
-
- procedure Elaborate_Units_Common
- (Use_Inv_Graph : Boolean;
- Is_Dyn_Elab : Boolean;
- Inv_Graph : out Invocation_Graph;
- Lib_Graph : out Library_Graph;
- Order : out Unit_Id_Table;
- Status : out Elaboration_Order_Status)
- is
- begin
- -- Create, validate, and output the library graph that captures the
- -- dependencies between library items.
-
- Lib_Graph := Build_Library_Graph (Is_Dyn_Elab);
- Validate_Library_Graph (Lib_Graph);
- Write_Library_Graph (Lib_Graph);
-
- -- Create, validate, output, and use the invocation graph that
- -- represents the flow of execusion only when requested by the
- -- caller.
+ -- Create the library graph that captures the dependencies between
+ -- library items.
- if Use_Inv_Graph then
- Inv_Graph := Build_Invocation_Graph (Lib_Graph);
- Validate_Invocation_Graph (Inv_Graph);
- Write_Invocation_Graph (Inv_Graph);
+ Lib_Graph := Build_Library_Graph;
- -- Otherwise the invocation graph is not used. Create a dummy graph
- -- as this allows for a uniform behavior on the caller side.
+ -- Create the invocation graph that represents the flow of execution
- else
- Inv_Graph :=
- Invocation_Graphs.Create
- (Initial_Vertices => 1,
- Initial_Edges => 1);
- end if;
+ 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, Lib_Graph);
- Write_Library_Graph (Lib_Graph);
- -- Create and output the component graph by collapsing all library
- -- items into library units and traversing the library graph.
+ -- Create the component graph by collapsing all library items into
+ -- library units and traversing the library graph.
- Find_Components (Lib_Graph);
- Write_Components (Lib_Graph);
+ Find_Components (Lib_Graph);
- -- Traverse the library graph to determine the elaboration order of
- -- units.
+ -- Output the contents of the ALI tables and both graphs to standard
+ -- output now that they have been fully decorated.
- Elaborate_Library_Graph
- (G => Lib_Graph,
- Order => Order,
- Status => Status);
- end Elaborate_Units_Common;
-
- -----------------------------
- -- Elaborate_Units_Dynamic --
- -----------------------------
+ Write_ALI_Tables;
+ Write_Invocation_Graph (Inv_Graph);
+ Write_Library_Graph (Lib_Graph);
- procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table) is
- Dyn_Inv_Graph : Invocation_Graph;
- Dyn_Lib_Graph : Library_Graph;
- Dyn_Order : Unit_Id_Table;
- Mix_Inv_Graph : Invocation_Graph;
- Mix_Lib_Graph : Library_Graph;
- Mix_Order : Unit_Id_Table;
- Status : Elaboration_Order_Status;
+ -- Traverse the library graph to determine the elaboration order of
+ -- units.
- begin
- -- Attempt to elaborate the units in the library graph by mixing in
- -- the information from the invocation graph. This assumes that all
- -- invocations will take place at elaboration time.
-
- Elaborate_Units_Common
- (Use_Inv_Graph => True,
- Is_Dyn_Elab => True,
- Inv_Graph => Mix_Inv_Graph,
- Lib_Graph => Mix_Lib_Graph,
- Order => Mix_Order,
- Status => Status);
+ Elaborate_Library_Graph (Lib_Graph, Order, Status);
-- The elaboration order is satisfactory
if Status = Order_OK then
- Order := Mix_Order;
+ Validate_Elaboration_Order (Order);
- -- Output the dependencies of vertices when switch -e (output
+ -- Output the dependencies among units when switch -e (output
-- complete list of elaboration order dependencies) is active.
- Write_Dependencies (Mix_Lib_Graph);
-
- -- The library graph contains an Elaborate_All circularity. There is
- -- no point in re-elaborating the units without the information from
- -- the invocation graph because the circularity will persist.
-
- elsif Status = Order_Has_Elaborate_All_Circularity then
- Diagnose_Circularities
- (Inv_Graph => Mix_Inv_Graph,
- Lib_Graph => Mix_Lib_Graph);
-
- -- Otherwise the library graph contains a circularity, or the extra
- -- information provided by the invocation graph caused a circularity.
- -- Re-elaborate the units without using the invocation graph. This
- -- assumes that all invocations will not take place at elaboration
- -- time.
-
- else
- pragma Assert (Status = Order_Has_Circularity);
-
- Elaborate_Units_Common
- (Use_Inv_Graph => False,
- Is_Dyn_Elab => True,
- Inv_Graph => Dyn_Inv_Graph,
- Lib_Graph => Dyn_Lib_Graph,
- Order => Dyn_Order,
- Status => Status);
-
- -- The elaboration order is satisfactory. The elaboration of the
- -- program may still fail at runtime with an ABE.
-
- if Status = Order_OK then
- Order := Dyn_Order;
-
- -- Output the dependencies of vertices when switch -e (output
- -- complete list of elaboration order dependencies) is active.
-
- Write_Dependencies (Dyn_Lib_Graph);
-
- -- Otherwise the library graph contains a circularity without the
- -- extra information provided by the invocation graph. Diagnose
- -- the circularity.
-
- else
- Diagnose_Circularities
- (Inv_Graph => Dyn_Inv_Graph,
- Lib_Graph => Dyn_Lib_Graph);
- end if;
-
- Destroy (Dyn_Inv_Graph);
- Destroy (Dyn_Lib_Graph);
- end if;
-
- Destroy (Mix_Inv_Graph);
- Destroy (Mix_Lib_Graph);
-
- -- Halt the bind as there is no satisfactory elaboration order
-
- if Status /= Order_OK then
- raise Unrecoverable_Error;
- end if;
- end Elaborate_Units_Dynamic;
+ Write_Dependencies (Lib_Graph);
- ----------------------------
- -- Elaborate_Units_Static --
- ----------------------------
+ -- Output the elaboration order when switch -l (output chosen
+ -- elaboration order) is in effect.
- procedure Elaborate_Units_Static (Order : out Unit_Id_Table) is
- Inv_Graph : Invocation_Graph;
- Lib_Graph : Library_Graph;
- Status : Elaboration_Order_Status;
+ Write_Elaboration_Order (Order);
- begin
- -- Attempt to elaborate the units in the library graph by mixing in
- -- the information from the invocation graph. This assumes that all
- -- invocations will take place at elaboration time.
-
- Elaborate_Units_Common
- (Use_Inv_Graph => True,
- Is_Dyn_Elab => False,
- Inv_Graph => Inv_Graph,
- Lib_Graph => Lib_Graph,
- Order => Order,
- Status => Status);
-
- -- The elaboration order is satisfactory. Output the dependencies of
- -- vertices when switch -e (output complete list of elaboration order
- -- dependencies) is active.
+ -- Output the sources referenced in the closure of the order when
+ -- switch -R (list sources referenced in closure) is in effect.
- if Status = Order_OK then
- Write_Dependencies (Lib_Graph);
+ Write_Unit_Closure (Order);
- -- Otherwise the augmented library graph contains a circularity
+ -- Otherwise the library graph contains at least one circularity
else
- Diagnose_Circularities
- (Inv_Graph => Inv_Graph,
- Lib_Graph => Lib_Graph);
+ Diagnose_Circularities (Inv_Graph, Lib_Graph);
end if;
Destroy (Inv_Graph);
Destroy (Lib_Graph);
- -- Halt the bind as there is no satisfactory elaboration order
+ -- Destroy all unit-related data structures
+
+ Finalize_Units;
+
+ -- Halt the bind when there is no satisfactory elaboration order
if Status /= Order_OK then
raise Unrecoverable_Error;
end if;
- end Elaborate_Units_Static;
+ end Elaborate_Units;
----------------------
-- Elaborate_Vertex --
----------------------
procedure Elaborate_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Remaining_Vertices : in out Natural;
- Order : in out Unit_Id_Table;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level)
+ (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_Candidates));
- pragma Assert (LGV_Sets.Present (Comp_Candidates));
+ 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,
Step => Step,
Indent => Indent);
- -- Remove the vertex from both candidate sets. This is needed when
+ -- 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. There is no need to
- -- check that the vertex is present in either set because the set
- -- implementation handles this case.
+ -- and the best candidate within the component.
+
+ LGV_Sets.Delete (All_Elaborable_Vertices, Vertex);
+ LGV_Sets.Delete (Comp_Elaborable_Vertices, Vertex);
- LGV_Sets.Delete (All_Candidates, Vertex);
- LGV_Sets.Delete (Comp_Candidates, 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.
Unit_Id_Tables.Append (Order, Unit (G, Vertex));
- -- There is now one fewer vertex to elaborate
-
- Remaining_Vertices := Remaining_Vertices - 1;
-
-- 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,
- Pred => Vertex,
- All_Candidates => All_Candidates,
- Comp_Candidates => Comp_Candidates,
- Step => Step,
- Indent => Indent + Nested_Indentation);
-
- -- The vertex denotes a spec with a completing body, and is subject
- -- to pragma Elaborate_Body. Elaborate the body in order to satisfy
- -- the semantics of the pragma.
-
- if Is_Spec_With_Elaborate_Body (G, Vertex) then
+ (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_Candidates => All_Candidates,
- Comp_Candidates => Comp_Candidates,
- Remaining_Vertices => Remaining_Vertices,
- Order => Order,
- Step => Step,
- Indent => Indent);
+ (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_Candidate --
- -------------------------
+ ---------------------------------
+ -- Find_Best_Elaborable_Vertex --
+ ---------------------------------
- function Find_Best_Candidate
+ 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
- Best : Library_Graph_Vertex_Id;
- Current : Library_Graph_Vertex_Id;
- Iter : LGV_Sets.Iterator;
+ 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 : Predicate_Ptr;
+ Compare_Vertices : 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 := No_Library_Graph_Vertex;
+ Best_Vertex := No_Library_Graph_Vertex;
- -- Inspect all vertices in the set, looking for the best candidate to
- -- elaborate.
+ -- 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);
- pragma Assert (Needs_Elaboration (G, Current));
+ 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;
- -- Update the best candidate when there is no such candidate
+ return Best_Vertex;
+ end Find_Best_Vertex;
- if not Present (Best) then
- Best := Current;
+ ----------------------------------------
+ -- Find_Best_Weakly_Elaborable_Vertex --
+ ----------------------------------------
- Trace_Vertex
- (G => G,
- Vertex => Best,
- Msg => "initial best candidate vertex",
- Step => Step,
- Indent => Indent);
+ 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));
- -- Update the best candidate when the current vertex is a better
- -- choice.
+ 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;
- elsif Is_Better_Candidate
- (G => G,
- Best_Candidate => Best,
- New_Candidate => Current)
- then
- Best := Current;
+ -------------------------
+ -- Has_Elaborable_Body --
+ -------------------------
- Trace_Vertex
- (G => G,
- Vertex => Best,
- Msg => "best candidate vertex",
- Step => Step,
- Indent => Indent);
- end if;
- end loop;
+ function Has_Elaborable_Body
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Vertex));
- return Best;
- end Find_Best_Candidate;
+ -- The body of an already-elaborated spec subject to Elaborate_Body
+ -- is always elaborable.
- -------------------------
- -- Is_Better_Candidate --
- -------------------------
+ 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
- function Is_Better_Candidate
- (G : Library_Graph;
- Best_Candidate : Library_Graph_Vertex_Id;
- New_Candidate : Library_Graph_Vertex_Id) return Boolean
+ 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 (Best_Candidate));
- pragma Assert (Present (New_Candidate));
+ 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
- if Is_Predefined_Unit (G, Best_Candidate)
- and then not Is_Predefined_Unit (G, New_Candidate)
+ elsif Is_Predefined_Unit (G, Vertex)
+ and then not Is_Predefined_Unit (G, Compared_To)
then
- return False;
+ return Higher_Precedence;
- elsif not Is_Predefined_Unit (G, Best_Candidate)
- and then Is_Predefined_Unit (G, New_Candidate)
+ elsif not Is_Predefined_Unit (G, Vertex)
+ and then Is_Predefined_Unit (G, Compared_To)
then
- return True;
+ return Lower_Precedence;
- -- Prefer an internal unit over a non-iternal unit
+ -- Prefer an internal unit over a non-internal unit
- elsif Is_Internal_Unit (G, Best_Candidate)
- and then not Is_Internal_Unit (G, New_Candidate)
+ elsif Is_Internal_Unit (G, Vertex)
+ and then not Is_Internal_Unit (G, Compared_To)
then
- return False;
+ return Higher_Precedence;
- elsif not Is_Internal_Unit (G, Best_Candidate)
- and then Is_Internal_Unit (G, New_Candidate)
+ elsif not Is_Internal_Unit (G, Vertex)
+ and then Is_Internal_Unit (G, Compared_To)
then
- return True;
+ return Lower_Precedence;
-- Prefer a preelaborated unit over a non-preelaborated unit
- elsif Is_Preelaborated_Unit (G, Best_Candidate)
- and then not Is_Preelaborated_Unit (G, New_Candidate)
+ elsif Is_Preelaborated_Unit (G, Vertex)
+ and then not Is_Preelaborated_Unit (G, Compared_To)
then
- return False;
+ return Higher_Precedence;
- elsif not Is_Preelaborated_Unit (G, Best_Candidate)
- and then Is_Preelaborated_Unit (G, New_Candidate)
+ elsif not Is_Preelaborated_Unit (G, Vertex)
+ and then Is_Preelaborated_Unit (G, Compared_To)
then
- return True;
+ 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
- Uname_Less (Name (G, Best_Candidate), Name (G, New_Candidate));
+ return Lower_Precedence;
end if;
- end Is_Better_Candidate;
+ end Is_Better_Elaborable_Vertex;
- ------------------------------
- -- Trace_Candidate_Vertices --
- ------------------------------
+ ----------------------------------------
+ -- Is_Better_Weakly_Elaborable_Vertex --
+ ----------------------------------------
- procedure Trace_Candidate_Vertices
- (G : Library_Graph;
- Set : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step)
+ function Is_Better_Weakly_Elaborable_Vertex
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id;
+ Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind
is
- Iter : LGV_Sets.Iterator;
- Vertex : Library_Graph_Vertex_Id;
+ Comp_Strong_Preds : Natural;
+ Comp_Weak_Preds : Natural;
+ Vertex_Strong_Preds : Natural;
+ Vertex_Weak_Preds : Natural;
begin
pragma Assert (Present (G));
- pragma Assert (LGV_Sets.Present (Set));
+ pragma Assert (Present (Vertex));
+ pragma Assert (Present (Compared_To));
- -- Nothing to do when switch -d_T (output elaboration order and cycle
- -- detection trace information) is not in effect.
+ -- Obtain the number of pending predecessors for both candidates,
+ -- taking into account Elaborate_Body pairs.
- if not Debug_Flag_Underscore_TT then
- return;
+ 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;
- Trace_Step (Step);
- Write_Str ("candidate vertices: ");
- Write_Int (Int (LGV_Sets.Size (Set)));
- Write_Eol;
+ -----------------------------------
+ -- Is_Suitable_Elaborable_Vertex --
+ -----------------------------------
- Iter := LGV_Sets.Iterate (Set);
- while LGV_Sets.Has_Next (Iter) loop
- LGV_Sets.Next (Iter, 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));
- Trace_Vertex
- (G => G,
- Vertex => Vertex,
- Msg => "candidate vertex",
- Step => Step,
- Indent => Nested_Indentation);
- end loop;
- end Trace_Candidate_Vertices;
+ -- 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;
---------------------
-- Trace_Component --
Trace_Step (Step);
Indent_By (Nested_Indentation);
- Write_Str ("pending predecessors: ");
- Write_Num (Int (Pending_Predecessors (G, Comp)));
+ 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;
Write_Str (": ");
end Trace_Step;
- ---------------------------------
- -- Trace_Unelaborated_Vertices --
- ---------------------------------
-
- procedure Trace_Unelaborated_Vertices
- (G : Library_Graph;
- Count : Natural;
- Step : Elaboration_Order_Step)
- is
- Iter : Library_Graphs.All_Vertex_Iterator;
- Vertex : Library_Graph_Vertex_Id;
-
- begin
- pragma Assert (Present (G));
-
- -- 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 ("remaining unelaborated vertices: ");
- Write_Int (Int (Count));
- Write_Eol;
-
- Iter := Iterate_All_Vertices (G);
- while Has_Next (Iter) loop
- Next (Iter, Vertex);
-
- if Needs_Elaboration (G, Vertex)
- and then not In_Elaboration_Order (G, Vertex)
- then
- Trace_Vertex
- (G => G,
- Vertex => Vertex,
- Msg => "remaining vertex",
- Step => Step,
- Indent => Nested_Indentation);
- end if;
- end loop;
- end Trace_Unelaborated_Vertices;
-
------------------
-- Trace_Vertex --
------------------
Trace_Step (Step);
Indent_By (Attr_Indent);
- Write_Str ("pending predecessors: ");
- Write_Num (Int (Pending_Predecessors (G, Vertex)));
+ 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 components : ");
- Write_Num (Int (Pending_Predecessors (G, Comp)));
+ 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;
- Pred : Library_Graph_Vertex_Id;
- Succ : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level)
+ (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 (Pred));
+ 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 (Present (Succ));
pragma Assert (Needs_Elaboration (G, Succ));
- pragma Assert (LGV_Sets.Present (All_Candidates));
- pragma Assert (LGV_Sets.Present (Comp_Candidates));
In_Different_Components : constant Boolean :=
not In_Same_Component
Vertex_Indent : constant Indentation_Level :=
Indent + Nested_Indentation;
- Candidate : Library_Graph_Vertex_Id;
- Iter : Component_Vertex_Iterator;
- Msg : String_Ptr;
- Set : LGV_Sets.Membership_Set;
+ Iter : Component_Vertex_Iterator;
+ Vertex : Library_Graph_Vertex_Id;
begin
Trace_Vertex
-- 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, Succ);
+ 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, Succ_Comp);
+ 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 is elaborated.
-
- -- 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 candidates
- -- that must be elaborated.
+ -- 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.
- if In_Different_Components then
- Msg := Add_To_All_Candidates_Msg'Access;
- Set := All_Candidates;
-
- -- Otherwise the predecessor and successor reside within the same
- -- component. Pred's component gains another elaborable node.
-
- else
- Msg := Add_To_Comp_Candidates_Msg'Access;
- Set := Comp_Candidates;
+ 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;
- Add_Vertex_If_Elaborable
- (G => G,
- Vertex => Succ,
- Set => Set,
- Msg => Msg.all,
- Step => Step,
- Indent => Vertex_Indent);
-
-- 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.
then
Iter := Iterate_Component_Vertices (G, Succ_Comp);
while Has_Next (Iter) loop
- Next (Iter, Candidate);
-
- Add_Vertex_If_Elaborable
- (G => G,
- Vertex => Candidate,
- Set => All_Candidates,
- Msg => Add_To_All_Candidates_Msg,
- Step => Step,
- Indent => Vertex_Indent);
+ 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;
-----------------------
procedure Update_Successors
- (G : Library_Graph;
- Pred : Library_Graph_Vertex_Id;
- All_Candidates : LGV_Sets.Membership_Set;
- Comp_Candidates : LGV_Sets.Membership_Set;
- Step : Elaboration_Order_Step;
- Indent : Indentation_Level)
+ (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 (Pred));
- pragma Assert (Needs_Elaboration (G, Pred));
- pragma Assert (LGV_Sets.Present (All_Candidates));
- pragma Assert (LGV_Sets.Present (Comp_Candidates));
+ 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, Pred);
+ Iter := Iterate_Edges_To_Successors (G, Vertex);
while Has_Next (Iter) loop
Next (Iter, Edge);
- pragma Assert (Predecessor (G, Edge) = Pred);
+ pragma Assert (Predecessor (G, Edge) = Vertex);
Update_Successor
- (G => G,
- Pred => Pred,
- Succ => Successor (G, Edge),
- All_Candidates => All_Candidates,
- Comp_Candidates => Comp_Candidates,
- Step => Step,
- Indent => Indent);
+ (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;
(G : Invocation_Graph;
Rel : Source_Target_Relation) return Boolean;
pragma Inline (Is_Existing_Source_Target_Relation);
- -- Determine whether a source vertex and a target vertex desctibed by
+ -- Determine whether a source vertex and a target vertex described by
-- relation Rel are already related in invocation graph G.
procedure Save_Elaboration_Root
Rel : Source_Target_Relation;
Val : Boolean := True);
pragma Inline (Set_Is_Existing_Source_Target_Relation);
- -- Mark a source vertex and a target vertex desctibed by relation Rel as
+ -- Mark a source vertex and a target vertex described by relation Rel as
-- already related in invocation graph G depending on value Val.
procedure Set_IGE_Attributes
package body Library_Graphs is
- -----------
- -- Types --
- -----------
-
- -- The following type represents the various kinds of precedence between
- -- two items.
-
- type Precedence_Kind is
- (Lower_Precedence,
- Equal_Precedence,
- Higher_Precedence);
-
-----------------------
-- Local subprograms --
-----------------------
Attrs : Library_Graph_Cycle_Attributes;
Indent : Indentation_Level);
pragma Inline (Add_Cycle);
- -- Store a cycle described by attribytes Attrs in library graph G,
+ -- Store a cycle described by attributes Attrs in library graph G,
-- unless a prior rotation of it already exists. The edges of the cycle
-- must be in normalized form. Indent is the desired indentation level
-- for tracing.
-- part of an Elaborate_Body pair, or flag Do_Complement is set, add
-- the complementary vertex to the set.
- function Complementary_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Do_Complement : Boolean) return Library_Graph_Vertex_Id;
- pragma Inline (Complementary_Vertex);
- -- If vertex Vertex of library graph G is part of an Elaborate_Body
- -- pair, or flag Do_Complement is set, return the spec when Vertex is
- -- a body, the body when Vertex is a spec, or No_Library_Graph_Vertex.
-
function Copy_Cycle_Path
(Cycle_Path : LGE_Lists.Doubly_Linked_List)
return LGE_Lists.Doubly_Linked_List;
procedure Increment_Pending_Predecessors
(G : Library_Graph;
- Comp : Component_Id);
+ Comp : Component_Id;
+ Edge : Library_Graph_Edge_Id);
pragma Inline (Increment_Pending_Predecessors);
- -- Increment the number of pending precedessors component Comp of
- -- library graph G must wait on before it can be elaborated by one.
+ -- Increment the number of pending predecessors component Comp which was
+ -- reached via edge Edge of library graph G must wait on before it can
+ -- be elaborated by one.
procedure Increment_Pending_Predecessors
(G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id);
+ Vertex : Library_Graph_Vertex_Id;
+ Edge : Library_Graph_Edge_Id);
pragma Inline (Increment_Pending_Predecessors);
- -- Increment the number of pending precedessors vertex Vertex of library
- -- graph G must wait on before it can be elaborated by one.
+ -- Increment the number of pending predecessors vertex Vertex which was
+ -- reached via edge Edge of library graph G must wait on before it can
+ -- be elaborated by one.
procedure Initialize_Components (G : Library_Graph);
pragma Inline (Initialize_Components);
Edge : Library_Graph_Edge_Id) return Boolean;
pragma Inline (Is_Cyclic_With_Edge);
-- Determine whether edge Edge of library graph G participates in a
- -- cycle and is the result of awith dependency between its successor
+ -- cycle and is the result of a with dependency between its successor
-- and predecessor.
- function Is_Elaborable_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Predecessors : Natural) return Boolean;
- pragma Inline (Is_Elaborable_Vertex);
- -- Determine whether vertex Vertex of library graph G can be elaborated
- -- given that it meets number of predecessors Predecessors.
-
function Is_Recorded_Cycle
(G : Library_Graph;
Attrs : Library_Graph_Cycle_Attributes) return Boolean;
pragma Inline (Is_Recorded_Cycle);
- -- Determine whether a cycle desctibed by its attributes Attrs has
+ -- Determine whether a cycle described by its attributes Attrs has
-- has already been recorded in library graph G.
function Is_Recorded_Edge
Rel : Predecessor_Successor_Relation) return Boolean;
pragma Inline (Is_Recorded_Edge);
-- Determine whether a predecessor vertex and a successor vertex
- -- desctibed by relation Rel are already linked in library graph G.
+ -- described by relation Rel are already linked in library graph G.
function Links_Vertices_In_Same_Component
(G : Library_Graph;
Rel : Predecessor_Successor_Relation;
Val : Boolean := True);
pragma Inline (Set_Is_Recorded_Edge);
- -- Mark a predecessor vertex and a successor vertex desctibed by
+ -- Mark a predecessor vertex and a successor vertex described by
-- relation Rel as already linked depending on value Val.
procedure Set_LGC_Attributes
-- Write the contents of vertex Vertex of library graph G to standard
-- output. Indent is the desired indentation level for tracing.
+ procedure Update_Pending_Predecessors
+ (Strong_Predecessors : in out Natural;
+ Weak_Predecessors : in out Natural;
+ Update_Weak : Boolean;
+ Value : Integer);
+ pragma Inline (Update_Pending_Predecessors);
+ -- Update the number of pending strong or weak predecessors denoted by
+ -- Strong_Predecessors and Weak_Predecessors respectively depending on
+ -- flag Update_Weak by adding value Value.
+
procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph);
pragma Inline (Update_Pending_Predecessors_Of_Components);
-- Update the number of pending predecessors all components of library
pragma Assert (LGE_Lists.Present (Edges));
-- A vertex requires a special Body_Before_Spec edge to its
- -- Corresponging_Item when it either denotes a
+ -- Corresponding_Item when it either denotes a
--
-- * Body that completes a previous spec
--
-- Update the number of pending predecessors the successor must wait
-- on before it is elaborated.
- Increment_Pending_Predecessors (G, Succ);
+ Increment_Pending_Predecessors
+ (G => G,
+ Vertex => Succ,
+ Edge => Edge);
-- Update the edge statistics
Set_LGV_Attributes
(G => G,
Vertex => Vertex,
- Val => (Corresponding_Item => No_Library_Graph_Vertex,
- In_Elaboration_Order => False,
- Pending_Predecessors => 0,
- Unit => U_Id));
+ Val =>
+ (Corresponding_Item => No_Library_Graph_Vertex,
+ In_Elaboration_Order => False,
+ Pending_Strong_Predecessors => 0,
+ Pending_Weak_Predecessors => 0,
+ Unit => U_Id));
-- Associate the unit with its corresponding vertex
Complement : constant Library_Graph_Vertex_Id :=
Complementary_Vertex
- (G => G,
- Vertex => Vertex,
- Do_Complement => Do_Complement);
+ (G => G,
+ Vertex => Vertex,
+ Force_Complement => Do_Complement);
begin
LGV_Sets.Insert (Set, Vertex);
--------------------------
function Complementary_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Do_Complement : Boolean) return Library_Graph_Vertex_Id
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id;
+ Force_Complement : Boolean) return Library_Graph_Vertex_Id
is
Complement : Library_Graph_Vertex_Id;
-- The caller requests the complement explicitly
- if Do_Complement then
+ if Force_Complement then
Complement := Corresponding_Item (G, Vertex);
-- The vertex is a completing body of a spec subject to pragma
return DG.Component (G.Graph, Vertex);
end Component;
+ ------------------------------------
+ -- Contains_Weak_Static_Successor --
+ ------------------------------------
+
+ function Contains_Weak_Static_Successor
+ (G : Library_Graph;
+ Cycle : Library_Graph_Cycle_Id) return Boolean
+ is
+ Edge : Library_Graph_Edge_Id;
+ Iter : Edges_Of_Cycle_Iterator;
+ Seen : Boolean;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Cycle));
+
+ -- Assume that no weak static successor has been seen
+
+ Seen := False;
+
+ -- IMPORTANT:
+ --
+ -- * The iteration must run to completion in order to unlock the
+ -- edges of the cycle.
+
+ Iter := Iterate_Edges_Of_Cycle (G, Cycle);
+ while Has_Next (Iter) loop
+ Next (Iter, Edge);
+
+ if not Seen
+ and then Is_Invocation_Edge (G, Edge)
+ and then not Is_Dynamically_Elaborated (G, Successor (G, Edge))
+ then
+ Seen := True;
+ end if;
+ end loop;
+
+ return Seen;
+ end Contains_Weak_Static_Successor;
+
---------------------
-- Copy_Cycle_Path --
---------------------
------------
function Create
- (Initial_Vertices : Positive;
- Initial_Edges : Positive;
- Dynamically_Elaborated : Boolean) return Library_Graph
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Library_Graph
is
G : constant Library_Graph := new Library_Graph_Attributes;
begin
- G.Dynamically_Elaborated := Dynamically_Elaborated;
-
G.Component_Attributes := Component_Tables.Create (Initial_Vertices);
G.Cycle_Attributes := LGC_Tables.Create (Initial_Vertices);
G.Cycles := LGC_Lists.Create;
procedure Decrement_Pending_Predecessors
(G : Library_Graph;
- Comp : Component_Id)
+ Comp : Component_Id;
+ Edge : Library_Graph_Edge_Id)
is
Attrs : Component_Attributes;
pragma Assert (Present (Comp));
Attrs := Get_Component_Attributes (G, Comp);
- Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+
+ Update_Pending_Predecessors
+ (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+ Weak_Predecessors => Attrs.Pending_Weak_Predecessors,
+ Update_Weak => Is_Invocation_Edge (G, Edge),
+ Value => -1);
+
Set_Component_Attributes (G, Comp, Attrs);
end Decrement_Pending_Predecessors;
procedure Decrement_Pending_Predecessors
(G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id)
+ Vertex : Library_Graph_Vertex_Id;
+ Edge : Library_Graph_Edge_Id)
is
Attrs : Library_Graph_Vertex_Attributes;
pragma Assert (Present (Vertex));
Attrs := Get_LGV_Attributes (G, Vertex);
- Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+
+ Update_Pending_Predecessors
+ (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+ Weak_Predecessors => Attrs.Pending_Weak_Predecessors,
+ Update_Weak => Is_Invocation_Edge (G, Edge),
+ Value => -1);
+
Set_LGV_Attributes (G, Vertex, Attrs);
end Decrement_Pending_Predecessors;
-- Update the number of pending predecessors the successor must wait
-- on before it is elaborated.
- Decrement_Pending_Predecessors (G, Succ);
+ Decrement_Pending_Predecessors
+ (G => G,
+ Vertex => Succ,
+ Edge => Edge);
-- Delete the link between the predecessor and successor. This allows
-- for further attempts to link the same predecessor and successor.
(G => G,
Vertex =>
Complementary_Vertex
- (G => G,
- Vertex => Vertex,
- Do_Complement => Spec_And_Body_Together),
+ (G => G,
+ Vertex => Vertex,
+ Force_Complement => Spec_And_Body_Together),
End_Vertices => End_Vertices,
Most_Significant_Edge => Most_Significant_Edge,
Invocation_Edge_Count => Invocation_Edge_Count,
Trace_Edge (G, Initial_Edge, Indent);
-- Use a set to represent the end vertices of the cycle. The set is
- -- needed to accomodate the Elaborate_All and Elaborate_Body cases
+ -- needed to accommodate the Elaborate_All and Elaborate_Body cases
-- where a cycle may terminate on either a spec or a body vertex.
End_Vertices := LGV_Sets.Create (2);
U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
begin
- return U_Rec.Elaborate_Body;
+ -- Treat the spec and body as decoupled when switch -d_b (ignore the
+ -- effects of pragma Elaborate_Body) is in effect.
+
+ return U_Rec.Elaborate_Body and not Debug_Flag_Underscore_B;
end Has_Elaborate_Body;
--------------
procedure Increment_Pending_Predecessors
(G : Library_Graph;
- Comp : Component_Id)
+ Comp : Component_Id;
+ Edge : Library_Graph_Edge_Id)
is
Attrs : Component_Attributes;
pragma Assert (Present (Comp));
Attrs := Get_Component_Attributes (G, Comp);
- Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+
+ Update_Pending_Predecessors
+ (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+ Weak_Predecessors => Attrs.Pending_Weak_Predecessors,
+ Update_Weak => Is_Invocation_Edge (G, Edge),
+ Value => 1);
+
Set_Component_Attributes (G, Comp, Attrs);
end Increment_Pending_Predecessors;
procedure Increment_Pending_Predecessors
(G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id)
+ Vertex : Library_Graph_Vertex_Id;
+ Edge : Library_Graph_Edge_Id)
is
Attrs : Library_Graph_Vertex_Attributes;
pragma Assert (Present (Vertex));
Attrs := Get_LGV_Attributes (G, Vertex);
- Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+
+ Update_Pending_Predecessors
+ (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+ Weak_Predecessors => Attrs.Pending_Weak_Predecessors,
+ Update_Weak => Is_Invocation_Edge (G, Edge),
+ Value => 1);
+
Set_LGV_Attributes (G, Vertex, Attrs);
end Increment_Pending_Predecessors;
pragma Assert (Present (G));
-- The graph already contains a set of components. Reinitialize
- -- them in order to accomodate the new set of components about to
+ -- them in order to accommodate the new set of components about to
-- be computed.
if Number_Of_Components (G) > 0 then
-- Is_Dynamically_Elaborated --
-------------------------------
- function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean is
+ function Is_Dynamically_Elaborated
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id) return Boolean
+ is
begin
pragma Assert (Present (G));
+ pragma Assert (Present (Vertex));
- return G.Dynamically_Elaborated;
+ return Is_Dynamically_Elaborated (Unit (G, Vertex));
end Is_Dynamically_Elaborated;
-----------------------------
pragma Assert (Present (G));
pragma Assert (Present (Comp));
- -- A component can be elaborated when
+ -- A component is elaborable when:
--
- -- * The component is no longer wanting on any of its predecessors
- -- to be elaborated.
+ -- * It is not waiting on strong predecessors, and
+ -- * It is not waiting on weak predecessors
- return Pending_Predecessors (G, Comp) = 0;
+ return
+ Pending_Strong_Predecessors (G, Comp) = 0
+ and then Pending_Weak_Predecessors (G, Comp) = 0;
end Is_Elaborable_Component;
--------------------------
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Boolean
is
- Check_Vertex : Library_Graph_Vertex_Id;
-
- begin
pragma Assert (Present (G));
pragma Assert (Present (Vertex));
- Check_Vertex := Vertex;
-
- -- A spec-body pair where the spec carries pragma Elaborate_Body must
- -- be treated as one vertex for elaboration purposes. Use the spec as
- -- the point of reference for the composite vertex.
-
- if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_Vertex) then
- Check_Vertex := Proper_Spec (G, Check_Vertex);
- end if;
-
- return
- Is_Elaborable_Vertex
- (G => G,
- Vertex => Check_Vertex,
- Predecessors => 0);
- end Is_Elaborable_Vertex;
-
- --------------------------
- -- Is_Elaborable_Vertex --
- --------------------------
+ Complement : constant Library_Graph_Vertex_Id :=
+ Complementary_Vertex
+ (G => G,
+ Vertex => Vertex,
+ Force_Complement => False);
- function Is_Elaborable_Vertex
- (G : Library_Graph;
- Vertex : Library_Graph_Vertex_Id;
- Predecessors : Natural) return Boolean
- is
- Body_Vertex : Library_Graph_Vertex_Id;
+ Strong_Preds : Natural;
+ Weak_Preds : Natural;
begin
- pragma Assert (Present (G));
- pragma Assert (Present (Vertex));
-
- -- The vertex must not be re-elaborated once it has been elaborated
+ -- A vertex is elaborable when:
+ --
+ -- * It has not been elaborated yet, and
+ -- * The complement vertex of an Elaborate_Body pair has not been
+ -- elaborated yet, and
+ -- * It resides within an elaborable component, and
+ -- * It is not waiting on strong predecessors, and
+ -- * It is not waiting on weak predecessors
if In_Elaboration_Order (G, Vertex) then
return False;
- -- The vertex must not be waiting on more precedessors than requested
- -- to be elaborated.
-
- elsif Pending_Predecessors (G, Vertex) /= Predecessors then
+ elsif Present (Complement)
+ and then In_Elaboration_Order (G, Complement)
+ then
return False;
- -- The component where the vertex resides must not be waiting on any
- -- of its precedessors to be elaborated.
-
elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then
return False;
-
- -- The vertex denotes a spec with a completing body, and is subject
- -- to pragma Elaborate_Body. The body must be elaborable for the
- -- vertex to be elaborated. Account for the sole predecessor of the
- -- body which is the vertex itself.
-
- elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
- Body_Vertex := Proper_Body (G, Vertex);
- pragma Assert (Present (Body_Vertex));
-
- return
- Is_Elaborable_Vertex
- (G => G,
- Vertex => Body_Vertex,
- Predecessors => 1);
end if;
- -- At this point it is known that the vertex can be elaborated
+ Pending_Predecessors_For_Elaboration
+ (G => G,
+ Vertex => Vertex,
+ Strong_Preds => Strong_Preds,
+ Weak_Preds => Weak_Preds);
- return True;
+ return Strong_Preds = 0 and then Weak_Preds = 0;
end Is_Elaborable_Vertex;
---------------------------
return Kind (G, Edge) = Elaborate_Edge;
end Is_Elaborate_Edge;
+ ----------------------------
+ -- Is_Elaborate_Body_Pair --
+ ----------------------------
+
+ function Is_Elaborate_Body_Pair
+ (G : Library_Graph;
+ Spec_Vertex : Library_Graph_Vertex_Id;
+ Body_Vertex : Library_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Spec_Vertex));
+ pragma Assert (Present (Body_Vertex));
+
+ return
+ Is_Spec_With_Elaborate_Body (G, Spec_Vertex)
+ and then Is_Body_Of_Spec_With_Elaborate_Body (G, Body_Vertex)
+ and then Proper_Body (G, Spec_Vertex) = Body_Vertex;
+ end Is_Elaborate_Body_Pair;
+
--------------------
-- Is_Forced_Edge --
--------------------
and then Has_Elaborate_Body (G, Vertex);
end Is_Spec_With_Elaborate_Body;
+ ---------------------------------
+ -- Is_Weakly_Elaborable_Vertex --
+ ----------------------------------
+
+ function Is_Weakly_Elaborable_Vertex
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (Vertex));
+
+ Complement : constant Library_Graph_Vertex_Id :=
+ Complementary_Vertex
+ (G => G,
+ Vertex => Vertex,
+ Force_Complement => False);
+
+ Strong_Preds : Natural;
+ Weak_Preds : Natural;
+
+ begin
+ -- A vertex is weakly elaborable when:
+ --
+ -- * It has not been elaborated yet, and
+ -- * The complement vertex of an Elaborate_Body pair has not been
+ -- elaborated yet, and
+ -- * It resides within an elaborable component, and
+ -- * It is not waiting on strong predecessors, and
+ -- * It is waiting on at least one weak predecessor
+
+ if In_Elaboration_Order (G, Vertex) then
+ return False;
+
+ elsif Present (Complement)
+ and then In_Elaboration_Order (G, Complement)
+ then
+ return False;
+
+ elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then
+ return False;
+ end if;
+
+ Pending_Predecessors_For_Elaboration
+ (G => G,
+ Vertex => Vertex,
+ Strong_Preds => Strong_Preds,
+ Weak_Preds => Weak_Preds);
+
+ return Strong_Preds = 0 and then Weak_Preds >= 1;
+ end Is_Weakly_Elaborable_Vertex;
+
------------------
-- Is_With_Edge --
------------------
return Get_LGC_Attributes (G, Cycle).Path;
end Path;
- --------------------------
- -- Pending_Predecessors --
- --------------------------
+ ------------------------------------------
+ -- Pending_Predecessors_For_Elaboration --
+ ------------------------------------------
- function Pending_Predecessors
+ procedure Pending_Predecessors_For_Elaboration
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id;
+ Strong_Preds : out Natural;
+ Weak_Preds : out Natural)
+ is
+ Complement : Library_Graph_Vertex_Id;
+ Spec_Vertex : Library_Graph_Vertex_Id;
+ Total_Strong_Preds : Natural;
+ Total_Weak_Preds : Natural;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Vertex));
+
+ Total_Strong_Preds := Pending_Strong_Predecessors (G, Vertex);
+ Total_Weak_Preds := Pending_Weak_Predecessors (G, Vertex);
+
+ -- Assume that there is no complementary vertex that needs to be
+ -- examined.
+
+ Complement := No_Library_Graph_Vertex;
+ Spec_Vertex := No_Library_Graph_Vertex;
+
+ if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then
+ Complement := Proper_Spec (G, Vertex);
+ Spec_Vertex := Complement;
+
+ elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
+ Complement := Proper_Body (G, Vertex);
+ Spec_Vertex := Vertex;
+ end if;
+
+ -- The vertex is part of an Elaborate_Body pair. Take into account
+ -- the strong and weak predecessors of the complementary vertex.
+
+ if Present (Complement) then
+ Total_Strong_Preds :=
+ Pending_Strong_Predecessors (G, Complement) + Total_Strong_Preds;
+ Total_Weak_Preds :=
+ Pending_Weak_Predecessors (G, Complement) + Total_Weak_Preds;
+
+ -- The body of an Elaborate_Body pair is the successor of a strong
+ -- edge where the predecessor is the spec. This edge must not be
+ -- considered for elaboration purposes because the pair is treated
+ -- as one vertex. Account for the edge only when the spec has not
+ -- been elaborated yet.
+
+ if not In_Elaboration_Order (G, Spec_Vertex) then
+ Total_Strong_Preds := Total_Strong_Preds - 1;
+ end if;
+ end if;
+
+ Strong_Preds := Total_Strong_Preds;
+ Weak_Preds := Total_Weak_Preds;
+ end Pending_Predecessors_For_Elaboration;
+
+ ---------------------------------
+ -- Pending_Strong_Predecessors --
+ ---------------------------------
+
+ function Pending_Strong_Predecessors
(G : Library_Graph;
Comp : Component_Id) return Natural
is
pragma Assert (Present (G));
pragma Assert (Present (Comp));
- return Get_Component_Attributes (G, Comp).Pending_Predecessors;
- end Pending_Predecessors;
+ return Get_Component_Attributes (G, Comp).Pending_Strong_Predecessors;
+ end Pending_Strong_Predecessors;
- --------------------------
- -- Pending_Predecessors --
- --------------------------
+ ---------------------------------
+ -- Pending_Strong_Predecessors --
+ ---------------------------------
- function Pending_Predecessors
+ function Pending_Strong_Predecessors
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Natural
is
pragma Assert (Present (G));
pragma Assert (Present (Vertex));
- return Get_LGV_Attributes (G, Vertex).Pending_Predecessors;
- end Pending_Predecessors;
+ return Get_LGV_Attributes (G, Vertex).Pending_Strong_Predecessors;
+ end Pending_Strong_Predecessors;
+
+ -------------------------------
+ -- Pending_Weak_Predecessors --
+ -------------------------------
+
+ function Pending_Weak_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ return Get_Component_Attributes (G, Comp).Pending_Weak_Predecessors;
+ end Pending_Weak_Predecessors;
+
+ -------------------------------
+ -- Pending_Weak_Predecessors --
+ -------------------------------
+
+ function Pending_Weak_Predecessors
+ (G : Library_Graph;
+ Vertex : Library_Graph_Vertex_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Vertex));
+
+ return Get_LGV_Attributes (G, Vertex).Pending_Weak_Predecessors;
+ end Pending_Weak_Predecessors;
----------------
-- Precedence --
Complement : constant Library_Graph_Vertex_Id :=
Complementary_Vertex
- (G => G,
- Vertex => Vertex,
- Do_Complement => Do_Complement);
+ (G => G,
+ Vertex => Vertex,
+ Force_Complement => Do_Complement);
begin
LGV_Sets.Delete (Set, Vertex);
return Get_LGV_Attributes (G, Vertex).Unit;
end Unit;
+ ---------------------------------
+ -- Update_Pending_Predecessors --
+ ---------------------------------
+
+ procedure Update_Pending_Predecessors
+ (Strong_Predecessors : in out Natural;
+ Weak_Predecessors : in out Natural;
+ Update_Weak : Boolean;
+ Value : Integer)
+ is
+ begin
+ if Update_Weak then
+ Weak_Predecessors := Weak_Predecessors + Value;
+ else
+ Strong_Predecessors := Strong_Predecessors + Value;
+ end if;
+ end Update_Pending_Predecessors;
+
-----------------------------------------------
-- Update_Pending_Predecessors_Of_Components --
-----------------------------------------------
-- must wait on another predecessor until it can be elaborated.
if Pred_Comp /= Succ_Comp then
- Increment_Pending_Predecessors (G, Succ_Comp);
+ Increment_Pending_Predecessors
+ (G => G,
+ Comp => Succ_Comp,
+ Edge => Edge);
end if;
end Update_Pending_Predecessors_Of_Components;
end Library_Graphs;
--------------------------
LGC_Sequencer : Library_Graph_Cycle_Id := First_Library_Graph_Cycle;
- -- The couhnter for library graph cycles. Do not directly manipulate its
+ -- The counter for library graph cycles. Do not directly manipulate its
-- value.
function Sequence_Next_Cycle return Library_Graph_Cycle_Id is