Commit 92c7734d by Hristian Kirtchev Committed by Pierre-Marie de Rodat

[Ada] New algorithm for Elaboration order v4.0

This patch introduces several changes to the new elaboration order
mechanism:

   * The concept of "strong" and "weak" edges is introduced. Strong
     edges are the byproduct of language-defined relations between
     units, such as with clauses. Weak edges are the byproduct of
     specilative invocations at elaboration time, which may or may not
     take place depending on control flow.

   * The elaboration order algorithm has been heavily modified to make
     use of the strong and weak edges, and operate on units compiled
     with different elaboration models.

   * The elaboration order algorithm employs the following logic:

        - Maintain two sets of vertices, one for all elaborable
          vertices, and one for all waiting vertices.

        - Pick the best elaborable vertex, and elaborate its component.

        - If no such elaborable vertex is available, pick the best
          weakly elaborable vertex whose unit has been compiled with the
          dynamic model, and elaborate its component.

        - If no such weakly elaborable vertex is available, then either
          all vertices were already elaborated, or the graph contains a
          cycle.

     The elaboration of a component employs the same logic, with an
     added step where all successors of some predecessor currently being
     elaborated are notified that they have one fewer predecessor to
     wait on. This may cause certain successors to become elaborable, in
     which case they are moved from the set of waiting vertices to the
     set of elaborable vertices.

   * Three new GNATbind debug switches are introduced, -d_a, -d_b, and
     -d_e, to eliminate the effects of pragmas Elaborate_All,
     Elaborate_Body, and Elaborate respectively.

   * The section on terminology is updated to include new entries.

2019-07-08  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

	* bindo.adb: Update the section on terminology to include new
	concepts.  Update the section on switches to include new
	entries.
	* bindo.ads: Add type Precedence_Kind.
	* bindo-builders.adb: Add with and use clauses for Debug and
	Bindo.Validators.  Add use clauses for
	Bindo.Validators.Invocation_Graph_Validators and
	Bindo.Validators.Library_Graph_Validators.
	(Build_Invocation_Graph): Validate the graph immediately after
	it was built.
	(Build_Library_Graph): Update the parameter profile. The
	creation of the graph is now elaboration model-agnostic.
	Validate the graph immediately after it was built.
	(Create_With_Edge): Create regular with edges for Elaborate and
	Elaborate_All edges when the appropriate debug switches are in
	effect.
	* bindo-builders.ads (Build_Library_Graph): Update the parameter
	profile.
	* bindo-diagnostics.adb (Diagnose_Cycle): Track the presence of
	an Elaborate_All edge throughout the inspection of the cycle's
	edges.
	(Output_Dynamic_Model_Suggestions): Output the suggestion only
	when the cycle contains at least one weak edge where the
	successor was statically elaborated.
	(Output_Elaborate_Body_Transition, Output_Forced_Transition,
	Output_With_Transition): Update the assertions.
	* bindo-elaborators.adb: Remove use clauses for
	Bindo.Validators.Invocation_Graph_Validators and
	Bindo.Validators.Library_Graph_Validators.  Remove strings
	Add_To_All_Candidates_Msg and Add_To_Comp_Candidates_Msg.
	Remove type String_Ptr.
	(Add_Vertex, Add_Vertex_If_Elaborable, Create_All_Candidates_Set
	Create_Component_Candidates_Set): Remove.
	(Create_Component_Vertex_Sets, Create_Vertex_Sets): New routine.
	(Elaborate_Component): Update the parameter profile and the
	comment on usage.  Reimplement the elaboration of a component.
	The algorithm will now attempt to elaborate as many vertices
	possible. If this is not possible, and a weakly elaborable
	vertex is available use unit was compiled using the dynamic
	model, the algorithm will elaborate it.
	(Elaborate_Library_Graph): Reimplement the elaboration of the
	graph. The algorithm will now attempt to elaborate as many
	vertices along with their components as possible. If this is not
	possible, and a weakly elaborable vertex is available use unit
	was compiled using the dynamic model, the algorithm will
	elaborate it along with its component.
	(Elaborate_Units): Merge with the functionality of
	Elaborate_Units_Common.
	(Elaborate_Units_Common, Elaborate_Units_Dynamic,
	Elaborate_Units_Static): Remove.
	(Elaborate_Vertex): Update the parameter profile and the comment
	on usage.  Reimplemented.
	(Find_Best_Candidate): Remove.
	(Find_Best_Elaborable_Vertex, Find_Best_Vertex,
	Find_Best_Weakly_Elaborable_Vertex, Has_Elaborable_Body,
	Insert_Elaborable_Successor, Insert_Vertex): New routines.
	(Is_Better_Candidate): Remove.
	(Is_Better_Elaborable_Vertex,
	Is_Better_Weakly_Elaborable_Vertex,
	Is_Suitable_Elaborable_Vertex,
	Is_Suitable_Weakly_Elaborable_Vertex): New routines.
	(Trace_Candidate_Vertices): Remove.
	(Trace_Component): Output the number of strong and weak
	predecessors.
	(Trace_Unelaborated_Vertices): Remove.
	(Trace_Vertex): Output the number of strong and weak
	predecessors.
	(Trace_Vertices): New routine.
	(Update_Successor, Update_Successors): Update the parameter
	profile and the comment on usage.
	* bindo-graphs.adb: Remove type Precedence_Kind.
	(Add_Edge_With_Return): Update the increment of pending
	predecessors.
	(Add_Vertex): Provide default values for strong and weak
	predecessors.
	(Complementary_Vertex): Move the initial declaration to the
	spec. Update the parameter profile and the comment on usage.
	(Contains_Weak_Static_Successor): New routine.
	(Create): Update the parameter profile. The creation of the
	graph is now elaboration model-agnostic.
	(Decrement_Pending_Predecessors): Update the parameter profile
	and the comment on usage. Reimplemented.
	(Delete_Edge): Update the decrement of pending predecesors.
	(Has_Elaborate_Body): Do not treat a vertex as being subject to
	Elaborate_Body when a debug switch is in effect.
	(Increment_Pending_Predecessors): Update the parameter profile
	and the comment on usage. Reimplemented.
	(Is_Elaborable_Component): Reimplemented.
	(Is_Elaborable_Vertex): Move the initial declaration to the
	spec.  Reimplemented.
	(Is_Elaborate_Body_Pair): New routine.
	(Is_Dynamically_Elaborated): Update the parameter profile.
	Reimplemented.
	(Is_Weakly_Elaborable_Vertex): New routine.
	(Pending_Predecessors): Removed.
	(Pending_Predecessors_For_Elaboration,
	Pending_Strong_Predecessors, Pending_Weak_Predecessors,
	Update_Pending_Predecessors): New routines.
	(Update_Pending_Predecessors_Of_Components): Update the
	increment of pending predecessors.
	* bindo-graphs.ads: Update the components of type
	Component_Attributes.  Update the components of type
	Library_Graph_Attributes.  Update the components of type
	Library_Graph_Vertex_Attributes.  Update the initialization of
	No_Component_Attributes.  Update the initialization of
	No_Library_Graph_Vertex_Attributes.
	(Complementary_Vertex, Contains_Weak_Static_Successor): New
	routines.
	(Create): Update the parameter profile and the comment on usage.
	(Decrement_Pending_Predecessors, Is_Dynamically_Elaborated):
	Update the parameter profile and the comment on usage.
	(Is_Elaborate_Body_Pair, Is_Weakly_Elaborable_Vertex): New
	routines.
	(Pending_Predecessors): Removed.
	(Pending_Predecessors_For_Elaboration,
	Pending_Strong_Predecessors, Pending_Weak_Predecessors): New
	routines.
	* bindo-writers.adb (Write_Components): Moved from the spec.
	(Write_Component): Output the strong and weak predecessors.
	(Write_Library_Graph): Output the components as part of the
	graph.
	(Write_Library_Graph_Vertex): Output the strong and weak
	predecessors.
	* bindo-writers.ads (Write_Components): Moved to the body.
	* debug.adb: Add and document new GNATbind switches -d_a, -d_b,
	-d_e.
	* bindo-validators.adb: Minor reformattings.

From-SVN: r273209
parent 79ee9e32
2019-07-08 Hristian Kirtchev <kirtchev@adacore.com>
* bindo.adb: Update the section on terminology to include new
concepts. Update the section on switches to include new
entries.
* bindo.ads: Add type Precedence_Kind.
* bindo-builders.adb: Add with and use clauses for Debug and
Bindo.Validators. Add use clauses for
Bindo.Validators.Invocation_Graph_Validators and
Bindo.Validators.Library_Graph_Validators.
(Build_Invocation_Graph): Validate the graph immediately after
it was built.
(Build_Library_Graph): Update the parameter profile. The
creation of the graph is now elaboration model-agnostic.
Validate the graph immediately after it was built.
(Create_With_Edge): Create regular with edges for Elaborate and
Elaborate_All edges when the appropriate debug switches are in
effect.
* bindo-builders.ads (Build_Library_Graph): Update the parameter
profile.
* bindo-diagnostics.adb (Diagnose_Cycle): Track the presence of
an Elaborate_All edge throughout the inspection of the cycle's
edges.
(Output_Dynamic_Model_Suggestions): Output the suggestion only
when the cycle contains at least one weak edge where the
successor was statically elaborated.
(Output_Elaborate_Body_Transition, Output_Forced_Transition,
Output_With_Transition): Update the assertions.
* bindo-elaborators.adb: Remove use clauses for
Bindo.Validators.Invocation_Graph_Validators and
Bindo.Validators.Library_Graph_Validators. Remove strings
Add_To_All_Candidates_Msg and Add_To_Comp_Candidates_Msg.
Remove type String_Ptr.
(Add_Vertex, Add_Vertex_If_Elaborable, Create_All_Candidates_Set
Create_Component_Candidates_Set): Remove.
(Create_Component_Vertex_Sets, Create_Vertex_Sets): New routine.
(Elaborate_Component): Update the parameter profile and the
comment on usage. Reimplement the elaboration of a component.
The algorithm will now attempt to elaborate as many vertices
possible. If this is not possible, and a weakly elaborable
vertex is available use unit was compiled using the dynamic
model, the algorithm will elaborate it.
(Elaborate_Library_Graph): Reimplement the elaboration of the
graph. The algorithm will now attempt to elaborate as many
vertices along with their components as possible. If this is not
possible, and a weakly elaborable vertex is available use unit
was compiled using the dynamic model, the algorithm will
elaborate it along with its component.
(Elaborate_Units): Merge with the functionality of
Elaborate_Units_Common.
(Elaborate_Units_Common, Elaborate_Units_Dynamic,
Elaborate_Units_Static): Remove.
(Elaborate_Vertex): Update the parameter profile and the comment
on usage. Reimplemented.
(Find_Best_Candidate): Remove.
(Find_Best_Elaborable_Vertex, Find_Best_Vertex,
Find_Best_Weakly_Elaborable_Vertex, Has_Elaborable_Body,
Insert_Elaborable_Successor, Insert_Vertex): New routines.
(Is_Better_Candidate): Remove.
(Is_Better_Elaborable_Vertex,
Is_Better_Weakly_Elaborable_Vertex,
Is_Suitable_Elaborable_Vertex,
Is_Suitable_Weakly_Elaborable_Vertex): New routines.
(Trace_Candidate_Vertices): Remove.
(Trace_Component): Output the number of strong and weak
predecessors.
(Trace_Unelaborated_Vertices): Remove.
(Trace_Vertex): Output the number of strong and weak
predecessors.
(Trace_Vertices): New routine.
(Update_Successor, Update_Successors): Update the parameter
profile and the comment on usage.
* bindo-graphs.adb: Remove type Precedence_Kind.
(Add_Edge_With_Return): Update the increment of pending
predecessors.
(Add_Vertex): Provide default values for strong and weak
predecessors.
(Complementary_Vertex): Move the initial declaration to the
spec. Update the parameter profile and the comment on usage.
(Contains_Weak_Static_Successor): New routine.
(Create): Update the parameter profile. The creation of the
graph is now elaboration model-agnostic.
(Decrement_Pending_Predecessors): Update the parameter profile
and the comment on usage. Reimplemented.
(Delete_Edge): Update the decrement of pending predecesors.
(Has_Elaborate_Body): Do not treat a vertex as being subject to
Elaborate_Body when a debug switch is in effect.
(Increment_Pending_Predecessors): Update the parameter profile
and the comment on usage. Reimplemented.
(Is_Elaborable_Component): Reimplemented.
(Is_Elaborable_Vertex): Move the initial declaration to the
spec. Reimplemented.
(Is_Elaborate_Body_Pair): New routine.
(Is_Dynamically_Elaborated): Update the parameter profile.
Reimplemented.
(Is_Weakly_Elaborable_Vertex): New routine.
(Pending_Predecessors): Removed.
(Pending_Predecessors_For_Elaboration,
Pending_Strong_Predecessors, Pending_Weak_Predecessors,
Update_Pending_Predecessors): New routines.
(Update_Pending_Predecessors_Of_Components): Update the
increment of pending predecessors.
* bindo-graphs.ads: Update the components of type
Component_Attributes. Update the components of type
Library_Graph_Attributes. Update the components of type
Library_Graph_Vertex_Attributes. Update the initialization of
No_Component_Attributes. Update the initialization of
No_Library_Graph_Vertex_Attributes.
(Complementary_Vertex, Contains_Weak_Static_Successor): New
routines.
(Create): Update the parameter profile and the comment on usage.
(Decrement_Pending_Predecessors, Is_Dynamically_Elaborated):
Update the parameter profile and the comment on usage.
(Is_Elaborate_Body_Pair, Is_Weakly_Elaborable_Vertex): New
routines.
(Pending_Predecessors): Removed.
(Pending_Predecessors_For_Elaboration,
Pending_Strong_Predecessors, Pending_Weak_Predecessors): New
routines.
* bindo-writers.adb (Write_Components): Moved from the spec.
(Write_Component): Output the strong and weak predecessors.
(Write_Library_Graph): Output the components as part of the
graph.
(Write_Library_Graph_Vertex): Output the strong and weak
predecessors.
* bindo-writers.ads (Write_Components): Moved to the body.
* debug.adb: Add and document new GNATbind switches -d_a, -d_b,
-d_e.
* bindo-validators.adb: Minor reformattings.
2019-07-08 Bob Duff <duff@adacore.com> 2019-07-08 Bob Duff <duff@adacore.com>
* libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate): * libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate):
......
...@@ -25,12 +25,18 @@ ...@@ -25,12 +25,18 @@
with Binderr; use Binderr; with Binderr; use Binderr;
with Butil; use Butil; with Butil; use Butil;
with Debug; use Debug;
with Opt; use Opt; with Opt; use Opt;
with Output; use Output; with Output; use Output;
with Types; use Types; with Types; use Types;
with Bindo.Units; use Bindo.Units; with Bindo.Units; use Bindo.Units;
with Bindo.Validators;
use Bindo.Validators;
use Bindo.Validators.Invocation_Graph_Validators;
use Bindo.Validators.Library_Graph_Validators;
with GNAT; use GNAT; with GNAT; use GNAT;
with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
...@@ -104,6 +110,8 @@ package body Bindo.Builders is ...@@ -104,6 +110,8 @@ package body Bindo.Builders is
For_Each_Elaborable_Unit (Create_Vertices'Access); For_Each_Elaborable_Unit (Create_Vertices'Access);
For_Each_Elaborable_Unit (Create_Edges'Access); For_Each_Elaborable_Unit (Create_Edges'Access);
Validate_Invocation_Graph (Inv_Graph);
return Inv_Graph; return Inv_Graph;
end Build_Invocation_Graph; end Build_Invocation_Graph;
...@@ -365,24 +373,22 @@ package body Bindo.Builders is ...@@ -365,24 +373,22 @@ package body Bindo.Builders is
-- Build_Library_Graph -- -- Build_Library_Graph --
------------------------- -------------------------
function Build_Library_Graph function Build_Library_Graph return Library_Graph is
(Dynamically_Elaborated : Boolean) return Library_Graph
is
begin begin
-- Prepare the global data -- Prepare the global data
Lib_Graph := Lib_Graph :=
Create Create
(Initial_Vertices => Number_Of_Elaborable_Units, (Initial_Vertices => Number_Of_Elaborable_Units,
Initial_Edges => Number_Of_Elaborable_Units, Initial_Edges => Number_Of_Elaborable_Units);
Dynamically_Elaborated => Dynamically_Elaborated);
For_Each_Elaborable_Unit (Create_Vertex'Access); For_Each_Elaborable_Unit (Create_Vertex'Access);
For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access); For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access);
For_Each_Elaborable_Unit (Create_With_Edges'Access); For_Each_Elaborable_Unit (Create_With_Edges'Access);
Create_Forced_Edges; Create_Forced_Edges;
Validate_Library_Graph (Lib_Graph);
return Lib_Graph; return Lib_Graph;
end Build_Library_Graph; end Build_Library_Graph;
...@@ -549,9 +555,13 @@ package body Bindo.Builders is ...@@ -549,9 +555,13 @@ package body Bindo.Builders is
Withed_Vertex := Corresponding_Vertex (Lib_Graph, Withed_U_Id); Withed_Vertex := Corresponding_Vertex (Lib_Graph, Withed_U_Id);
-- The with comes with pragma Elaborate -- The with comes with pragma Elaborate. Treat the edge as a with
-- edge when switch -d_e (ignore the effects of pragma Elaborate)
-- is in effect.
if Withed_Rec.Elaborate then if Withed_Rec.Elaborate
and then not Debug_Flag_Underscore_E
then
Kind := Elaborate_Edge; Kind := Elaborate_Edge;
-- The withed unit is a spec with a completing body. Add an edge -- The withed unit is a spec with a completing body. Add an edge
...@@ -568,9 +578,13 @@ package body Bindo.Builders is ...@@ -568,9 +578,13 @@ package body Bindo.Builders is
Kind => Kind); Kind => Kind);
end if; end if;
-- The with comes with pragma Elaborate_All -- The with comes with pragma Elaborate_All. Treat the edge as a with
-- edge when switch -d_a (ignore the effects of pragma Elaborate_All)
-- is in effect.
elsif Withed_Rec.Elaborate_All then elsif Withed_Rec.Elaborate_All
and then not Debug_Flag_Underscore_A
then
Kind := Elaborate_All_Edge; Kind := Elaborate_All_Edge;
-- Otherwise this is a regular with -- Otherwise this is a regular with
......
...@@ -56,11 +56,9 @@ package Bindo.Builders is ...@@ -56,11 +56,9 @@ package Bindo.Builders is
---------------------------- ----------------------------
package Library_Graph_Builders is package Library_Graph_Builders is
function Build_Library_Graph function Build_Library_Graph return Library_Graph;
(Dynamically_Elaborated : Boolean) return Library_Graph;
-- Return a new library graph that reflects the dependencies between -- Return a new library graph that reflects the dependencies between
-- all units of the bind. Flag Dynamically_Elaborated must be set when -- all units of the bind.
-- the main library unit was compiled using the dynamic model.
end Library_Graph_Builders; end Library_Graph_Builders;
......
...@@ -285,9 +285,9 @@ package body Bindo.Diagnostics is ...@@ -285,9 +285,9 @@ package body Bindo.Diagnostics is
end loop; end loop;
end Diagnose_All_Cycles; end Diagnose_All_Cycles;
-------------------------- ----------------------------
-- Diagnose_Circularities -- -- Diagnose_Circularities --
-------------------------- ----------------------------
procedure Diagnose_Circularities procedure Diagnose_Circularities
(Inv_Graph : Invocation_Graph; (Inv_Graph : Invocation_Graph;
...@@ -374,6 +374,12 @@ package body Bindo.Diagnostics is ...@@ -374,6 +374,12 @@ package body Bindo.Diagnostics is
-- taking into account the predecessors and successors involved, as -- taking into account the predecessors and successors involved, as
-- well as the nature of the edge. -- well as the nature of the edge.
Elaborate_All_Active :=
Elaborate_All_Active
or else Is_Elaborate_All_Edge
(G => Lib_Graph,
Edge => Current_Edge);
Output_Transition Output_Transition
(Inv_Graph => Inv_Graph, (Inv_Graph => Inv_Graph,
Lib_Graph => Lib_Graph, Lib_Graph => Lib_Graph,
...@@ -533,12 +539,12 @@ package body Bindo.Diagnostics is ...@@ -533,12 +539,12 @@ package body Bindo.Diagnostics is
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Cycle)); pragma Assert (Present (Cycle));
-- The cycle contains at least one invocation edge and the main library -- The cycle contains at least one invocation edge where the successor
-- unit was compiled with the static model. Using the dynamic model may -- was statically elaborated. Using the dynamic model may eliminate an
-- eliminate the invocation edge, and thus the cycle. -- invocation edge, and thus the cycle.
if Invocation_Edge_Count (G, Cycle) > 0 if Invocation_Edge_Count (G, Cycle) > 0
and then not Is_Dynamically_Elaborated (G) and then Contains_Weak_Static_Successor (G, Cycle)
then then
Error_Msg_Info Error_Msg_Info
(" use the dynamic elaboration model (compiler switch -gnatE)"); (" use the dynamic elaboration model (compiler switch -gnatE)");
...@@ -703,10 +709,11 @@ package body Bindo.Diagnostics is ...@@ -703,10 +709,11 @@ package body Bindo.Diagnostics is
-- Expected_Destination -- Expected_Destination
else else
pragma Assert (Is_Spec_With_Body (G, Actual_Destination));
pragma Assert (Is_Body_With_Spec (G, Expected_Destination));
pragma Assert pragma Assert
(Proper_Body (G, Actual_Destination) = Expected_Destination); (Is_Elaborate_Body_Pair
(G => G,
Spec_Vertex => Actual_Destination,
Body_Vertex => Expected_Destination));
Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_1 := Name (G, Source);
Error_Msg_Unit_2 := Name (G, Actual_Destination); Error_Msg_Unit_2 := Name (G, Actual_Destination);
...@@ -922,13 +929,11 @@ package body Bindo.Diagnostics is ...@@ -922,13 +929,11 @@ package body Bindo.Diagnostics is
-- Expected_Destination -- Expected_Destination
else else
pragma Assert (Is_Spec_With_Body (G, Actual_Destination));
pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination));
pragma Assert (Is_Body_With_Spec (G, Expected_Destination));
pragma Assert
(Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination));
pragma Assert pragma Assert
(Proper_Body (G, Actual_Destination) = Expected_Destination); (Is_Elaborate_Body_Pair
(G => G,
Spec_Vertex => Actual_Destination,
Body_Vertex => Expected_Destination));
Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_1 := Name (G, Source);
Error_Msg_Unit_2 := Name (G, Actual_Destination); Error_Msg_Unit_2 := Name (G, Actual_Destination);
...@@ -1392,13 +1397,11 @@ package body Bindo.Diagnostics is ...@@ -1392,13 +1397,11 @@ package body Bindo.Diagnostics is
-- Expected_Destination -- Expected_Destination
else else
pragma Assert (Is_Spec_With_Body (G, Actual_Destination));
pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination));
pragma Assert (Is_Body_With_Spec (G, Expected_Destination));
pragma Assert
(Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination));
pragma Assert pragma Assert
(Proper_Body (G, Actual_Destination) = Expected_Destination); (Is_Elaborate_Body_Pair
(G => G,
Spec_Vertex => Actual_Destination,
Body_Vertex => Expected_Destination));
Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_1 := Name (G, Source);
Error_Msg_Unit_2 := Name (G, Actual_Destination); Error_Msg_Unit_2 := Name (G, Actual_Destination);
......
...@@ -46,8 +46,6 @@ use Bindo.Units; ...@@ -46,8 +46,6 @@ use Bindo.Units;
with Bindo.Validators; with Bindo.Validators;
use Bindo.Validators; use Bindo.Validators;
use Bindo.Validators.Elaboration_Order_Validators; use Bindo.Validators.Elaboration_Order_Validators;
use Bindo.Validators.Invocation_Graph_Validators;
use Bindo.Validators.Library_Graph_Validators;
with Bindo.Writers; with Bindo.Writers;
use Bindo.Writers; use Bindo.Writers;
...@@ -76,76 +74,61 @@ package body Bindo.Elaborators is ...@@ -76,76 +74,61 @@ package body Bindo.Elaborators is
---------------------------------------------- ----------------------------------------------
package body Invocation_And_Library_Graph_Elaborators is 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 -- -- Local subprograms --
----------------------- -----------------------
procedure Add_Vertex procedure Create_Component_Vertex_Sets
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; Comp : Component_Id;
Set : LGV_Sets.Membership_Set; Elaborable_Vertices : out LGV_Sets.Membership_Set;
Msg : String; Waiting_Vertices : out LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Step : Elaboration_Order_Step);
Indent : Indentation_Level); pragma Inline (Create_Component_Vertex_Sets);
pragma Inline (Add_Vertex); -- Split all vertices of component Comp of library graph G as follows:
-- 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 -- * Elaborable vertices are added to set Elaborable_Vertices.
-- the elaboration order. Indent is the desired indentation level for --
-- tracing. -- * Vertices that are still waiting on their predecessors to be
-- elaborated are added to set Waiting_Vertices.
procedure Add_Vertex_If_Elaborable --
(G : Library_Graph; -- Step is the current step in the elaboration order.
Vertex : Library_Graph_Vertex_Id;
Set : LGV_Sets.Membership_Set; procedure Create_Vertex_Sets
Msg : String; (G : Library_Graph;
Step : Elaboration_Order_Step; Elaborable_Vertices : out LGV_Sets.Membership_Set;
Indent : Indentation_Level); Waiting_Vertices : out LGV_Sets.Membership_Set;
pragma Inline (Add_Vertex_If_Elaborable); Step : Elaboration_Order_Step);
-- Add vertex Vertex of library graph G to membership set Set if it can pragma Inline (Create_Vertex_Sets);
-- be elaborated. Msg is a message emitted for tracing purposes. Step is -- Split all vertices of library graph G as follows:
-- the current step in the elaboration order. Indent is the desired --
-- indentation level for tracing. -- * Elaborable vertices are added to set Elaborable_Vertices.
--
function Create_All_Candidates_Set -- * Vertices that are still waiting on their predecessors to be
(G : Library_Graph; -- elaborated are added to set Waiting_Vertices.
Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set; --
pragma Inline (Create_All_Candidates_Set); -- Step is the current step in the elaboration order.
-- 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 Elaborate_Component procedure Elaborate_Component
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id; Comp : Component_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Remaining_Vertices : in out Natural; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Order : in out Unit_Id_Table; Order : in out Unit_Id_Table;
Step : Elaboration_Order_Step); Step : Elaboration_Order_Step);
pragma Inline (Elaborate_Component); pragma Inline (Elaborate_Component);
-- Elaborate as many vertices as possible that appear in component -- Elaborate as many vertices as possible that appear in component Comp
-- Comp of library graph G. All_Candidates is the set of all elaborable -- of library graph G. The sets contain vertices arranged as follows:
-- vertices across the whole library graph. Remaining_Vertices is the --
-- number of vertices that remain to be elaborated. Order denotes the -- * All_Elaborable_Vertices - all elaborable vertices in the library
-- elaboration order. Step is the current step in the elaboration order. -- 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 procedure Elaborate_Library_Graph
(G : Library_Graph; (G : Library_Graph;
...@@ -156,81 +139,149 @@ package body Bindo.Elaborators is ...@@ -156,81 +139,149 @@ package body Bindo.Elaborators is
-- the elaboration order. Status is the condition of the elaboration -- the elaboration order. Status is the condition of the elaboration
-- order. -- 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 procedure Elaborate_Vertex
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Remaining_Vertices : in out Natural; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Order : in out Unit_Id_Table; Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Order : in out Unit_Id_Table;
Indent : Indentation_Level); Step : Elaboration_Order_Step;
Indent : Indentation_Level);
pragma Inline (Elaborate_Vertex); pragma Inline (Elaborate_Vertex);
-- Elaborate vertex Vertex of library graph G by adding its unit to -- Elaborate vertex Vertex of library graph G by adding its unit to
-- elaboration order Order. The routine updates awaiting successors -- elaboration order Order. The routine updates awaiting successors
-- where applicable. All_Candidates denotes the set of all elaborable -- where applicable. The sets contain vertices arranged as follows:
-- vertices across the whole library graph. Comp_Candidates is the set --
-- of all elaborable vertices in the component of Vertex. Parameter -- * All_Elaborable_Vertices - all elaborable vertices in the library
-- Remaining_Vertices denotes the number of vertices that remain to -- graph.
-- be elaborated. Step is the current step in the elaboration order. --
-- * 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. -- 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; (G : Library_Graph;
Set : LGV_Sets.Membership_Set; Set : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Step : Elaboration_Order_Step;
Indent : Indentation_Level) return Library_Graph_Vertex_Id; Indent : Indentation_Level) return Library_Graph_Vertex_Id;
pragma Inline (Find_Best_Candidate); pragma Inline (Find_Best_Weakly_Elaborable_Vertex);
-- Find the most suitable vertex of library graph G for elaboration from -- Find the best vertex of library graph G from membership set S that
-- membership set Set. Step denotes the current step in the elaboration -- can be weakly elaborated. Step is the current step in the elaboration
-- order. Indent is the desired indentation level for tracing. -- order. Indent is the desired indentation level for tracing.
function Is_Better_Candidate function Has_Elaborable_Body
(G : Library_Graph; (G : Library_Graph;
Best_Candidate : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id) return Boolean;
New_Candidate : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Has_Elaborable_Body);
pragma Inline (Is_Better_Candidate); -- Determine whether vertex Vertex of library graph G has a body that is
-- Determine whether new candidate vertex New_Candidate of library graph -- elaborable. It is assumed that the vertex has been elaborated.
-- G is a more suitable choice for elaboration compared to the current
-- best candidate Best_Candidate. 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 function Is_Better_Elaborable_Vertex
(G : Library_Graph; (G : Library_Graph;
Set : LGV_Sets.Membership_Set; Vertex : Library_Graph_Vertex_Id;
Step : Elaboration_Order_Step); Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind;
pragma Inline (Trace_Candidate_Vertices); pragma Inline (Is_Better_Elaborable_Vertex);
-- Write the candidate vertices of library graph G present in membership -- Determine whether vertex Vertex of library graph G is a better choice
-- set Set to standard output. Formal Step denotes the current step in -- for elaboration compared to vertex Compared_To.
-- the elaboration order.
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 procedure Trace_Component
(G : Library_Graph; (G : Library_Graph;
...@@ -246,15 +297,6 @@ package body Bindo.Elaborators is ...@@ -246,15 +297,6 @@ package body Bindo.Elaborators is
pragma Inline (Trace_Step); pragma Inline (Trace_Step);
-- Write current step Step of the elaboration order to standard output -- 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 procedure Trace_Vertex
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
...@@ -267,220 +309,202 @@ package body Bindo.Elaborators is ...@@ -267,220 +309,202 @@ package body Bindo.Elaborators is
-- current step in the elaboration order. Indent denotes the desired -- current step in the elaboration order. Indent denotes the desired
-- indentation level for tracing. -- 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 procedure Update_Successor
(G : Library_Graph; (G : Library_Graph;
Pred : Library_Graph_Vertex_Id; Edge : Library_Graph_Edge_Id;
Succ : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
All_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Indent : Indentation_Level); Step : Elaboration_Order_Step;
Indent : Indentation_Level);
pragma Inline (Update_Successor); pragma Inline (Update_Successor);
-- Notify successor vertex Succ of library graph G along with its -- Notify the successor of edge Edge of library graph G along with its
-- component that their predecessor Pred has just been elaborated. -- component that their predecessor has just been elaborated. This may
-- This may cause new vertices to become elaborable, and thus be added -- cause new vertices to become elaborable. The sets contain vertices
-- to one of the two sets. All_Candidates is the set of all elaborable -- arranged as follows:
-- vertices across the whole library graph. Comp_Candidates is the set --
-- of all elaborable vertices in the component of Pred. Step is the -- * All_Elaborable_Vertices - all elaborable vertices in the library
-- current step in the elaboration order. Indent denotes the desired -- graph.
-- indentation level for tracing. --
-- * 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 procedure Update_Successors
(G : Library_Graph; (G : Library_Graph;
Pred : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Indent : Indentation_Level); Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step;
Indent : Indentation_Level);
pragma Inline (Update_Successors); pragma Inline (Update_Successors);
-- Notify all successors along with their components that their -- Notify all successors of vertex Vertex of library graph G along with
-- predecessor vertex Pred of ligrary graph G has just been elaborated. -- their components that their predecessor has just been elaborated.
-- This may cause new vertices to become elaborable, and thus be added -- This may cause new vertices to become elaborable. The sets contain
-- to one of the two sets. All_Candidates is the set of all elaborable -- vertices arranged as follows:
-- vertices across the whole library graph. Comp_Candidates is the set --
-- of all elaborable vertices in the component of Pred. Step is the -- * All_Elaborable_Vertices - all elaborable vertices in the library
-- current step in the elaboration order. Indent denotes the desired -- graph.
-- indentation level for tracing. --
-- * All_Waiting_Vertices - all vertices in the library graph that are
---------------- -- waiting on predecessors to be elaborated.
-- Add_Vertex -- --
---------------- -- * Comp_Elaborable_Vertices - all elaborable vertices found in the
-- component of Vertex.
procedure Add_Vertex --
(G : Library_Graph; -- * Comp_Waiting_Vertices - all vertices found in the component of
Vertex : Library_Graph_Vertex_Id; -- Vertex that are still waiting on predecessors to be elaborated.
Set : LGV_Sets.Membership_Set; --
Msg : String; -- Step is the current step in the elaboration order. Indent denotes the
Step : Elaboration_Order_Step; -- desired indentation level for tracing.
Indent : Indentation_Level)
----------------------------------
-- 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 is
begin pragma Assert (Present (G));
pragma Assert (Present (Vertex)); pragma Assert (Present (Comp));
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;
------------------------------ Num_Of_Vertices : constant Natural :=
-- Add_Vertex_If_Elaborable -- Number_Of_Component_Vertices (G, Comp);
------------------------------
procedure Add_Vertex_If_Elaborable Iter : Component_Vertex_Iterator;
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; 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 begin
pragma Assert (Present (G)); Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices);
pragma Assert (Present (Vertex)); Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices);
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
Extra_Vertex := No_Library_Graph_Vertex; Iter := Iterate_Component_Vertices (G, Comp);
while Has_Next (Iter) loop
-- A spec-body pair where the spec carries pragma Elaborate_Body Next (Iter, Vertex);
-- 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));
elsif Is_Spec_With_Elaborate_Body (G, Vertex) then -- Add the vertex to the proper set depending on whether it can be
Extra_Vertex := Proper_Body (G, Vertex); -- elaborated.
pragma Assert (Present (Extra_Vertex));
end if;
if Present (Extra_Vertex) then if Is_Elaborable_Vertex (G, Vertex) then
pragma Assert (Needs_Elaboration (G, Extra_Vertex)); 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, (G => G,
Vertex => Extra_Vertex, Vertex => Vertex,
Set => Set, Set => Waiting_Vertices,
Msg => Msg, Msg => "add waiting component vertex",
Step => Step, Step => Step,
Indent => Indent); Indent => No_Indentation);
end if; end if;
end if; end loop;
end Add_Vertex_If_Elaborable; end Create_Component_Vertex_Sets;
------------------------------- ------------------------
-- Create_All_Candidates_Set -- -- Create_Vertex_Sets --
------------------------------- ------------------------
function Create_All_Candidates_Set procedure Create_Vertex_Sets
(G : Library_Graph; (G : Library_Graph;
Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set Elaborable_Vertices : out LGV_Sets.Membership_Set;
Waiting_Vertices : out LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step)
is is
pragma Assert (Present (G));
Num_Of_Vertices : constant Natural := Number_Of_Vertices (G);
Iter : Library_Graphs.All_Vertex_Iterator; Iter : Library_Graphs.All_Vertex_Iterator;
Set : LGV_Sets.Membership_Set;
Vertex : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
begin 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); Iter := Iterate_All_Vertices (G);
while Has_Next (Iter) loop while Has_Next (Iter) loop
Next (Iter, Vertex); Next (Iter, Vertex);
Add_Vertex_If_Elaborable -- Add the vertex to the proper set depending on whether it can be
(G => G, -- elaborated.
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));
Set := LGV_Sets.Create (Number_Of_Component_Vertices (G, Comp)); if Is_Elaborable_Vertex (G, Vertex) then
Iter := Iterate_Component_Vertices (G, Comp); Insert_Vertex
while Has_Next (Iter) loop (G => G,
Next (Iter, Vertex); Vertex => Vertex,
Set => Elaborable_Vertices,
Msg => "add elaborable vertex",
Step => Step,
Indent => No_Indentation);
Add_Vertex_If_Elaborable else
(G => G, Insert_Vertex
Vertex => Vertex, (G => G,
Set => Set, Vertex => Vertex,
Msg => Add_To_Comp_Candidates_Msg, Set => Waiting_Vertices,
Step => Step, Msg => "add waiting vertex",
Indent => No_Indentation); Step => Step,
Indent => No_Indentation);
end if;
end loop; end loop;
end Create_Vertex_Sets;
return Set;
end Create_Component_Candidates_Set;
------------------------- -------------------------
-- Elaborate_Component -- -- Elaborate_Component --
------------------------- -------------------------
procedure Elaborate_Component procedure Elaborate_Component
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id; Comp : Component_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Remaining_Vertices : in out Natural; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Order : in out Unit_Id_Table; Order : in out Unit_Id_Table;
Step : Elaboration_Order_Step) Step : Elaboration_Order_Step)
is is
Candidate : Library_Graph_Vertex_Id; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Vertex : Library_Graph_Vertex_Id;
begin begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Comp)); 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 Trace_Component
(G => G, (G => G,
...@@ -488,35 +512,81 @@ package body Bindo.Elaborators is ...@@ -488,35 +512,81 @@ package body Bindo.Elaborators is
Msg => "elaborating component", Msg => "elaborating component",
Step => Step); 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 loop
Candidate := Trace_Vertices
Find_Best_Candidate (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, (G => G,
Set => Comp_Candidates, Set => Comp_Elaborable_Vertices,
Step => Step, Step => Step,
Indent => Nested_Indentation); Indent => Nested_Indentation);
-- Stop the elaboration of the component when there is no suitable -- The component lacks an elaborable vertex. This indicates that
-- candidate. This indicates that either all vertices within the -- either all vertices of the component have been elaborated or
-- component have been elaborated, or the library graph contains a -- the graph has a circularity. Locate the best weak vertex that
-- circularity. -- 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 Elaborate_Vertex
(G => G, (G => G,
Vertex => Candidate, Vertex => Vertex,
All_Candidates => All_Candidates, All_Elaborable_Vertices => All_Elaborable_Vertices,
Comp_Candidates => Comp_Candidates, All_Waiting_Vertices => All_Waiting_Vertices,
Remaining_Vertices => Remaining_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
Order => Order, Comp_Waiting_Vertices => Comp_Waiting_Vertices,
Step => Step, Order => Order,
Indent => Nested_Indentation); Step => Step,
Indent => Nested_Indentation);
end loop; end loop;
LGV_Sets.Destroy (Comp_Candidates); LGV_Sets.Destroy (Comp_Elaborable_Vertices);
LGV_Sets.Destroy (Comp_Waiting_Vertices);
end Elaborate_Component; end Elaborate_Component;
----------------------------- -----------------------------
...@@ -528,73 +598,97 @@ package body Bindo.Elaborators is ...@@ -528,73 +598,97 @@ package body Bindo.Elaborators is
Order : out Unit_Id_Table; Order : out Unit_Id_Table;
Status : out Elaboration_Order_Status) Status : out Elaboration_Order_Status)
is is
All_Candidates : LGV_Sets.Membership_Set; Elaborable_Vertices : LGV_Sets.Membership_Set;
Candidate : Library_Graph_Vertex_Id; Step : Elaboration_Order_Step;
Remaining_Vertices : Natural; Vertex : Library_Graph_Vertex_Id;
Step : Elaboration_Order_Step; Waiting_Vertices : LGV_Sets.Membership_Set;
begin begin
pragma Assert (Present (G)); pragma Assert (Present (G));
Step := Initial_Step; Step := Initial_Step;
All_Candidates := Create_All_Candidates_Set (G, Step); -- Divide all vertices of the library graph into an elaborable and
Remaining_Vertices := Number_Of_Vertices (G); -- waiting vertex set.
Create_Vertex_Sets
(G => G,
Elaborable_Vertices => Elaborable_Vertices,
Waiting_Vertices => Waiting_Vertices,
Step => Step);
loop loop
Step := Step + 1; Step := Step + 1;
Trace_Candidate_Vertices Trace_Vertices
(G => G, (G => G,
Set => All_Candidates, Set => Elaborable_Vertices,
Step => Step); Set_Msg => "elaborable vertices",
Vertex_Msg => "elaborable vertex",
Trace_Unelaborated_Vertices Step => Step,
(G => G, Indent => No_Indentation);
Count => Remaining_Vertices,
Step => Step); Trace_Vertices
(G => G,
Candidate := Set => Waiting_Vertices,
Find_Best_Candidate Set_Msg => "waiting vertices",
Vertex_Msg => "waiting vertex",
Step => Step,
Indent => No_Indentation);
Vertex :=
Find_Best_Elaborable_Vertex
(G => G, (G => G,
Set => All_Candidates, Set => Elaborable_Vertices,
Step => Step, Step => Step,
Indent => No_Indentation); Indent => No_Indentation);
-- Stop the elaboration when there is no suitable candidate. This -- The graph lacks an elaborable vertex. This indicates that
-- indicates that either all units were elaborated or the library -- either all vertices have been elaborated or the graph has a
-- graph contains a circularity. -- 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 the component of the vertex by trying to elaborate as
-- elaborate as many vertices within the component as possible. -- many vertices within the component as possible. Each successful
-- Each successful elaboration signals the appropriate successors -- elaboration signals the appropriate successors and components
-- and their components that they have one less predecessor to -- that they have one less predecessor to wait on.
-- wait on. This may add new candidates to set All_Candidates.
Elaborate_Component Elaborate_Component
(G => G, (G => G,
Comp => Component (G, Candidate), Comp => Component (G, Vertex),
All_Candidates => All_Candidates, All_Elaborable_Vertices => Elaborable_Vertices,
Remaining_Vertices => Remaining_Vertices, All_Waiting_Vertices => Waiting_Vertices,
Order => Order, Order => Order,
Step => Step); Step => Step);
end loop; end loop;
LGV_Sets.Destroy (All_Candidates); -- The graph contains an Elaborate_All circularity when at least one
-- edge subject to the related pragma appears in a component.
-- The library 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 if Has_Elaborate_All_Cycle (G) then
Status := Order_Has_Elaborate_All_Circularity; 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. -- to elaborate.
elsif Remaining_Vertices /= 0 then elsif LGV_Sets.Size (Waiting_Vertices) /= 0 then
Status := Order_Has_Circularity; Status := Order_Has_Circularity;
-- Otherwise the elaboration order is satisfactory -- Otherwise the elaboration order is satisfactory
...@@ -602,6 +696,9 @@ package body Bindo.Elaborators is ...@@ -602,6 +696,9 @@ package body Bindo.Elaborators is
else else
Status := Order_OK; Status := Order_OK;
end if; end if;
LGV_Sets.Destroy (Elaborable_Vertices);
LGV_Sets.Destroy (Waiting_Vertices);
end Elaborate_Library_Graph; end Elaborate_Library_Graph;
--------------------- ---------------------
...@@ -612,271 +709,114 @@ package body Bindo.Elaborators is ...@@ -612,271 +709,114 @@ package body Bindo.Elaborators is
(Order : out Unit_Id_Table; (Order : out Unit_Id_Table;
Main_Lib_File : File_Name_Type) Main_Lib_File : File_Name_Type)
is is
Main_Lib_Unit : constant Unit_Id := pragma Unreferenced (Main_Lib_File);
Corresponding_Unit (Unit_Name_Type (Main_Lib_File));
begin Inv_Graph : Invocation_Graph;
pragma Assert (Present (Main_Lib_Unit)); Lib_Graph : Library_Graph;
Status : Elaboration_Order_Status;
begin
-- Initialize all unit-related data structures and gather all units -- Initialize all unit-related data structures and gather all units
-- that need elaboration. -- that need elaboration.
Initialize_Units; Initialize_Units;
Collect_Elaborable_Units; Collect_Elaborable_Units;
Write_ALI_Tables; -- Create the library graph that captures the dependencies between
-- library items.
-- 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.
if Use_Inv_Graph then Lib_Graph := Build_Library_Graph;
Inv_Graph := Build_Invocation_Graph (Lib_Graph);
Validate_Invocation_Graph (Inv_Graph);
Write_Invocation_Graph (Inv_Graph);
-- Otherwise the invocation graph is not used. Create a dummy graph -- Create the invocation graph that represents the flow of execution
-- as this allows for a uniform behavior on the caller side.
else Inv_Graph := Build_Invocation_Graph (Lib_Graph);
Inv_Graph :=
Invocation_Graphs.Create
(Initial_Vertices => 1,
Initial_Edges => 1);
end if;
-- Traverse the invocation graph starting from elaboration code in -- Traverse the invocation graph starting from elaboration code in
-- order to discover transitions of the execution flow from a unit -- order to discover transitions of the execution flow from a unit
-- to a unit that result in extra edges within the library graph. -- to a unit that result in extra edges within the library graph.
Augment_Library_Graph (Inv_Graph, Lib_Graph); Augment_Library_Graph (Inv_Graph, Lib_Graph);
Write_Library_Graph (Lib_Graph);
-- Create and output the component graph by collapsing all library -- Create the component graph by collapsing all library items into
-- items into library units and traversing the library graph. -- library units and traversing the library graph.
Find_Components (Lib_Graph); Find_Components (Lib_Graph);
Write_Components (Lib_Graph);
-- Traverse the library graph to determine the elaboration order of -- Output the contents of the ALI tables and both graphs to standard
-- units. -- output now that they have been fully decorated.
Elaborate_Library_Graph Write_ALI_Tables;
(G => Lib_Graph, Write_Invocation_Graph (Inv_Graph);
Order => Order, Write_Library_Graph (Lib_Graph);
Status => Status);
end Elaborate_Units_Common;
-----------------------------
-- Elaborate_Units_Dynamic --
-----------------------------
procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table) is -- Traverse the library graph to determine the elaboration order of
Dyn_Inv_Graph : Invocation_Graph; -- units.
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;
begin Elaborate_Library_Graph (Lib_Graph, Order, Status);
-- 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);
-- The elaboration order is satisfactory -- The elaboration order is satisfactory
if Status = Order_OK then 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. -- complete list of elaboration order dependencies) is active.
Write_Dependencies (Mix_Lib_Graph); Write_Dependencies (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;
---------------------------- -- Output the elaboration order when switch -l (output chosen
-- Elaborate_Units_Static -- -- elaboration order) is in effect.
----------------------------
procedure Elaborate_Units_Static (Order : out Unit_Id_Table) is Write_Elaboration_Order (Order);
Inv_Graph : Invocation_Graph;
Lib_Graph : Library_Graph;
Status : Elaboration_Order_Status;
begin -- Output the sources referenced in the closure of the order when
-- Attempt to elaborate the units in the library graph by mixing in -- switch -R (list sources referenced in closure) is in effect.
-- 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.
if Status = Order_OK then Write_Unit_Closure (Order);
Write_Dependencies (Lib_Graph);
-- Otherwise the augmented library graph contains a circularity -- Otherwise the library graph contains at least one circularity
else else
Diagnose_Circularities Diagnose_Circularities (Inv_Graph, Lib_Graph);
(Inv_Graph => Inv_Graph,
Lib_Graph => Lib_Graph);
end if; end if;
Destroy (Inv_Graph); Destroy (Inv_Graph);
Destroy (Lib_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 if Status /= Order_OK then
raise Unrecoverable_Error; raise Unrecoverable_Error;
end if; end if;
end Elaborate_Units_Static; end Elaborate_Units;
---------------------- ----------------------
-- Elaborate_Vertex -- -- Elaborate_Vertex --
---------------------- ----------------------
procedure Elaborate_Vertex procedure Elaborate_Vertex
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Remaining_Vertices : in out Natural; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Order : in out Unit_Id_Table; Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Order : in out Unit_Id_Table;
Indent : Indentation_Level) Step : Elaboration_Order_Step;
Indent : Indentation_Level)
is is
begin begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Vertex)); pragma Assert (Present (Vertex));
pragma Assert (Needs_Elaboration (G, Vertex)); pragma Assert (Needs_Elaboration (G, Vertex));
pragma Assert (LGV_Sets.Present (All_Candidates)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
pragma Assert (LGV_Sets.Present (Comp_Candidates)); 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 Trace_Vertex
(G => G, (G => G,
...@@ -885,14 +825,20 @@ package body Bindo.Elaborators is ...@@ -885,14 +825,20 @@ package body Bindo.Elaborators is
Step => Step, Step => Step,
Indent => Indent); 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, -- the vertex is both an overall best candidate among all vertices,
-- and the best candidate within the component. There is no need to -- and the best candidate within the component.
-- check that the vertex is present in either set because the set
-- implementation handles this case. LGV_Sets.Delete (All_Elaborable_Vertices, Vertex);
LGV_Sets.Delete (Comp_Elaborable_Vertices, Vertex);
LGV_Sets.Delete (All_Candidates, Vertex); -- Remove the vertex from both waiting sets. This is needed when a
LGV_Sets.Delete (Comp_Candidates, Vertex); -- 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 -- Mark the vertex as elaborated in order to prevent further attempts
-- to re-elaborate it. -- to re-elaborate it.
...@@ -903,202 +849,469 @@ package body Bindo.Elaborators is ...@@ -903,202 +849,469 @@ package body Bindo.Elaborators is
Unit_Id_Tables.Append (Order, Unit (G, Vertex)); 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 -- Notify all successors and their components that they have one
-- fewer predecessor to wait on. This may cause some successors to -- fewer predecessor to wait on. This may cause some successors to
-- be included in one of the sets. -- be included in one of the sets.
Update_Successors Update_Successors
(G => G, (G => G,
Pred => Vertex, Vertex => Vertex,
All_Candidates => All_Candidates, All_Elaborable_Vertices => All_Elaborable_Vertices,
Comp_Candidates => Comp_Candidates, All_Waiting_Vertices => All_Waiting_Vertices,
Step => Step, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
Indent => Indent + Nested_Indentation); Comp_Waiting_Vertices => Comp_Waiting_Vertices,
Step => Step,
-- The vertex denotes a spec with a completing body, and is subject Indent => Indent + Nested_Indentation);
-- to pragma Elaborate_Body. Elaborate the body in order to satisfy
-- the semantics of the pragma. -- Elaborate an eligible completing body immediately after its spec.
-- This action satisfies the semantics of pragma Elaborate_Body. In
if Is_Spec_With_Elaborate_Body (G, Vertex) then -- 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 Elaborate_Vertex
(G => G, (G => G,
Vertex => Proper_Body (G, Vertex), Vertex => Proper_Body (G, Vertex),
All_Candidates => All_Candidates, All_Elaborable_Vertices => All_Elaborable_Vertices,
Comp_Candidates => Comp_Candidates, All_Waiting_Vertices => All_Waiting_Vertices,
Remaining_Vertices => Remaining_Vertices, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
Order => Order, Comp_Waiting_Vertices => Comp_Waiting_Vertices,
Step => Step, Order => Order,
Indent => Indent); Step => Step,
Indent => Indent);
end if; end if;
end Elaborate_Vertex; end Elaborate_Vertex;
------------------------- ---------------------------------
-- Find_Best_Candidate -- -- Find_Best_Elaborable_Vertex --
------------------------- ---------------------------------
function Find_Best_Candidate function Find_Best_Elaborable_Vertex
(G : Library_Graph; (G : Library_Graph;
Set : LGV_Sets.Membership_Set; Set : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Step : Elaboration_Order_Step;
Indent : Indentation_Level) return Library_Graph_Vertex_Id Indent : Indentation_Level) return Library_Graph_Vertex_Id
is is
Best : Library_Graph_Vertex_Id; begin
Current : Library_Graph_Vertex_Id; pragma Assert (Present (G));
Iter : LGV_Sets.Iterator; 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 begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (LGV_Sets.Present (Set)); pragma Assert (LGV_Sets.Present (Set));
pragma Assert (Is_Suitable_Vertex /= null);
pragma Assert (Compare_Vertices /= null);
-- Assume that there is no candidate -- 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 -- Inspect all vertices in the set, looking for the best candidate
-- elaborate. -- according to the comparator.
Iter := LGV_Sets.Iterate (Set); Iter := LGV_Sets.Iterate (Set);
while LGV_Sets.Has_Next (Iter) loop while LGV_Sets.Has_Next (Iter) loop
LGV_Sets.Next (Iter, Current); LGV_Sets.Next (Iter, Current_Vertex);
pragma Assert (Needs_Elaboration (G, Current)); 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 function Find_Best_Weakly_Elaborable_Vertex
(G => G, (G : Library_Graph;
Vertex => Best, Set : LGV_Sets.Membership_Set;
Msg => "initial best candidate vertex", Step : Elaboration_Order_Step;
Step => Step, Indent : Indentation_Level) return Library_Graph_Vertex_Id
Indent => Indent); is
begin
pragma Assert (Present (G));
pragma Assert (LGV_Sets.Present (Set));
-- Update the best candidate when the current vertex is a better return
-- choice. 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, -- Has_Elaborable_Body --
Best_Candidate => Best, -------------------------
New_Candidate => Current)
then
Best := Current;
Trace_Vertex function Has_Elaborable_Body
(G => G, (G : Library_Graph;
Vertex => Best, Vertex : Library_Graph_Vertex_Id) return Boolean
Msg => "best candidate vertex", is
Step => Step, begin
Indent => Indent); pragma Assert (Present (G));
end if; pragma Assert (Present (Vertex));
end loop;
return Best; -- The body of an already-elaborated spec subject to Elaborate_Body
end Find_Best_Candidate; -- is always elaborable.
------------------------- if Is_Spec_With_Elaborate_Body (G, Vertex) then
-- Is_Better_Candidate -- 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 if LGV_Sets.Contains (Set, Vertex) then
(G : Library_Graph; return;
Best_Candidate : Library_Graph_Vertex_Id; end if;
New_Candidate : Library_Graph_Vertex_Id) return Boolean
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 is
begin begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Best_Candidate)); pragma Assert (Present (Vertex));
pragma Assert (Present (New_Candidate)); 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 -- Prefer a predefined unit over a non-predefined unit
if Is_Predefined_Unit (G, Best_Candidate) elsif Is_Predefined_Unit (G, Vertex)
and then not Is_Predefined_Unit (G, New_Candidate) and then not Is_Predefined_Unit (G, Compared_To)
then then
return False; return Higher_Precedence;
elsif not Is_Predefined_Unit (G, Best_Candidate) elsif not Is_Predefined_Unit (G, Vertex)
and then Is_Predefined_Unit (G, New_Candidate) and then Is_Predefined_Unit (G, Compared_To)
then 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) elsif Is_Internal_Unit (G, Vertex)
and then not Is_Internal_Unit (G, New_Candidate) and then not Is_Internal_Unit (G, Compared_To)
then then
return False; return Higher_Precedence;
elsif not Is_Internal_Unit (G, Best_Candidate) elsif not Is_Internal_Unit (G, Vertex)
and then Is_Internal_Unit (G, New_Candidate) and then Is_Internal_Unit (G, Compared_To)
then then
return True; return Lower_Precedence;
-- Prefer a preelaborated unit over a non-preelaborated unit -- Prefer a preelaborated unit over a non-preelaborated unit
elsif Is_Preelaborated_Unit (G, Best_Candidate) elsif Is_Preelaborated_Unit (G, Vertex)
and then not Is_Preelaborated_Unit (G, New_Candidate) and then not Is_Preelaborated_Unit (G, Compared_To)
then then
return False; return Higher_Precedence;
elsif not Is_Preelaborated_Unit (G, Best_Candidate) elsif not Is_Preelaborated_Unit (G, Vertex)
and then Is_Preelaborated_Unit (G, New_Candidate) and then Is_Preelaborated_Unit (G, Compared_To)
then then
return True; return Lower_Precedence;
-- Otherwise default to lexicographical order to ensure deterministic -- Otherwise default to lexicographical order to ensure deterministic
-- behavior. -- behavior.
elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then
return Higher_Precedence;
else else
return return Lower_Precedence;
Uname_Less (Name (G, Best_Candidate), Name (G, New_Candidate));
end if; end if;
end Is_Better_Candidate; end Is_Better_Elaborable_Vertex;
------------------------------ ----------------------------------------
-- Trace_Candidate_Vertices -- -- Is_Better_Weakly_Elaborable_Vertex --
------------------------------ ----------------------------------------
procedure Trace_Candidate_Vertices function Is_Better_Weakly_Elaborable_Vertex
(G : Library_Graph; (G : Library_Graph;
Set : LGV_Sets.Membership_Set; Vertex : Library_Graph_Vertex_Id;
Step : Elaboration_Order_Step) Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind
is is
Iter : LGV_Sets.Iterator; Comp_Strong_Preds : Natural;
Vertex : Library_Graph_Vertex_Id; Comp_Weak_Preds : Natural;
Vertex_Strong_Preds : Natural;
Vertex_Weak_Preds : Natural;
begin begin
pragma Assert (Present (G)); 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 -- Obtain the number of pending predecessors for both candidates,
-- detection trace information) is not in effect. -- taking into account Elaborate_Body pairs.
if not Debug_Flag_Underscore_TT then Pending_Predecessors_For_Elaboration
return; (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 if;
end Is_Better_Weakly_Elaborable_Vertex;
Trace_Step (Step); -----------------------------------
Write_Str ("candidate vertices: "); -- Is_Suitable_Elaborable_Vertex --
Write_Int (Int (LGV_Sets.Size (Set))); -----------------------------------
Write_Eol;
Iter := LGV_Sets.Iterate (Set); function Is_Suitable_Elaborable_Vertex
while LGV_Sets.Has_Next (Iter) loop (G : Library_Graph;
LGV_Sets.Next (Iter, Vertex); Vertex : Library_Graph_Vertex_Id) return Boolean
is
begin
pragma Assert (Present (G));
pragma Assert (Present (Vertex));
Trace_Vertex -- A vertex is suitable for elaboration as long it is not waiting on
(G => G, -- any predecessors, ignoring the static or dynamic model.
Vertex => Vertex,
Msg => "candidate vertex", return Is_Elaborable_Vertex (G, Vertex);
Step => Step, end Is_Suitable_Elaborable_Vertex;
Indent => Nested_Indentation);
end loop; ------------------------------------------
end Trace_Candidate_Vertices; -- 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_Component --
...@@ -1130,8 +1343,14 @@ package body Bindo.Elaborators is ...@@ -1130,8 +1343,14 @@ package body Bindo.Elaborators is
Trace_Step (Step); Trace_Step (Step);
Indent_By (Nested_Indentation); Indent_By (Nested_Indentation);
Write_Str ("pending predecessors: "); Write_Str ("pending strong predecessors: ");
Write_Num (Int (Pending_Predecessors (G, Comp))); 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; Write_Eol;
end Trace_Component; end Trace_Component;
...@@ -1154,50 +1373,6 @@ package body Bindo.Elaborators is ...@@ -1154,50 +1373,6 @@ package body Bindo.Elaborators is
Write_Str (": "); Write_Str (": ");
end Trace_Step; 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_Vertex --
------------------ ------------------
...@@ -1247,37 +1422,104 @@ package body Bindo.Elaborators is ...@@ -1247,37 +1422,104 @@ package body Bindo.Elaborators is
Trace_Step (Step); Trace_Step (Step);
Indent_By (Attr_Indent); Indent_By (Attr_Indent);
Write_Str ("pending predecessors: "); Write_Str ("pending strong predecessors: ");
Write_Num (Int (Pending_Predecessors (G, Vertex))); 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; Write_Eol;
Trace_Step (Step); Trace_Step (Step);
Indent_By (Attr_Indent); Indent_By (Attr_Indent);
Write_Str ("pending components : "); Write_Str ("pending strong components : ");
Write_Num (Int (Pending_Predecessors (G, Comp))); 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; Write_Eol;
end Trace_Vertex; 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 -- -- Update_Successor --
---------------------- ----------------------
procedure Update_Successor procedure Update_Successor
(G : Library_Graph; (G : Library_Graph;
Pred : Library_Graph_Vertex_Id; Edge : Library_Graph_Edge_Id;
Succ : Library_Graph_Vertex_Id; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
All_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Indent : Indentation_Level) Step : Elaboration_Order_Step;
Indent : Indentation_Level)
is is
pragma Assert (Present (G)); 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 (Needs_Elaboration (G, Pred));
pragma Assert (Present (Succ));
pragma Assert (Needs_Elaboration (G, 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 := In_Different_Components : constant Boolean :=
not In_Same_Component not In_Same_Component
...@@ -1289,10 +1531,8 @@ package body Bindo.Elaborators is ...@@ -1289,10 +1531,8 @@ package body Bindo.Elaborators is
Vertex_Indent : constant Indentation_Level := Vertex_Indent : constant Indentation_Level :=
Indent + Nested_Indentation; Indent + Nested_Indentation;
Candidate : Library_Graph_Vertex_Id; Iter : Component_Vertex_Iterator;
Iter : Component_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id;
Msg : String_Ptr;
Set : LGV_Sets.Membership_Set;
begin begin
Trace_Vertex Trace_Vertex
...@@ -1305,45 +1545,61 @@ package body Bindo.Elaborators is ...@@ -1305,45 +1545,61 @@ package body Bindo.Elaborators is
-- Notify the successor that it has one less predecessor to wait on. -- Notify the successor that it has one less predecessor to wait on.
-- This effectively eliminates the edge that links the two. -- 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. -- The predecessor and successor reside in different components.
-- Notify the successor component it has one fewer components to -- Notify the successor component it has one fewer components to
-- wait on. -- wait on.
if In_Different_Components then if In_Different_Components then
Decrement_Pending_Predecessors (G, Succ_Comp); Decrement_Pending_Predecessors
(G => G,
Comp => Succ_Comp,
Edge => Edge);
end if; end if;
-- At this point the successor may become elaborable when its final -- At this point the successor may become elaborable when its final
-- predecessor or final predecessor component is elaborated. -- predecessor or final predecessor component has been elaborated.
-- The predecessor and successor reside in different components. if Is_Elaborable_Vertex (G, Succ) then
-- The successor must not be added to the candidates of Pred's
-- component because this will mix units from the two components. -- The predecessor and successor reside in different components.
-- Instead, the successor is added to the set of all candidates -- The successor must not be added to the candidates of Pred's
-- that must be elaborated. -- 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 else
Msg := Add_To_All_Candidates_Msg'Access; Insert_Elaborable_Successor
Set := All_Candidates; (G => G,
Vertex => Succ,
-- Otherwise the predecessor and successor reside within the same Elaborable_Vertices => Comp_Elaborable_Vertices,
-- component. Pred's component gains another elaborable node. All_Waiting_Vertices => All_Waiting_Vertices,
Comp_Waiting_Vertices => Comp_Waiting_Vertices,
else Msg =>
Msg := Add_To_Comp_Candidates_Msg'Access; "add elaborable component successor",
Set := Comp_Candidates; Step => Step,
Indent => Vertex_Indent);
end if;
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 -- At this point the successor component may become elaborable when
-- its final predecessor component is elaborated. This in turn may -- its final predecessor component is elaborated. This in turn may
-- allow vertices of the successor component to be elaborated. -- allow vertices of the successor component to be elaborated.
...@@ -1353,15 +1609,19 @@ package body Bindo.Elaborators is ...@@ -1353,15 +1609,19 @@ package body Bindo.Elaborators is
then then
Iter := Iterate_Component_Vertices (G, Succ_Comp); Iter := Iterate_Component_Vertices (G, Succ_Comp);
while Has_Next (Iter) loop while Has_Next (Iter) loop
Next (Iter, Candidate); Next (Iter, Vertex);
Add_Vertex_If_Elaborable if Is_Elaborable_Vertex (G, Vertex) then
(G => G, Insert_Elaborable_Successor
Vertex => Candidate, (G => G,
Set => All_Candidates, Vertex => Vertex,
Msg => Add_To_All_Candidates_Msg, Elaborable_Vertices => All_Elaborable_Vertices,
Step => Step, All_Waiting_Vertices => All_Waiting_Vertices,
Indent => Vertex_Indent); Comp_Waiting_Vertices => Comp_Waiting_Vertices,
Msg => "add elaborable vertex",
Step => Step,
Indent => Vertex_Indent);
end if;
end loop; end loop;
end if; end if;
end Update_Successor; end Update_Successor;
...@@ -1371,36 +1631,41 @@ package body Bindo.Elaborators is ...@@ -1371,36 +1631,41 @@ package body Bindo.Elaborators is
----------------------- -----------------------
procedure Update_Successors procedure Update_Successors
(G : Library_Graph; (G : Library_Graph;
Pred : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
All_Candidates : LGV_Sets.Membership_Set; All_Elaborable_Vertices : LGV_Sets.Membership_Set;
Comp_Candidates : LGV_Sets.Membership_Set; All_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step; Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
Indent : Indentation_Level) Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
Step : Elaboration_Order_Step;
Indent : Indentation_Level)
is is
Edge : Library_Graph_Edge_Id; Edge : Library_Graph_Edge_Id;
Iter : Edges_To_Successors_Iterator; Iter : Edges_To_Successors_Iterator;
begin begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Pred)); pragma Assert (Present (Vertex));
pragma Assert (Needs_Elaboration (G, Pred)); pragma Assert (Needs_Elaboration (G, Vertex));
pragma Assert (LGV_Sets.Present (All_Candidates)); pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
pragma Assert (LGV_Sets.Present (Comp_Candidates)); 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 while Has_Next (Iter) loop
Next (Iter, Edge); Next (Iter, Edge);
pragma Assert (Predecessor (G, Edge) = Pred); pragma Assert (Predecessor (G, Edge) = Vertex);
Update_Successor Update_Successor
(G => G, (G => G,
Pred => Pred, Edge => Edge,
Succ => Successor (G, Edge), All_Elaborable_Vertices => All_Elaborable_Vertices,
All_Candidates => All_Candidates, All_Waiting_Vertices => All_Waiting_Vertices,
Comp_Candidates => Comp_Candidates, Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
Step => Step, Comp_Waiting_Vertices => Comp_Waiting_Vertices,
Indent => Indent); Step => Step,
Indent => Indent);
end loop; end loop;
end Update_Successors; end Update_Successors;
end Invocation_And_Library_Graph_Elaborators; end Invocation_And_Library_Graph_Elaborators;
......
...@@ -205,7 +205,7 @@ package body Bindo.Graphs is ...@@ -205,7 +205,7 @@ package body Bindo.Graphs is
(G : Invocation_Graph; (G : Invocation_Graph;
Rel : Source_Target_Relation) return Boolean; Rel : Source_Target_Relation) return Boolean;
pragma Inline (Is_Existing_Source_Target_Relation); 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. -- relation Rel are already related in invocation graph G.
procedure Save_Elaboration_Root procedure Save_Elaboration_Root
...@@ -226,7 +226,7 @@ package body Bindo.Graphs is ...@@ -226,7 +226,7 @@ package body Bindo.Graphs is
Rel : Source_Target_Relation; Rel : Source_Target_Relation;
Val : Boolean := True); Val : Boolean := True);
pragma Inline (Set_Is_Existing_Source_Target_Relation); 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. -- already related in invocation graph G depending on value Val.
procedure Set_IGE_Attributes procedure Set_IGE_Attributes
...@@ -1026,18 +1026,6 @@ package body Bindo.Graphs is ...@@ -1026,18 +1026,6 @@ package body Bindo.Graphs is
package body Library_Graphs is 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 -- -- Local subprograms --
----------------------- -----------------------
...@@ -1064,7 +1052,7 @@ package body Bindo.Graphs is ...@@ -1064,7 +1052,7 @@ package body Bindo.Graphs is
Attrs : Library_Graph_Cycle_Attributes; Attrs : Library_Graph_Cycle_Attributes;
Indent : Indentation_Level); Indent : Indentation_Level);
pragma Inline (Add_Cycle); 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 -- unless a prior rotation of it already exists. The edges of the cycle
-- must be in normalized form. Indent is the desired indentation level -- must be in normalized form. Indent is the desired indentation level
-- for tracing. -- for tracing.
...@@ -1090,15 +1078,6 @@ package body Bindo.Graphs is ...@@ -1090,15 +1078,6 @@ package body Bindo.Graphs is
-- part of an Elaborate_Body pair, or flag Do_Complement is set, add -- part of an Elaborate_Body pair, or flag Do_Complement is set, add
-- the complementary vertex to the set. -- 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 function Copy_Cycle_Path
(Cycle_Path : LGE_Lists.Doubly_Linked_List) (Cycle_Path : LGE_Lists.Doubly_Linked_List)
return LGE_Lists.Doubly_Linked_List; return LGE_Lists.Doubly_Linked_List;
...@@ -1228,17 +1207,21 @@ package body Bindo.Graphs is ...@@ -1228,17 +1207,21 @@ package body Bindo.Graphs is
procedure Increment_Pending_Predecessors procedure Increment_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id); Comp : Component_Id;
Edge : Library_Graph_Edge_Id);
pragma Inline (Increment_Pending_Predecessors); pragma Inline (Increment_Pending_Predecessors);
-- Increment the number of pending precedessors component Comp of -- Increment the number of pending predecessors component Comp which was
-- library graph G must wait on before it can be elaborated by one. -- reached via edge Edge of library graph G must wait on before it can
-- be elaborated by one.
procedure Increment_Pending_Predecessors procedure Increment_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id); Vertex : Library_Graph_Vertex_Id;
Edge : Library_Graph_Edge_Id);
pragma Inline (Increment_Pending_Predecessors); pragma Inline (Increment_Pending_Predecessors);
-- Increment the number of pending precedessors vertex Vertex of library -- Increment the number of pending predecessors vertex Vertex which was
-- graph G must wait on before it can be elaborated by one. -- reached via edge Edge of library graph G must wait on before it can
-- be elaborated by one.
procedure Initialize_Components (G : Library_Graph); procedure Initialize_Components (G : Library_Graph);
pragma Inline (Initialize_Components); pragma Inline (Initialize_Components);
...@@ -1306,22 +1289,14 @@ package body Bindo.Graphs is ...@@ -1306,22 +1289,14 @@ package body Bindo.Graphs is
Edge : Library_Graph_Edge_Id) return Boolean; Edge : Library_Graph_Edge_Id) return Boolean;
pragma Inline (Is_Cyclic_With_Edge); pragma Inline (Is_Cyclic_With_Edge);
-- Determine whether edge Edge of library graph G participates in a -- 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. -- 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 function Is_Recorded_Cycle
(G : Library_Graph; (G : Library_Graph;
Attrs : Library_Graph_Cycle_Attributes) return Boolean; Attrs : Library_Graph_Cycle_Attributes) return Boolean;
pragma Inline (Is_Recorded_Cycle); 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. -- has already been recorded in library graph G.
function Is_Recorded_Edge function Is_Recorded_Edge
...@@ -1329,7 +1304,7 @@ package body Bindo.Graphs is ...@@ -1329,7 +1304,7 @@ package body Bindo.Graphs is
Rel : Predecessor_Successor_Relation) return Boolean; Rel : Predecessor_Successor_Relation) return Boolean;
pragma Inline (Is_Recorded_Edge); pragma Inline (Is_Recorded_Edge);
-- Determine whether a predecessor vertex and a successor vertex -- 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 function Links_Vertices_In_Same_Component
(G : Library_Graph; (G : Library_Graph;
...@@ -1441,7 +1416,7 @@ package body Bindo.Graphs is ...@@ -1441,7 +1416,7 @@ package body Bindo.Graphs is
Rel : Predecessor_Successor_Relation; Rel : Predecessor_Successor_Relation;
Val : Boolean := True); Val : Boolean := True);
pragma Inline (Set_Is_Recorded_Edge); 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. -- relation Rel as already linked depending on value Val.
procedure Set_LGC_Attributes procedure Set_LGC_Attributes
...@@ -1493,6 +1468,16 @@ package body Bindo.Graphs is ...@@ -1493,6 +1468,16 @@ package body Bindo.Graphs is
-- Write the contents of vertex Vertex of library graph G to standard -- Write the contents of vertex Vertex of library graph G to standard
-- output. Indent is the desired indentation level for tracing. -- 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); procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph);
pragma Inline (Update_Pending_Predecessors_Of_Components); pragma Inline (Update_Pending_Predecessors_Of_Components);
-- Update the number of pending predecessors all components of library -- Update the number of pending predecessors all components of library
...@@ -1523,7 +1508,7 @@ package body Bindo.Graphs is ...@@ -1523,7 +1508,7 @@ package body Bindo.Graphs is
pragma Assert (LGE_Lists.Present (Edges)); pragma Assert (LGE_Lists.Present (Edges));
-- A vertex requires a special Body_Before_Spec edge to its -- 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 -- * Body that completes a previous spec
-- --
...@@ -1717,7 +1702,10 @@ package body Bindo.Graphs is ...@@ -1717,7 +1702,10 @@ package body Bindo.Graphs is
-- Update the number of pending predecessors the successor must wait -- Update the number of pending predecessors the successor must wait
-- on before it is elaborated. -- on before it is elaborated.
Increment_Pending_Predecessors (G, Succ); Increment_Pending_Predecessors
(G => G,
Vertex => Succ,
Edge => Edge);
-- Update the edge statistics -- Update the edge statistics
...@@ -1757,10 +1745,12 @@ package body Bindo.Graphs is ...@@ -1757,10 +1745,12 @@ package body Bindo.Graphs is
Set_LGV_Attributes Set_LGV_Attributes
(G => G, (G => G,
Vertex => Vertex, Vertex => Vertex,
Val => (Corresponding_Item => No_Library_Graph_Vertex, Val =>
In_Elaboration_Order => False, (Corresponding_Item => No_Library_Graph_Vertex,
Pending_Predecessors => 0, In_Elaboration_Order => False,
Unit => U_Id)); Pending_Strong_Predecessors => 0,
Pending_Weak_Predecessors => 0,
Unit => U_Id));
-- Associate the unit with its corresponding vertex -- Associate the unit with its corresponding vertex
...@@ -1783,9 +1773,9 @@ package body Bindo.Graphs is ...@@ -1783,9 +1773,9 @@ package body Bindo.Graphs is
Complement : constant Library_Graph_Vertex_Id := Complement : constant Library_Graph_Vertex_Id :=
Complementary_Vertex Complementary_Vertex
(G => G, (G => G,
Vertex => Vertex, Vertex => Vertex,
Do_Complement => Do_Complement); Force_Complement => Do_Complement);
begin begin
LGV_Sets.Insert (Set, Vertex); LGV_Sets.Insert (Set, Vertex);
...@@ -1800,9 +1790,9 @@ package body Bindo.Graphs is ...@@ -1800,9 +1790,9 @@ package body Bindo.Graphs is
-------------------------- --------------------------
function Complementary_Vertex function Complementary_Vertex
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id; Vertex : Library_Graph_Vertex_Id;
Do_Complement : Boolean) return Library_Graph_Vertex_Id Force_Complement : Boolean) return Library_Graph_Vertex_Id
is is
Complement : Library_Graph_Vertex_Id; Complement : Library_Graph_Vertex_Id;
...@@ -1816,7 +1806,7 @@ package body Bindo.Graphs is ...@@ -1816,7 +1806,7 @@ package body Bindo.Graphs is
-- The caller requests the complement explicitly -- The caller requests the complement explicitly
if Do_Complement then if Force_Complement then
Complement := Corresponding_Item (G, Vertex); Complement := Corresponding_Item (G, Vertex);
-- The vertex is a completing body of a spec subject to pragma -- The vertex is a completing body of a spec subject to pragma
...@@ -1850,6 +1840,46 @@ package body Bindo.Graphs is ...@@ -1850,6 +1840,46 @@ package body Bindo.Graphs is
return DG.Component (G.Graph, Vertex); return DG.Component (G.Graph, Vertex);
end Component; 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 -- -- Copy_Cycle_Path --
--------------------- ---------------------
...@@ -1911,15 +1941,12 @@ package body Bindo.Graphs is ...@@ -1911,15 +1941,12 @@ package body Bindo.Graphs is
------------ ------------
function Create function Create
(Initial_Vertices : Positive; (Initial_Vertices : Positive;
Initial_Edges : Positive; Initial_Edges : Positive) return Library_Graph
Dynamically_Elaborated : Boolean) return Library_Graph
is is
G : constant Library_Graph := new Library_Graph_Attributes; G : constant Library_Graph := new Library_Graph_Attributes;
begin begin
G.Dynamically_Elaborated := Dynamically_Elaborated;
G.Component_Attributes := Component_Tables.Create (Initial_Vertices); G.Component_Attributes := Component_Tables.Create (Initial_Vertices);
G.Cycle_Attributes := LGC_Tables.Create (Initial_Vertices); G.Cycle_Attributes := LGC_Tables.Create (Initial_Vertices);
G.Cycles := LGC_Lists.Create; G.Cycles := LGC_Lists.Create;
...@@ -1990,7 +2017,8 @@ package body Bindo.Graphs is ...@@ -1990,7 +2017,8 @@ package body Bindo.Graphs is
procedure Decrement_Pending_Predecessors procedure Decrement_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id) Comp : Component_Id;
Edge : Library_Graph_Edge_Id)
is is
Attrs : Component_Attributes; Attrs : Component_Attributes;
...@@ -1999,7 +2027,13 @@ package body Bindo.Graphs is ...@@ -1999,7 +2027,13 @@ package body Bindo.Graphs is
pragma Assert (Present (Comp)); pragma Assert (Present (Comp));
Attrs := Get_Component_Attributes (G, 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); Set_Component_Attributes (G, Comp, Attrs);
end Decrement_Pending_Predecessors; end Decrement_Pending_Predecessors;
...@@ -2009,7 +2043,8 @@ package body Bindo.Graphs is ...@@ -2009,7 +2043,8 @@ package body Bindo.Graphs is
procedure Decrement_Pending_Predecessors procedure Decrement_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) Vertex : Library_Graph_Vertex_Id;
Edge : Library_Graph_Edge_Id)
is is
Attrs : Library_Graph_Vertex_Attributes; Attrs : Library_Graph_Vertex_Attributes;
...@@ -2018,7 +2053,13 @@ package body Bindo.Graphs is ...@@ -2018,7 +2053,13 @@ package body Bindo.Graphs is
pragma Assert (Present (Vertex)); pragma Assert (Present (Vertex));
Attrs := Get_LGV_Attributes (G, 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); Set_LGV_Attributes (G, Vertex, Attrs);
end Decrement_Pending_Predecessors; end Decrement_Pending_Predecessors;
...@@ -2071,7 +2112,10 @@ package body Bindo.Graphs is ...@@ -2071,7 +2112,10 @@ package body Bindo.Graphs is
-- Update the number of pending predecessors the successor must wait -- Update the number of pending predecessors the successor must wait
-- on before it is elaborated. -- 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 -- Delete the link between the predecessor and successor. This allows
-- for further attempts to link the same predecessor and successor. -- for further attempts to link the same predecessor and successor.
...@@ -2298,9 +2342,9 @@ package body Bindo.Graphs is ...@@ -2298,9 +2342,9 @@ package body Bindo.Graphs is
(G => G, (G => G,
Vertex => Vertex =>
Complementary_Vertex Complementary_Vertex
(G => G, (G => G,
Vertex => Vertex, Vertex => Vertex,
Do_Complement => Spec_And_Body_Together), Force_Complement => Spec_And_Body_Together),
End_Vertices => End_Vertices, End_Vertices => End_Vertices,
Most_Significant_Edge => Most_Significant_Edge, Most_Significant_Edge => Most_Significant_Edge,
Invocation_Edge_Count => Invocation_Edge_Count, Invocation_Edge_Count => Invocation_Edge_Count,
...@@ -2343,7 +2387,7 @@ package body Bindo.Graphs is ...@@ -2343,7 +2387,7 @@ package body Bindo.Graphs is
Trace_Edge (G, Initial_Edge, Indent); Trace_Edge (G, Initial_Edge, Indent);
-- Use a set to represent the end vertices of the cycle. The set is -- 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. -- where a cycle may terminate on either a spec or a body vertex.
End_Vertices := LGV_Sets.Create (2); End_Vertices := LGV_Sets.Create (2);
...@@ -2650,7 +2694,10 @@ package body Bindo.Graphs is ...@@ -2650,7 +2694,10 @@ package body Bindo.Graphs is
U_Rec : Unit_Record renames ALI.Units.Table (U_Id); U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
begin 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; end Has_Elaborate_Body;
-------------- --------------
...@@ -2884,7 +2931,8 @@ package body Bindo.Graphs is ...@@ -2884,7 +2931,8 @@ package body Bindo.Graphs is
procedure Increment_Pending_Predecessors procedure Increment_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id) Comp : Component_Id;
Edge : Library_Graph_Edge_Id)
is is
Attrs : Component_Attributes; Attrs : Component_Attributes;
...@@ -2893,7 +2941,13 @@ package body Bindo.Graphs is ...@@ -2893,7 +2941,13 @@ package body Bindo.Graphs is
pragma Assert (Present (Comp)); pragma Assert (Present (Comp));
Attrs := Get_Component_Attributes (G, 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); Set_Component_Attributes (G, Comp, Attrs);
end Increment_Pending_Predecessors; end Increment_Pending_Predecessors;
...@@ -2903,7 +2957,8 @@ package body Bindo.Graphs is ...@@ -2903,7 +2957,8 @@ package body Bindo.Graphs is
procedure Increment_Pending_Predecessors procedure Increment_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) Vertex : Library_Graph_Vertex_Id;
Edge : Library_Graph_Edge_Id)
is is
Attrs : Library_Graph_Vertex_Attributes; Attrs : Library_Graph_Vertex_Attributes;
...@@ -2912,7 +2967,13 @@ package body Bindo.Graphs is ...@@ -2912,7 +2967,13 @@ package body Bindo.Graphs is
pragma Assert (Present (Vertex)); pragma Assert (Present (Vertex));
Attrs := Get_LGV_Attributes (G, 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); Set_LGV_Attributes (G, Vertex, Attrs);
end Increment_Pending_Predecessors; end Increment_Pending_Predecessors;
...@@ -2925,7 +2986,7 @@ package body Bindo.Graphs is ...@@ -2925,7 +2986,7 @@ package body Bindo.Graphs is
pragma Assert (Present (G)); pragma Assert (Present (G));
-- The graph already contains a set of components. Reinitialize -- 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. -- be computed.
if Number_Of_Components (G) > 0 then if Number_Of_Components (G) > 0 then
...@@ -3216,11 +3277,15 @@ package body Bindo.Graphs is ...@@ -3216,11 +3277,15 @@ package body Bindo.Graphs is
-- Is_Dynamically_Elaborated -- -- 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 begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Vertex));
return G.Dynamically_Elaborated; return Is_Dynamically_Elaborated (Unit (G, Vertex));
end Is_Dynamically_Elaborated; end Is_Dynamically_Elaborated;
----------------------------- -----------------------------
...@@ -3235,12 +3300,14 @@ package body Bindo.Graphs is ...@@ -3235,12 +3300,14 @@ package body Bindo.Graphs is
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Comp)); 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 -- * It is not waiting on strong predecessors, and
-- to be elaborated. -- * 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; end Is_Elaborable_Component;
-------------------------- --------------------------
...@@ -3251,80 +3318,47 @@ package body Bindo.Graphs is ...@@ -3251,80 +3318,47 @@ package body Bindo.Graphs is
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Boolean Vertex : Library_Graph_Vertex_Id) return Boolean
is is
Check_Vertex : Library_Graph_Vertex_Id;
begin
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Vertex)); pragma Assert (Present (Vertex));
Check_Vertex := Vertex; Complement : constant Library_Graph_Vertex_Id :=
Complementary_Vertex
-- A spec-body pair where the spec carries pragma Elaborate_Body must (G => G,
-- be treated as one vertex for elaboration purposes. Use the spec as Vertex => Vertex,
-- the point of reference for the composite vertex. Force_Complement => False);
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 --
--------------------------
function Is_Elaborable_Vertex Strong_Preds : Natural;
(G : Library_Graph; Weak_Preds : Natural;
Vertex : Library_Graph_Vertex_Id;
Predecessors : Natural) return Boolean
is
Body_Vertex : Library_Graph_Vertex_Id;
begin begin
pragma Assert (Present (G)); -- A vertex is elaborable when:
pragma Assert (Present (Vertex)); --
-- * It has not been elaborated yet, and
-- The vertex must not be re-elaborated once it has been elaborated -- * 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 if In_Elaboration_Order (G, Vertex) then
return False; return False;
-- The vertex must not be waiting on more precedessors than requested elsif Present (Complement)
-- to be elaborated. and then In_Elaboration_Order (G, Complement)
then
elsif Pending_Predecessors (G, Vertex) /= Predecessors then
return False; 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 elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then
return False; 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; 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; end Is_Elaborable_Vertex;
--------------------------- ---------------------------
...@@ -3378,6 +3412,26 @@ package body Bindo.Graphs is ...@@ -3378,6 +3412,26 @@ package body Bindo.Graphs is
return Kind (G, Edge) = Elaborate_Edge; return Kind (G, Edge) = Elaborate_Edge;
end Is_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 -- -- Is_Forced_Edge --
-------------------- --------------------
...@@ -3539,6 +3593,57 @@ package body Bindo.Graphs is ...@@ -3539,6 +3593,57 @@ package body Bindo.Graphs is
and then Has_Elaborate_Body (G, Vertex); and then Has_Elaborate_Body (G, Vertex);
end Is_Spec_With_Elaborate_Body; 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 -- -- Is_With_Edge --
------------------ ------------------
...@@ -4044,11 +4149,72 @@ package body Bindo.Graphs is ...@@ -4044,11 +4149,72 @@ package body Bindo.Graphs is
return Get_LGC_Attributes (G, Cycle).Path; return Get_LGC_Attributes (G, Cycle).Path;
end 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; (G : Library_Graph;
Comp : Component_Id) return Natural Comp : Component_Id) return Natural
is is
...@@ -4056,14 +4222,14 @@ package body Bindo.Graphs is ...@@ -4056,14 +4222,14 @@ package body Bindo.Graphs is
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Comp)); pragma Assert (Present (Comp));
return Get_Component_Attributes (G, Comp).Pending_Predecessors; return Get_Component_Attributes (G, Comp).Pending_Strong_Predecessors;
end Pending_Predecessors; end Pending_Strong_Predecessors;
-------------------------- ---------------------------------
-- Pending_Predecessors -- -- Pending_Strong_Predecessors --
-------------------------- ---------------------------------
function Pending_Predecessors function Pending_Strong_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Natural Vertex : Library_Graph_Vertex_Id) return Natural
is is
...@@ -4071,8 +4237,38 @@ package body Bindo.Graphs is ...@@ -4071,8 +4237,38 @@ package body Bindo.Graphs is
pragma Assert (Present (G)); pragma Assert (Present (G));
pragma Assert (Present (Vertex)); pragma Assert (Present (Vertex));
return Get_LGV_Attributes (G, Vertex).Pending_Predecessors; return Get_LGV_Attributes (G, Vertex).Pending_Strong_Predecessors;
end Pending_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 -- -- Precedence --
...@@ -4306,9 +4502,9 @@ package body Bindo.Graphs is ...@@ -4306,9 +4502,9 @@ package body Bindo.Graphs is
Complement : constant Library_Graph_Vertex_Id := Complement : constant Library_Graph_Vertex_Id :=
Complementary_Vertex Complementary_Vertex
(G => G, (G => G,
Vertex => Vertex, Vertex => Vertex,
Do_Complement => Do_Complement); Force_Complement => Do_Complement);
begin begin
LGV_Sets.Delete (Set, Vertex); LGV_Sets.Delete (Set, Vertex);
...@@ -4702,6 +4898,24 @@ package body Bindo.Graphs is ...@@ -4702,6 +4898,24 @@ package body Bindo.Graphs is
return Get_LGV_Attributes (G, Vertex).Unit; return Get_LGV_Attributes (G, Vertex).Unit;
end 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 -- -- Update_Pending_Predecessors_Of_Components --
----------------------------------------------- -----------------------------------------------
...@@ -4748,7 +4962,10 @@ package body Bindo.Graphs is ...@@ -4748,7 +4962,10 @@ package body Bindo.Graphs is
-- must wait on another predecessor until it can be elaborated. -- must wait on another predecessor until it can be elaborated.
if Pred_Comp /= Succ_Comp then 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 if;
end Update_Pending_Predecessors_Of_Components; end Update_Pending_Predecessors_Of_Components;
end Library_Graphs; end Library_Graphs;
...@@ -4835,7 +5052,7 @@ package body Bindo.Graphs is ...@@ -4835,7 +5052,7 @@ package body Bindo.Graphs is
-------------------------- --------------------------
LGC_Sequencer : Library_Graph_Cycle_Id := First_Library_Graph_Cycle; 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. -- value.
function Sequence_Next_Cycle return Library_Graph_Cycle_Id is function Sequence_Next_Cycle return Library_Graph_Cycle_Id is
......
...@@ -668,7 +668,7 @@ package Bindo.Graphs is ...@@ -668,7 +668,7 @@ package Bindo.Graphs is
-- The following type represents the various kinds of library graph -- The following type represents the various kinds of library graph
-- cycles. The ordering of kinds is significant, where a literal with -- cycles. The ordering of kinds is significant, where a literal with
-- lower ordinal has a higner precedence than one with higher ordinal. -- lower ordinal has a higher precedence than one with higher ordinal.
type Library_Graph_Cycle_Kind is type Library_Graph_Cycle_Kind is
(Elaborate_Body_Cycle, (Elaborate_Body_Cycle,
...@@ -753,13 +753,11 @@ package Bindo.Graphs is ...@@ -753,13 +753,11 @@ package Bindo.Graphs is
-- describes. -- describes.
function Create function Create
(Initial_Vertices : Positive; (Initial_Vertices : Positive;
Initial_Edges : Positive; Initial_Edges : Positive) return Library_Graph;
Dynamically_Elaborated : Boolean) return Library_Graph;
pragma Inline (Create); pragma Inline (Create);
-- Create a new empty graph with vertex capacity Initial_Vertices and -- Create a new empty graph with vertex capacity Initial_Vertices and
-- edge capacity Initial_Edges. Flag Dynamically_Elaborated must be set -- edge capacity Initial_Edges.
-- when the main library unit was compiled using the dynamic model.
procedure Destroy (G : in out Library_Graph); procedure Destroy (G : in out Library_Graph);
pragma Inline (Destroy); pragma Inline (Destroy);
...@@ -809,10 +807,12 @@ package Bindo.Graphs is ...@@ -809,10 +807,12 @@ package Bindo.Graphs is
procedure Decrement_Pending_Predecessors procedure Decrement_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id); Vertex : Library_Graph_Vertex_Id;
Edge : Library_Graph_Edge_Id);
pragma Inline (Decrement_Pending_Predecessors); pragma Inline (Decrement_Pending_Predecessors);
-- Decrease the number of pending predecessors vertex Vertex of library -- Decrease the number of pending predecessors vertex Vertex which was
-- graph G must wait on until it can be elaborated. -- reached via edge Edge of library graph G must wait until it can be
-- elaborated.
function File_Name function File_Name
(G : Library_Graph; (G : Library_Graph;
...@@ -844,12 +844,30 @@ package Bindo.Graphs is ...@@ -844,12 +844,30 @@ package Bindo.Graphs is
-- Obtain the name of the unit which vertex Vertex of library graph G -- Obtain the name of the unit which vertex Vertex of library graph G
-- represents. -- represents.
function Pending_Predecessors procedure Pending_Predecessors_For_Elaboration
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id;
Strong_Preds : out Natural;
Weak_Preds : out Natural);
pragma Inline (Pending_Predecessors_For_Elaboration);
-- Obtain the number of pending strong and weak predecessors of vertex
-- Vertex of library graph G, taking into account Elaborate_Body pairs.
-- Strong predecessors are returned in Strong_Preds. Weak predecessors
-- are returned in Weak_Preds.
function Pending_Strong_Predecessors
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Natural;
pragma Inline (Pending_Strong_Predecessors);
-- Obtain the number of pending strong predecessors vertex Vertex of
-- library graph G must wait on until it can be elaborated.
function Pending_Weak_Predecessors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Natural; Vertex : Library_Graph_Vertex_Id) return Natural;
pragma Inline (Pending_Predecessors); pragma Inline (Pending_Weak_Predecessors);
-- Obtain the number of pending predecessors vertex Vertex of library -- Obtain the number of pending weak predecessors vertex Vertex of
-- graph G must wait on until it can be elaborated. -- library graph G must wait on until it can be elaborated.
procedure Set_Corresponding_Item procedure Set_Corresponding_Item
(G : Library_Graph; (G : Library_Graph;
...@@ -901,17 +919,26 @@ package Bindo.Graphs is ...@@ -901,17 +919,26 @@ package Bindo.Graphs is
procedure Decrement_Pending_Predecessors procedure Decrement_Pending_Predecessors
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id); Comp : Component_Id;
Edge : Library_Graph_Edge_Id);
pragma Inline (Decrement_Pending_Predecessors); pragma Inline (Decrement_Pending_Predecessors);
-- Decrease the number of pending predecessors component Comp of library -- Decrease the number of pending predecessors component Comp which was
-- graph G must wait on until it can be elaborated. -- reached via edge Edge of library graph G must wait on until it can be
-- elaborated.
function Pending_Predecessors function Pending_Strong_Predecessors
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id) return Natural; Comp : Component_Id) return Natural;
pragma Inline (Pending_Predecessors); pragma Inline (Pending_Strong_Predecessors);
-- Obtain the number of pending predecessors component Comp of library -- Obtain the number of pending strong predecessors component Comp of
-- graph G must wait on until it can be elaborated. -- library graph G must wait on until it can be elaborated.
function Pending_Weak_Predecessors
(G : Library_Graph;
Comp : Component_Id) return Natural;
pragma Inline (Pending_Weak_Predecessors);
-- Obtain the number of pending weak predecessors component Comp of
-- library graph G must wait on until it can be elaborated.
---------------------- ----------------------
-- Cycle attributes -- -- Cycle attributes --
...@@ -940,6 +967,26 @@ package Bindo.Graphs is ...@@ -940,6 +967,26 @@ package Bindo.Graphs is
-- Semantics -- -- Semantics --
--------------- ---------------
function Complementary_Vertex
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id;
Force_Complement : Boolean) return Library_Graph_Vertex_Id;
pragma Inline (Complementary_Vertex);
-- Obtain the complementary vertex of vertex Vertex of library graph G
-- as follows:
--
-- * If Vertex is the spec of an Elaborate_Body pair, return the body
-- * If Vertex is the body of an Elaborate_Body pair, return the spec
--
-- This behavior can be forced by setting flag Force_Complement to True.
function Contains_Weak_Static_Successor
(G : Library_Graph;
Cycle : Library_Graph_Cycle_Id) return Boolean;
pragma Inline (Contains_Weak_Static_Successor);
-- Determine whether cycle Cycle of library graph G contains a weak edge
-- where the successor was compiled using the static model.
function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean; function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean;
pragma Inline (Has_Elaborate_All_Cycle); pragma Inline (Has_Elaborate_All_Cycle);
-- Determine whether library graph G contains a cycle involving pragma -- Determine whether library graph G contains a cycle involving pragma
...@@ -973,22 +1020,26 @@ package Bindo.Graphs is ...@@ -973,22 +1020,26 @@ package Bindo.Graphs is
-- Determine whether vertex Vertex of library graph G denotes a body -- Determine whether vertex Vertex of library graph G denotes a body
-- with a corresponding spec. -- with a corresponding spec.
function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean; function Is_Dynamically_Elaborated
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Boolean;
pragma Inline (Is_Dynamically_Elaborated); pragma Inline (Is_Dynamically_Elaborated);
-- Determine whether library graph G was created from a set of units -- Determine whether vertex Vertex of library graph G was compiled
-- where the main library unit was compiled using the dynamic model. -- using the dynamic model.
function Is_Elaborable_Component function Is_Elaborable_Component
(G : Library_Graph; (G : Library_Graph;
Comp : Component_Id) return Boolean; Comp : Component_Id) return Boolean;
pragma Inline (Is_Elaborable_Component); pragma Inline (Is_Elaborable_Component);
-- Determine whether component Comp of library graph G can be elaborated -- Determine whether component Comp of library graph G is not waiting on
-- any predecessors, and can thus be elaborated.
function Is_Elaborable_Vertex function Is_Elaborable_Vertex
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Boolean; Vertex : Library_Graph_Vertex_Id) return Boolean;
pragma Inline (Is_Elaborable_Vertex); pragma Inline (Is_Elaborable_Vertex);
-- Determine whether vertex Vertex of library graph G can be elaborated -- Determine whether vertex Vertex of library graph G is not waiting on
-- any predecessors, and can thus be elaborated.
function Is_Elaborate_All_Edge function Is_Elaborate_All_Edge
(G : Library_Graph; (G : Library_Graph;
...@@ -1012,6 +1063,15 @@ package Bindo.Graphs is ...@@ -1012,6 +1063,15 @@ package Bindo.Graphs is
-- Determine whether edge Edge of library graph G is an edge whose -- Determine whether edge Edge of library graph G is an edge whose
-- predecessor is subject to pragma Elaborate. -- predecessor is subject to pragma Elaborate.
function Is_Elaborate_Body_Pair
(G : Library_Graph;
Spec_Vertex : Library_Graph_Vertex_Id;
Body_Vertex : Library_Graph_Vertex_Id) return Boolean;
pragma Inline (Is_Elaborate_Body_Pair);
-- Determine whether vertices Spec_Vertex and Body_Vertex of library
-- graph G denote a spec subject to Elaborate_Body and its completing
-- body.
function Is_Forced_Edge function Is_Forced_Edge
(G : Library_Graph; (G : Library_Graph;
Edge : Library_Graph_Edge_Id) return Boolean; Edge : Library_Graph_Edge_Id) return Boolean;
...@@ -1045,7 +1105,7 @@ package Bindo.Graphs is ...@@ -1045,7 +1105,7 @@ package Bindo.Graphs is
Vertex : Library_Graph_Vertex_Id) return Boolean; Vertex : Library_Graph_Vertex_Id) return Boolean;
pragma Inline (Is_Preelaborated_Unit); pragma Inline (Is_Preelaborated_Unit);
-- Determine whether vertex Vertex of library graph G denotes a unit -- Determine whether vertex Vertex of library graph G denotes a unit
-- subjec to pragma Pure or Preelaborable. -- subject to pragma Pure or Preelaborable.
function Is_Spec function Is_Spec
(G : Library_Graph; (G : Library_Graph;
...@@ -1067,6 +1127,14 @@ package Bindo.Graphs is ...@@ -1067,6 +1127,14 @@ package Bindo.Graphs is
-- Determine whether vertex Vertex of library graph G denotes a spec -- Determine whether vertex Vertex of library graph G denotes a spec
-- with a corresponding body, and is subject to pragma Elaborate_Body. -- with a corresponding body, and is subject to pragma Elaborate_Body.
function Is_Weakly_Elaborable_Vertex
(G : Library_Graph;
Vertex : Library_Graph_Vertex_Id) return Boolean;
pragma Inline (Is_Weakly_Elaborable_Vertex);
-- Determine whether vertex Vertex of library graph G is waiting on
-- weak predecessors only, in which case it can be elaborated assuming
-- that the weak edges will not be exercised at elaboration time.
function Is_With_Edge function Is_With_Edge
(G : Library_Graph; (G : Library_Graph;
Edge : Library_Graph_Edge_Id) return Boolean; Edge : Library_Graph_Edge_Id) return Boolean;
...@@ -1320,9 +1388,13 @@ package Bindo.Graphs is ...@@ -1320,9 +1388,13 @@ package Bindo.Graphs is
In_Elaboration_Order : Boolean := False; In_Elaboration_Order : Boolean := False;
-- Set when this vertex is elaborated -- Set when this vertex is elaborated
Pending_Predecessors : Natural := 0; Pending_Strong_Predecessors : Natural := 0;
-- The number of pending predecessor vertices this vertex must wait -- The number of pending strong predecessor vertices this vertex must
-- on before it can be elaborated. -- wait on before it can be elaborated.
Pending_Weak_Predecessors : Natural := 0;
-- The number of weak predecessor vertices this vertex must wait on
-- before it can be elaborated.
Unit : Unit_Id := No_Unit_Id; Unit : Unit_Id := No_Unit_Id;
-- The reference to unit this vertex represents -- The reference to unit this vertex represents
...@@ -1330,10 +1402,11 @@ package Bindo.Graphs is ...@@ -1330,10 +1402,11 @@ package Bindo.Graphs is
No_Library_Graph_Vertex_Attributes : No_Library_Graph_Vertex_Attributes :
constant Library_Graph_Vertex_Attributes := constant Library_Graph_Vertex_Attributes :=
(Corresponding_Item => No_Library_Graph_Vertex, (Corresponding_Item => No_Library_Graph_Vertex,
In_Elaboration_Order => False, In_Elaboration_Order => False,
Pending_Predecessors => 0, Pending_Strong_Predecessors => 0,
Unit => No_Unit_Id); Pending_Weak_Predecessors => 0,
Unit => No_Unit_Id);
procedure Destroy_Library_Graph_Vertex_Attributes procedure Destroy_Library_Graph_Vertex_Attributes
(Attrs : in out Library_Graph_Vertex_Attributes); (Attrs : in out Library_Graph_Vertex_Attributes);
...@@ -1391,13 +1464,18 @@ package Bindo.Graphs is ...@@ -1391,13 +1464,18 @@ package Bindo.Graphs is
-- The following type represents the attributes of a component -- The following type represents the attributes of a component
type Component_Attributes is record type Component_Attributes is record
Pending_Predecessors : Natural := 0; Pending_Strong_Predecessors : Natural := 0;
-- The number of pending predecessor components this component must -- The number of pending strong predecessor components this component
-- wait on before it can be elaborated. -- must wait on before it can be elaborated.
Pending_Weak_Predecessors : Natural := 0;
-- The number of pending weak predecessor components this component
-- must wait on before it can be elaborated.
end record; end record;
No_Component_Attributes : constant Component_Attributes := No_Component_Attributes : constant Component_Attributes :=
(Pending_Predecessors => 0); (Pending_Strong_Predecessors => 0,
Pending_Weak_Predecessors => 0);
procedure Destroy_Component_Attributes procedure Destroy_Component_Attributes
(Attrs : in out Component_Attributes); (Attrs : in out Component_Attributes);
...@@ -1560,10 +1638,6 @@ package Bindo.Graphs is ...@@ -1560,10 +1638,6 @@ package Bindo.Graphs is
Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil; Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil;
-- The list of all cycles in the graph, sorted based on precedence -- The list of all cycles in the graph, sorted based on precedence
Dynamically_Elaborated : Boolean := False;
-- Set when the main library unit was compiled using the dynamic
-- model.
Edge_Attributes : LGE_Tables.Dynamic_Hash_Table := LGE_Tables.Nil; Edge_Attributes : LGE_Tables.Dynamic_Hash_Table := LGE_Tables.Nil;
-- The map of edge -> edge attributes for all edges in the graph -- The map of edge -> edge attributes for all edges in the graph
......
...@@ -140,7 +140,7 @@ package body Bindo.Validators is ...@@ -140,7 +140,7 @@ package body Bindo.Validators is
Edges := LGE_Sets.Create (Length (G, Cycle)); Edges := LGE_Sets.Create (Length (G, Cycle));
-- Inspect the edges of the cucle, trying to catch duplicates -- Inspect the edges of the cycle, trying to catch duplicates
Iter := Iterate_Edges_Of_Cycle (G, Cycle); Iter := Iterate_Edges_Of_Cycle (G, Cycle);
while Has_Next (Iter) loop while Has_Next (Iter) loop
...@@ -155,7 +155,7 @@ package body Bindo.Validators is ...@@ -155,7 +155,7 @@ package body Bindo.Validators is
Write_Str (" library graph edge (LGE_Id_"); Write_Str (" library graph edge (LGE_Id_");
Write_Int (Int (Edge)); Write_Int (Int (Edge));
Write_Str (") is repeaded in cycle (LGC_Id_"); Write_Str (") is repeated in cycle (LGC_Id_");
Write_Int (Int (Cycle)); Write_Int (Int (Cycle));
Write_Str (")"); Write_Str (")");
Write_Eol; Write_Eol;
...@@ -421,7 +421,7 @@ package body Bindo.Validators is ...@@ -421,7 +421,7 @@ package body Bindo.Validators is
(G : Invocation_Graph; (G : Invocation_Graph;
Vertex : Invocation_Graph_Vertex_Id); Vertex : Invocation_Graph_Vertex_Id);
pragma Inline (Validate_Invocation_Graph_Vertex); pragma Inline (Validate_Invocation_Graph_Vertex);
-- Verify that the attributes of vertex Vertex of inbocation graph G are -- Verify that the attributes of vertex Vertex of invocation graph G are
-- properly set. -- properly set.
procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph); procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph);
...@@ -468,7 +468,7 @@ package body Bindo.Validators is ...@@ -468,7 +468,7 @@ package body Bindo.Validators is
if not Present (Edge) then if not Present (Edge) then
Write_Error (Msg, Has_Invalid_Data); Write_Error (Msg, Has_Invalid_Data);
Write_Str (" emply invocation graph edge"); Write_Str (" empty invocation graph edge");
Write_Eol; Write_Eol;
Write_Eol; Write_Eol;
return; return;
...@@ -530,7 +530,7 @@ package body Bindo.Validators is ...@@ -530,7 +530,7 @@ package body Bindo.Validators is
if not Present (Vertex) then if not Present (Vertex) then
Write_Error (Msg, Has_Invalid_Data); Write_Error (Msg, Has_Invalid_Data);
Write_Str (" emply invocation graph vertex"); Write_Str (" empty invocation graph vertex");
Write_Eol; Write_Eol;
Write_Eol; Write_Eol;
return; return;
...@@ -662,7 +662,7 @@ package body Bindo.Validators is ...@@ -662,7 +662,7 @@ package body Bindo.Validators is
if not Present (Edge) then if not Present (Edge) then
Write_Error (Msg, Has_Invalid_Data); Write_Error (Msg, Has_Invalid_Data);
Write_Str (" emply library graph edge"); Write_Str (" empty library graph edge");
Write_Eol; Write_Eol;
Write_Eol; Write_Eol;
return; return;
......
...@@ -1025,6 +1025,10 @@ package body Bindo.Writers is ...@@ -1025,6 +1025,10 @@ package body Bindo.Writers is
-- Write all vertices of component Comp of library graph G to standard -- Write all vertices of component Comp of library graph G to standard
-- output. -- output.
procedure Write_Components (G : Library_Graph);
pragma Inline (Write_Component);
-- Write all components of library graph G to standard output
procedure Write_Edges_To_Successors procedure Write_Edges_To_Successors
(G : Library_Graph; (G : Library_Graph;
Vertex : Library_Graph_Vertex_Id); Vertex : Library_Graph_Vertex_Id);
...@@ -1089,8 +1093,12 @@ package body Bindo.Writers is ...@@ -1089,8 +1093,12 @@ package body Bindo.Writers is
Write_Str (")"); Write_Str (")");
Write_Eol; Write_Eol;
Write_Str (" Pending_Predecessors = "); Write_Str (" Pending_Strong_Predecessors = ");
Write_Int (Int (Pending_Predecessors (G, Comp))); Write_Int (Int (Pending_Strong_Predecessors (G, Comp)));
Write_Eol;
Write_Str (" Pending_Weak_Predecessors = ");
Write_Int (Int (Pending_Weak_Predecessors (G, Comp)));
Write_Eol; Write_Eol;
Write_Component_Vertices (G, Comp); Write_Component_Vertices (G, Comp);
...@@ -1225,6 +1233,7 @@ package body Bindo.Writers is ...@@ -1225,6 +1233,7 @@ package body Bindo.Writers is
Write_Statistics (G); Write_Statistics (G);
Write_Library_Graph_Vertices (G); Write_Library_Graph_Vertices (G);
Write_Components (G);
Write_Str ("Library Graph end"); Write_Str ("Library Graph end");
Write_Eol; Write_Eol;
...@@ -1312,8 +1321,12 @@ package body Bindo.Writers is ...@@ -1312,8 +1321,12 @@ package body Bindo.Writers is
end if; end if;
Write_Eol; Write_Eol;
Write_Str (" Pending_Predecessors = "); Write_Str (" Pending_Strong_Predecessors = ");
Write_Int (Int (Pending_Predecessors (G, Vertex))); Write_Int (Int (Pending_Strong_Predecessors (G, Vertex)));
Write_Eol;
Write_Str (" Pending_Weak_Predecessors = ");
Write_Int (Int (Pending_Weak_Predecessors (G, Vertex)));
Write_Eol; Write_Eol;
Write_Str (" Component (Comp_Id_"); Write_Str (" Component (Comp_Id_");
...@@ -1612,7 +1625,7 @@ package body Bindo.Writers is ...@@ -1612,7 +1625,7 @@ package body Bindo.Writers is
is is
function Digits_Indentation return Indentation_Level; function Digits_Indentation return Indentation_Level;
pragma Inline (Digits_Indentation); pragma Inline (Digits_Indentation);
-- Determine the level of indentation the number requies in order to -- Determine the level of indentation the number requires in order to
-- be right-justified by Val_Indent. -- be right-justified by Val_Indent.
------------------------ ------------------------
......
...@@ -127,9 +127,6 @@ package Bindo.Writers is ...@@ -127,9 +127,6 @@ package Bindo.Writers is
--------------------------- ---------------------------
package Library_Graph_Writers is package Library_Graph_Writers is
procedure Write_Components (G : Library_Graph);
-- Write all components of library graph G to standard output
procedure Write_Library_Graph (G : Library_Graph); procedure Write_Library_Graph (G : Library_Graph);
-- Write library graph G to standard output -- Write library graph G to standard output
......
...@@ -74,7 +74,7 @@ package body Bindo is ...@@ -74,7 +74,7 @@ package body Bindo is
-- --
-- * Diagnose elaboration circularities between units -- * Diagnose elaboration circularities between units
-- --
-- An elaboration circularity arrises when either -- An elaboration circularity arises when either
-- --
-- - At least one unit cannot be ordered, or -- - At least one unit cannot be ordered, or
-- --
...@@ -95,6 +95,12 @@ package body Bindo is ...@@ -95,6 +95,12 @@ package body Bindo is
-- * Component - A strongly connected component of a graph. -- * Component - A strongly connected component of a graph.
-- --
-- * Elaborable component - A component that is not waiting on other
-- components to be elaborated.
--
-- * Elaborable vertex - A vertex that is not waiting on strong and weak
-- predecessors, and whose component is elaborable.
--
-- * Elaboration circularity - A cycle involving units from the bind. -- * Elaboration circularity - A cycle involving units from the bind.
-- --
-- * Elaboration root - A special invocation construct which denotes the -- * Elaboration root - A special invocation construct which denotes the
...@@ -136,8 +142,23 @@ package body Bindo is ...@@ -136,8 +142,23 @@ package body Bindo is
-- * Pending predecessor - A vertex that must be elaborated before another -- * Pending predecessor - A vertex that must be elaborated before another
-- vertex can be elaborated. -- vertex can be elaborated.
-- --
-- * Strong edge - A non-invocation library graph edge. Strong edges
-- represent the language-defined relations between units.
--
-- * Strong predecessor - A library graph vertex reachable via a strong
-- edge.
--
-- * Target - The destination construct of an invocation relation (the -- * Target - The destination construct of an invocation relation (the
-- generic, subprogram, or task type). -- generic, subprogram, or task type).
--
-- * Weak edge - An invocation library graph edge. Weak edges represent
-- the speculative flow of execution at elaboration time, which may or
-- may not take place.
--
-- * Weak predecessor - A library graph vertex reachable via a weak edge.
--
-- * Weakly elaborable vertex - A vertex that is waiting solely on weak
-- predecessors to be elaborated, and whose component is elaborable.
------------------ ------------------
-- Architecture -- -- Architecture --
...@@ -233,7 +254,7 @@ package body Bindo is ...@@ -233,7 +254,7 @@ package body Bindo is
-- bodies as single vertices. -- bodies as single vertices.
-- --
-- * Try to order as many vertices of the library graph as possible by -- * Try to order as many vertices of the library graph as possible by
-- peforming a topological sort based on the pending predecessors of -- performing a topological sort based on the pending predecessors of
-- vertices across all components and within a single component. -- vertices across all components and within a single component.
-- --
-- * Validate the consistency of the order, only when switch -d_V is in -- * Validate the consistency of the order, only when switch -d_V is in
...@@ -251,7 +272,7 @@ package body Bindo is ...@@ -251,7 +272,7 @@ package body Bindo is
-- The Diagnostics phase has the following objectives: -- The Diagnostics phase has the following objectives:
-- --
-- * Discover, save, and sort all cycles in the library graph. The cycles -- * Discover, save, and sort all cycles in the library graph. The cycles
-- are sorted based on the following heiristics: -- are sorted based on the following heuristics:
-- --
-- - A cycle with higher precedence is preferred. -- - A cycle with higher precedence is preferred.
-- --
...@@ -268,7 +289,7 @@ package body Bindo is ...@@ -268,7 +289,7 @@ package body Bindo is
-- * Diagnose the most important cycle, or all cycles when switch -d_C is -- * Diagnose the most important cycle, or all cycles when switch -d_C is
-- in effect. The diagnostic consists of: -- in effect. The diagnostic consists of:
-- --
-- - The reason for the existance of the cycle, along with the unit -- - The reason for the existence of the cycle, along with the unit
-- whose elaboration cannot be guaranteed. -- whose elaboration cannot be guaranteed.
-- --
-- - A detailed traceback of the cycle, showcasing the transition -- - A detailed traceback of the cycle, showcasing the transition
...@@ -276,7 +297,7 @@ package body Bindo is ...@@ -276,7 +297,7 @@ package body Bindo is
-- information. -- information.
-- --
-- - A set of suggestions on how to break the cycle considering the -- - A set of suggestions on how to break the cycle considering the
-- the edges coprising the circuit, the elaboration model used to -- the edges comprising the circuit, the elaboration model used to
-- compile the units, the availability of invocation information, -- compile the units, the availability of invocation information,
-- and the state of various relevant switches. -- and the state of various relevant switches.
...@@ -284,6 +305,23 @@ package body Bindo is ...@@ -284,6 +305,23 @@ package body Bindo is
-- Switches -- -- Switches --
-------------- --------------
-- -d_a Ignore the effects of pragma Elaborate_All
--
-- GNATbind creates a regular with edge instead of an Elaborate_All
-- edge in the library graph, thus eliminating the effects of the
-- pragma.
--
-- -d_b Ignore the effects of pragma Elaborate_Body
--
-- GNATbind treats a spec and body pair as decoupled.
--
-- -d_e Ignore the effects of pragma Elaborate
--
-- GNATbind creates a regular with edge instead of an Elaborate edge
-- in the library graph, thus eliminating the effects of the pragma.
-- In addition, GNATbind does not create an edge to the body of the
-- pragma argument.
--
-- -d_A Output ALI invocation tables -- -d_A Output ALI invocation tables
-- --
-- GNATbind outputs the contents of ALI table Invocation_Constructs -- GNATbind outputs the contents of ALI table Invocation_Constructs
......
...@@ -41,4 +41,14 @@ package Bindo is ...@@ -41,4 +41,14 @@ package Bindo is
-- exists, it is returned in Order, otherwise Unrecoverable_Error is -- exists, it is returned in Order, otherwise Unrecoverable_Error is
-- raised. -- raised.
private
-- The following type represents the various kinds of precedence between
-- two items.
type Precedence_Kind is
(Lower_Precedence,
Equal_Precedence,
Higher_Precedence);
end Bindo; end Bindo;
...@@ -349,11 +349,11 @@ package body Debug is ...@@ -349,11 +349,11 @@ package body Debug is
-- d.8 -- d.8
-- d.9 -- d.9
-- d_a -- d_a Ignore the effects of pragma Elaborate_All
-- d_b -- d_b Ignore the effects of pragma Elaborate_Body
-- d_c -- d_c
-- d_d -- d_d
-- d_e -- d_e Ignore the effects of pragma Elaborate
-- d_f -- d_f
-- d_g -- d_g
-- d_h -- d_h
...@@ -1141,6 +1141,17 @@ package body Debug is ...@@ -1141,6 +1141,17 @@ package body Debug is
-- dx Force the binder to read (and then ignore) the xref information -- dx Force the binder to read (and then ignore) the xref information
-- in ali files (used to check that read circuit is working OK). -- in ali files (used to check that read circuit is working OK).
-- d_a GNATBIND ignores the effects of pragma Elaborate_All in the case of
-- elaboration order and treats the associated dependency as a regular
-- with edge.
-- d_b GNATBIND ignores the effects of pragma Elaborate_Body in the case
-- of elaboration order and treats the spec and body as decoupled.
-- d_e GNATBIND ignores the effects of pragma Elaborate in the case of
-- elaboration order and no longer creates an implicit dependency on
-- the body of the argument.
-- d_A GNATBIND output the contents of all ALI invocation-related tables -- d_A GNATBIND output the contents of all ALI invocation-related tables
-- in textual format to standard output. -- in textual format to standard output.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment