[Ada] New algorithm for Elaboration order v4.0
authorHristian Kirtchev <kirtchev@adacore.com>
Mon, 8 Jul 2019 08:13:43 +0000 (08:13 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Mon, 8 Jul 2019 08:13:43 +0000 (08:13 +0000)
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

13 files changed:
gcc/ada/ChangeLog
gcc/ada/bindo-builders.adb
gcc/ada/bindo-builders.ads
gcc/ada/bindo-diagnostics.adb
gcc/ada/bindo-elaborators.adb
gcc/ada/bindo-graphs.adb
gcc/ada/bindo-graphs.ads
gcc/ada/bindo-validators.adb
gcc/ada/bindo-writers.adb
gcc/ada/bindo-writers.ads
gcc/ada/bindo.adb
gcc/ada/bindo.ads
gcc/ada/debug.adb

index 3bbc1cfc5da2496a8e704f0ce372a07bcb885ab2..e6eac08a8025cf441b2c855fa0419203b48a2a17 100644 (file)
@@ -1,3 +1,133 @@
+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>
 
        * libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate):
index f4b8e42fe08753cd990b12c8e86bae04a2baae47..233891d12e486ad96917ab77158f9af3060ca2d1 100644 (file)
 
 with Binderr; use Binderr;
 with Butil;   use Butil;
+with Debug;   use Debug;
 with Opt;     use Opt;
 with Output;  use Output;
 with Types;   use Types;
 
 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.Dynamic_HTables; use GNAT.Dynamic_HTables;
 
@@ -104,6 +110,8 @@ package body Bindo.Builders is
          For_Each_Elaborable_Unit (Create_Vertices'Access);
          For_Each_Elaborable_Unit (Create_Edges'Access);
 
+         Validate_Invocation_Graph (Inv_Graph);
+
          return Inv_Graph;
       end Build_Invocation_Graph;
 
@@ -365,24 +373,22 @@ package body Bindo.Builders is
       -- Build_Library_Graph --
       -------------------------
 
-      function Build_Library_Graph
-        (Dynamically_Elaborated : Boolean) return Library_Graph
-      is
+      function Build_Library_Graph return Library_Graph is
       begin
          --  Prepare the global data
 
          Lib_Graph :=
            Create
-             (Initial_Vertices       => Number_Of_Elaborable_Units,
-              Initial_Edges          => Number_Of_Elaborable_Units,
-              Dynamically_Elaborated => Dynamically_Elaborated);
+             (Initial_Vertices => Number_Of_Elaborable_Units,
+              Initial_Edges    => Number_Of_Elaborable_Units);
 
          For_Each_Elaborable_Unit (Create_Vertex'Access);
          For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access);
          For_Each_Elaborable_Unit (Create_With_Edges'Access);
-
          Create_Forced_Edges;
 
+         Validate_Library_Graph (Lib_Graph);
+
          return Lib_Graph;
       end Build_Library_Graph;
 
@@ -549,9 +555,13 @@ package body Bindo.Builders is
 
          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;
 
             --  The withed unit is a spec with a completing body. Add an edge
@@ -568,9 +578,13 @@ package body Bindo.Builders is
                   Kind => Kind);
             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;
 
          --  Otherwise this is a regular with
index 0e8519fd1eb3fd10655ab3c5a258448770690195..54c39e4820a8ff4b149caffe6c64fe2144ad6ea0 100644 (file)
@@ -56,11 +56,9 @@ package Bindo.Builders is
    ----------------------------
 
    package Library_Graph_Builders is
-      function Build_Library_Graph
-        (Dynamically_Elaborated : Boolean) return Library_Graph;
+      function Build_Library_Graph return Library_Graph;
       --  Return a new library graph that reflects the dependencies between
-      --  all units of the bind. Flag Dynamically_Elaborated must be set when
-      --  the main library unit was compiled using the dynamic model.
+      --  all units of the bind.
 
    end Library_Graph_Builders;
 
index 0c9da46506301b9e2cba9614418b7fbf4b018678..0c1a924a1d668107eb0bb7a3ffa4eb6923813ea3 100644 (file)
@@ -285,9 +285,9 @@ package body Bindo.Diagnostics is
       end loop;
    end Diagnose_All_Cycles;
 
-   --------------------------
+   ----------------------------
    -- Diagnose_Circularities --
-   --------------------------
+   ----------------------------
 
    procedure Diagnose_Circularities
      (Inv_Graph : Invocation_Graph;
@@ -374,6 +374,12 @@ package body Bindo.Diagnostics is
          --  taking into account the predecessors and successors involved, as
          --  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
            (Inv_Graph            => Inv_Graph,
             Lib_Graph            => Lib_Graph,
@@ -533,12 +539,12 @@ package body Bindo.Diagnostics is
       pragma Assert (Present (G));
       pragma Assert (Present (Cycle));
 
-      --  The cycle contains at least one invocation edge and the main library
-      --  unit was compiled with the static model. Using the dynamic model may
-      --  eliminate the invocation edge, and thus the cycle.
+      --  The cycle contains at least one invocation edge where the successor
+      --  was statically elaborated. Using the dynamic model may eliminate an
+      --  invocation edge, and thus the cycle.
 
       if Invocation_Edge_Count (G, Cycle) > 0
-        and then not Is_Dynamically_Elaborated (G)
+        and then Contains_Weak_Static_Successor (G, Cycle)
       then
          Error_Msg_Info
            ("    use the dynamic elaboration model (compiler switch -gnatE)");
@@ -703,10 +709,11 @@ package body Bindo.Diagnostics is
       --               Expected_Destination
 
       else
-         pragma Assert (Is_Spec_With_Body (G, Actual_Destination));
-         pragma Assert (Is_Body_With_Spec (G, Expected_Destination));
          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_2 := Name (G, Actual_Destination);
@@ -922,13 +929,11 @@ package body Bindo.Diagnostics is
       --                     Expected_Destination
 
       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
-           (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_2 := Name (G, Actual_Destination);
@@ -1392,13 +1397,11 @@ package body Bindo.Diagnostics is
       --                   Expected_Destination
 
       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
-           (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_2 := Name (G, Actual_Destination);
index 762198bd69131e9591258f5fe4b7c79a567b3d3b..192e4a228ed63e0e361782902699411edbd9a72f 100644 (file)
@@ -46,8 +46,6 @@ use  Bindo.Units;
 with Bindo.Validators;
 use  Bindo.Validators;
 use  Bindo.Validators.Elaboration_Order_Validators;
-use  Bindo.Validators.Invocation_Graph_Validators;
-use  Bindo.Validators.Library_Graph_Validators;
 
 with Bindo.Writers;
 use  Bindo.Writers;
@@ -76,76 +74,61 @@ package body Bindo.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 --
       -----------------------
 
-      procedure Add_Vertex
-        (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id;
-         Set    : LGV_Sets.Membership_Set;
-         Msg    : String;
-         Step   : Elaboration_Order_Step;
-         Indent : Indentation_Level);
-      pragma Inline (Add_Vertex);
-      --  Add vertex Vertex of library graph G to membership set Set. Msg is
-      --  a message emitted for tracing purposes. Step is the current step in
-      --  the elaboration order. Indent is the desired indentation level for
-      --  tracing.
-
-      procedure Add_Vertex_If_Elaborable
-        (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id;
-         Set    : LGV_Sets.Membership_Set;
-         Msg    : String;
-         Step   : Elaboration_Order_Step;
-         Indent : Indentation_Level);
-      pragma Inline (Add_Vertex_If_Elaborable);
-      --  Add vertex Vertex of library graph G to membership set Set if it can
-      --  be elaborated. Msg is a message emitted for tracing purposes. Step is
-      --  the current step in the elaboration order. Indent is the desired
-      --  indentation level for tracing.
-
-      function Create_All_Candidates_Set
-        (G    : Library_Graph;
-         Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set;
-      pragma Inline (Create_All_Candidates_Set);
-      --  Collect all elaborable candidate vertices of library graph G in a
-      --  set. Step is the current step in the elaboration order.
-
-      function Create_Component_Candidates_Set
-        (G    : Library_Graph;
-         Comp : Component_Id;
-         Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set;
-      pragma Inline (Create_Component_Candidates_Set);
-      --  Collect all elaborable candidate vertices that appear in component
-      --  Comp of library graph G in a set. Step is the current step in the
-      --  elaboration order.
+      procedure Create_Component_Vertex_Sets
+        (G                   : Library_Graph;
+         Comp                : Component_Id;
+         Elaborable_Vertices : out LGV_Sets.Membership_Set;
+         Waiting_Vertices    : out LGV_Sets.Membership_Set;
+         Step                : Elaboration_Order_Step);
+      pragma Inline (Create_Component_Vertex_Sets);
+      --  Split all vertices of component Comp of library graph G as follows:
+      --
+      --    * Elaborable vertices are added to set Elaborable_Vertices.
+      --
+      --    * Vertices that are still waiting on their predecessors to be
+      --      elaborated are added to set Waiting_Vertices.
+      --
+      --  Step is the current step in the elaboration order.
+
+      procedure Create_Vertex_Sets
+        (G                   : Library_Graph;
+         Elaborable_Vertices : out LGV_Sets.Membership_Set;
+         Waiting_Vertices    : out LGV_Sets.Membership_Set;
+         Step                : Elaboration_Order_Step);
+      pragma Inline (Create_Vertex_Sets);
+      --  Split all vertices of library graph G as follows:
+      --
+      --    * Elaborable vertices are added to set Elaborable_Vertices.
+      --
+      --    * Vertices that are still waiting on their predecessors to be
+      --      elaborated are added to set Waiting_Vertices.
+      --
+      --  Step is the current step in the elaboration order.
 
       procedure Elaborate_Component
-        (G                  : Library_Graph;
-         Comp               : Component_Id;
-         All_Candidates     : LGV_Sets.Membership_Set;
-         Remaining_Vertices : in out Natural;
-         Order              : in out Unit_Id_Table;
-         Step               : Elaboration_Order_Step);
+        (G                       : Library_Graph;
+         Comp                    : Component_Id;
+         All_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Order                   : in out Unit_Id_Table;
+         Step                    : Elaboration_Order_Step);
       pragma Inline (Elaborate_Component);
-      --  Elaborate as many vertices as possible that appear in component
-      --  Comp of library graph G. All_Candidates is the set of all elaborable
-      --  vertices across the whole library graph. Remaining_Vertices is the
-      --  number of vertices that remain to be elaborated. Order denotes the
-      --  elaboration order. Step is the current step in the elaboration order.
+      --  Elaborate as many vertices as possible that appear in component Comp
+      --  of library graph G. The sets contain vertices arranged as follows:
+      --
+      --    * All_Elaborable_Vertices - all elaborable vertices in the library
+      --      graph.
+      --
+      --    * All_Waiting_Vertices - all vertices in the library graph that are
+      --      waiting on predecessors to be elaborated.
+      --
+      --  Order is the elaboration order. Step denotes the current step in the
+      --  elaboration order.
 
       procedure Elaborate_Library_Graph
         (G      : Library_Graph;
@@ -156,81 +139,149 @@ package body Bindo.Elaborators is
       --  the elaboration order. Status is the condition of the elaboration
       --  order.
 
-      procedure Elaborate_Units_Common
-        (Use_Inv_Graph : Boolean;
-         Is_Dyn_Elab   : Boolean;
-         Inv_Graph     : out Invocation_Graph;
-         Lib_Graph     : out Library_Graph;
-         Order         : out Unit_Id_Table;
-         Status        : out Elaboration_Order_Status);
-      pragma Inline (Elaborate_Units_Common);
-      --  Find the elaboration order of all units in the bind. Use_Inv_Graph
-      --  should be set when library graph Lib_Graph is to be augmented with
-      --  information from invocation graph Inv_Graph. Is_Dyn_Elab should be
-      --  set when the main library unit was compiled using the dynamic model.
-      --  Order is the elaboration order. Status is the condition of the
-      --  elaboration order.
-
-      procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table);
-      pragma Inline (Elaborate_Units_Dynamic);
-      --  Find the elaboration order of all units in the bind using the dynamic
-      --  model. Order is the elaboration order. In the event where no ordering
-      --  is possible, this routine diagnoses the issue(s) and raises exception
-      --  Unrecoverable_Error.
-
-      procedure Elaborate_Units_Static (Order : out Unit_Id_Table);
-      pragma Inline (Elaborate_Units_Static);
-      --  Find the elaboration order of all units in the bind using the static
-      --  model. Order is the elaboration order. In the event where no ordering
-      --  is possible, this routine diagnoses the issue(s) and raises exception
-      --  Unrecoverable_Error.
-
       procedure Elaborate_Vertex
-        (G                  : Library_Graph;
-         Vertex             : Library_Graph_Vertex_Id;
-         All_Candidates     : LGV_Sets.Membership_Set;
-         Comp_Candidates    : LGV_Sets.Membership_Set;
-         Remaining_Vertices : in out Natural;
-         Order              : in out Unit_Id_Table;
-         Step               : Elaboration_Order_Step;
-         Indent             : Indentation_Level);
+        (G                        : Library_Graph;
+         Vertex                   : Library_Graph_Vertex_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Order                    : in out Unit_Id_Table;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level);
       pragma Inline (Elaborate_Vertex);
       --  Elaborate vertex Vertex of library graph G by adding its unit to
       --  elaboration order Order. The routine updates awaiting successors
-      --  where applicable. All_Candidates denotes the set of all elaborable
-      --  vertices across the whole library graph. Comp_Candidates is the set
-      --  of all elaborable vertices in the component of Vertex. Parameter
-      --  Remaining_Vertices denotes the number of vertices that remain to
-      --  be elaborated. Step is the current step in the elaboration order.
+      --  where applicable. The sets contain vertices arranged as follows:
+      --
+      --    * All_Elaborable_Vertices - all elaborable vertices in the library
+      --      graph.
+      --
+      --    * All_Waiting_Vertices - all vertices in the library graph that are
+      --      waiting on predecessors to be elaborated.
+      --
+      --    * Comp_Elaborable_Vertices - all elaborable vertices found in the
+      --      component of Vertex.
+      --
+      --    * Comp_Waiting_Vertices - all vertices found in the component of
+      --      Vertex that are still waiting on predecessors to be elaborated.
+      --
+      --  Order denotes the elaboration order. Step is the current step in the
+      --  elaboration order. Indent denotes the desired indentation level for
+      --  tracing.
+
+      function Find_Best_Elaborable_Vertex
+        (G      : Library_Graph;
+         Set    : LGV_Sets.Membership_Set;
+         Step   : Elaboration_Order_Step;
+         Indent : Indentation_Level) return Library_Graph_Vertex_Id;
+      pragma Inline (Find_Best_Elaborable_Vertex);
+      --  Find the best vertex of library graph G from membership set S that
+      --  can be elaborated. Step is the current step in the elaboration order.
       --  Indent is the desired indentation level for tracing.
 
-      function Find_Best_Candidate
+      type Comparator_Ptr is access function
+        (G           : Library_Graph;
+         Vertex      : Library_Graph_Vertex_Id;
+         Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind;
+
+      type Predicate_Ptr is access function
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean;
+
+      function Find_Best_Vertex
+        (G                   : Library_Graph;
+         Set                 : LGV_Sets.Membership_Set;
+         Is_Suitable_Vertex  : Predicate_Ptr;
+         Compare_Vertices    : Comparator_Ptr;
+         Initial_Best_Msg    : String;
+         Subsequent_Best_Msg : String;
+         Step                : Elaboration_Order_Step;
+         Indent              : Indentation_Level)
+         return Library_Graph_Vertex_Id;
+      pragma Inline (Find_Best_Vertex);
+      --  Find the best vertex of library graph G from membership set S which
+      --  satisfies predicate Is_Suitable_Vertex and is preferred by comparator
+      --  Compare_Vertices. Initial_Best_Msg is emitted on the first candidate
+      --  vertex. Subsequent_Best_Msg is emitted whenever a better vertex is
+      --  discovered. Step is the current step in the elaboration order. Indent
+      --  is the desired indentation level for tracing.
+
+      function Find_Best_Weakly_Elaborable_Vertex
         (G      : Library_Graph;
          Set    : LGV_Sets.Membership_Set;
          Step   : Elaboration_Order_Step;
          Indent : Indentation_Level) return Library_Graph_Vertex_Id;
-      pragma Inline (Find_Best_Candidate);
-      --  Find the most suitable vertex of library graph G for elaboration from
-      --  membership set Set. Step denotes the current step in the elaboration
+      pragma Inline (Find_Best_Weakly_Elaborable_Vertex);
+      --  Find the best vertex of library graph G from membership set S that
+      --  can be weakly elaborated. Step is the current step in the elaboration
       --  order. Indent is the desired indentation level for tracing.
 
-      function Is_Better_Candidate
-        (G              : Library_Graph;
-         Best_Candidate : Library_Graph_Vertex_Id;
-         New_Candidate  : Library_Graph_Vertex_Id) return Boolean;
-      pragma Inline (Is_Better_Candidate);
-      --  Determine whether new candidate vertex New_Candidate of library graph
-      --  G is a more suitable choice for elaboration compared to the current
-      --  best candidate Best_Candidate.
+      function Has_Elaborable_Body
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean;
+      pragma Inline (Has_Elaborable_Body);
+      --  Determine whether vertex Vertex of library graph G has a body that is
+      --  elaborable. It is assumed that the vertex has been elaborated.
+
+      procedure Insert_Elaborable_Successor
+        (G                     : Library_Graph;
+         Vertex                : Library_Graph_Vertex_Id;
+         Elaborable_Vertices   : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices  : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
+         Msg                   : String;
+         Step                  : Elaboration_Order_Step;
+         Indent                : Indentation_Level);
+      pragma Inline (Insert_Elaborable_Successor);
+      --  Add elaborable successor Vertex of library graph G to membership set
+      --  Elaborable_Vertices and remove it from both All_Waiting_Vertices and
+      --  Comp_Waiting_Vertices. Msg is a message emitted for tracing purposes.
+      --  Step is the current step in the elaboration order. Indent denotes the
+      --  desired indentation level for tracing.
+
+      procedure Insert_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id;
+         Set    : LGV_Sets.Membership_Set;
+         Msg    : String;
+         Step   : Elaboration_Order_Step;
+         Indent : Indentation_Level);
+      pragma Inline (Insert_Vertex);
+      --  Add vertex Vertex of library graph G to membership set Set. Msg is
+      --  a message emitted for tracing purposes. Step is the current step in
+      --  the elaboration order. Indent is the desired indentation level for
+      --  tracing.
 
-      procedure Trace_Candidate_Vertices
-        (G    : Library_Graph;
-         Set  : LGV_Sets.Membership_Set;
-         Step : Elaboration_Order_Step);
-      pragma Inline (Trace_Candidate_Vertices);
-      --  Write the candidate vertices of library graph G present in membership
-      --  set Set to standard output. Formal Step denotes the current step in
-      --  the elaboration order.
+      function Is_Better_Elaborable_Vertex
+        (G           : Library_Graph;
+         Vertex      : Library_Graph_Vertex_Id;
+         Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind;
+      pragma Inline (Is_Better_Elaborable_Vertex);
+      --  Determine whether vertex Vertex of library graph G is a better choice
+      --  for elaboration compared to vertex Compared_To.
+
+      function Is_Better_Weakly_Elaborable_Vertex
+        (G           : Library_Graph;
+         Vertex      : Library_Graph_Vertex_Id;
+         Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind;
+      pragma Inline (Is_Better_Weakly_Elaborable_Vertex);
+      --  Determine whether vertex Vertex of library graph G is a better choice
+      --  for weak elaboration compared to vertex Compared_To.
+
+      function Is_Suitable_Elaborable_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean;
+      pragma Inline (Is_Suitable_Elaborable_Vertex);
+      --  Determine whether vertex Vertex of library graph G is suitable for
+      --  elaboration.
+
+      function Is_Suitable_Weakly_Elaborable_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean;
+      pragma Inline (Is_Suitable_Weakly_Elaborable_Vertex);
+      --  Determine whether vertex Vertex of library graph G is suitable for
+      --  weak elaboration.
 
       procedure Trace_Component
         (G    : Library_Graph;
@@ -246,15 +297,6 @@ package body Bindo.Elaborators is
       pragma Inline (Trace_Step);
       --  Write current step Step of the elaboration order to standard output
 
-      procedure Trace_Unelaborated_Vertices
-        (G     : Library_Graph;
-         Count : Natural;
-         Step  : Elaboration_Order_Step);
-      pragma Inline (Trace_Unelaborated_Vertices);
-      --  Write the remaining unelaborated vertices of library graph G to
-      --  standard output. Count is the number of vertices that remain to
-      --  be elaborated. Step is the current step in the elaboration order.
-
       procedure Trace_Vertex
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id;
@@ -267,220 +309,202 @@ package body Bindo.Elaborators is
       --  current step in the elaboration order. Indent denotes the desired
       --  indentation level for tracing.
 
+      procedure Trace_Vertices
+        (G          : Library_Graph;
+         Set        : LGV_Sets.Membership_Set;
+         Set_Msg    : String;
+         Vertex_Msg : String;
+         Step       : Elaboration_Order_Step;
+         Indent     : Indentation_Level);
+      pragma Inline (Trace_Vertices);
+      --  Write the candidate vertices of library graph G present in membership
+      --  set Set to standard output, starting with message Set_Msg. Vertex_Msg
+      --  is the message emitted prior to each vertex. Step denotes the current
+      --  step in the elaboration order. Indent denotes the desired indentation
+      --  level for tracing.
+
       procedure Update_Successor
-        (G               : Library_Graph;
-         Pred            : Library_Graph_Vertex_Id;
-         Succ            : Library_Graph_Vertex_Id;
-         All_Candidates  : LGV_Sets.Membership_Set;
-         Comp_Candidates : LGV_Sets.Membership_Set;
-         Step            : Elaboration_Order_Step;
-         Indent          : Indentation_Level);
+        (G                        : Library_Graph;
+         Edge                     : Library_Graph_Edge_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level);
       pragma Inline (Update_Successor);
-      --  Notify successor vertex Succ of library graph G along with its
-      --  component that their predecessor Pred has just been elaborated.
-      --  This may cause new vertices to become elaborable, and thus be added
-      --  to one of the two sets. All_Candidates is the set of all elaborable
-      --  vertices across the whole library graph. Comp_Candidates is the set
-      --  of all elaborable vertices in the component of Pred. Step is the
-      --  current step in the elaboration order. Indent denotes the desired
-      --  indentation level for tracing.
+      --  Notify the successor of edge Edge of library graph G along with its
+      --  component that their predecessor has just been elaborated. This may
+      --  cause new vertices to become elaborable. The sets contain vertices
+      --  arranged as follows:
+      --
+      --    * All_Elaborable_Vertices - all elaborable vertices in the library
+      --      graph.
+      --
+      --    * All_Waiting_Vertices - all vertices in the library graph that are
+      --      waiting on predecessors to be elaborated.
+      --
+      --    * Comp_Elaborable_Vertices - all elaborable vertices found in the
+      --      component of Vertex.
+      --
+      --    * Comp_Waiting_Vertices - all vertices found in the component of
+      --      Vertex that are still waiting on predecessors to be elaborated.
+      --
+      --  Step is the current step in the elaboration order. Indent denotes the
+      --  desired indentation level for tracing.
 
       procedure Update_Successors
-        (G               : Library_Graph;
-         Pred            : Library_Graph_Vertex_Id;
-         All_Candidates  : LGV_Sets.Membership_Set;
-         Comp_Candidates : LGV_Sets.Membership_Set;
-         Step            : Elaboration_Order_Step;
-         Indent          : Indentation_Level);
+        (G                        : Library_Graph;
+         Vertex                   : Library_Graph_Vertex_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level);
       pragma Inline (Update_Successors);
-      --  Notify all successors along with their components that their
-      --  predecessor vertex Pred of ligrary graph G has just been elaborated.
-      --  This may cause new vertices to become elaborable, and thus be added
-      --  to one of the two sets. All_Candidates is the set of all elaborable
-      --  vertices across the whole library graph. Comp_Candidates is the set
-      --  of all elaborable vertices in the component of Pred. Step is the
-      --  current step in the elaboration order. Indent denotes the desired
-      --  indentation level for tracing.
-
-      ----------------
-      -- Add_Vertex --
-      ----------------
-
-      procedure Add_Vertex
-        (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id;
-         Set    : LGV_Sets.Membership_Set;
-         Msg    : String;
-         Step   : Elaboration_Order_Step;
-         Indent : Indentation_Level)
+      --  Notify all successors of vertex Vertex of library graph G along with
+      --  their components that their predecessor has just been elaborated.
+      --  This may cause new vertices to become elaborable. The sets contain
+      --  vertices arranged as follows:
+      --
+      --    * All_Elaborable_Vertices - all elaborable vertices in the library
+      --      graph.
+      --
+      --    * All_Waiting_Vertices - all vertices in the library graph that are
+      --      waiting on predecessors to be elaborated.
+      --
+      --    * Comp_Elaborable_Vertices - all elaborable vertices found in the
+      --      component of Vertex.
+      --
+      --    * Comp_Waiting_Vertices - all vertices found in the component of
+      --      Vertex that are still waiting on predecessors to be elaborated.
+      --
+      --  Step is the current step in the elaboration order. Indent denotes the
+      --  desired indentation level for tracing.
+
+      ----------------------------------
+      -- Create_Component_Vertex_Sets --
+      ----------------------------------
+
+      procedure Create_Component_Vertex_Sets
+        (G                   : Library_Graph;
+         Comp                : Component_Id;
+         Elaborable_Vertices : out LGV_Sets.Membership_Set;
+         Waiting_Vertices    : out LGV_Sets.Membership_Set;
+         Step                : Elaboration_Order_Step)
       is
-      begin
-         pragma Assert (Present (Vertex));
-         pragma Assert (Needs_Elaboration (G, Vertex));
-         pragma Assert (LGV_Sets.Present (Set));
-
-         --  Add vertex only when it is not present in the set. This is not
-         --  strictly necessary because the set implementation handles this
-         --  case, however the check eliminates spurious traces.
-
-         if not LGV_Sets.Contains (Set, Vertex) then
-            Trace_Vertex
-              (G      => G,
-               Vertex => Vertex,
-               Msg    => Msg,
-               Step   => Step,
-               Indent => Indent);
-
-            LGV_Sets.Insert (Set, Vertex);
-         end if;
-      end Add_Vertex;
+         pragma Assert (Present (G));
+         pragma Assert (Present (Comp));
 
-      ------------------------------
-      -- Add_Vertex_If_Elaborable --
-      ------------------------------
+         Num_Of_Vertices : constant Natural :=
+                             Number_Of_Component_Vertices (G, Comp);
 
-      procedure Add_Vertex_If_Elaborable
-        (G      : Library_Graph;
+         Iter   : Component_Vertex_Iterator;
          Vertex : Library_Graph_Vertex_Id;
-         Set    : LGV_Sets.Membership_Set;
-         Msg    : String;
-         Step   : Elaboration_Order_Step;
-         Indent : Indentation_Level)
-      is
-         Extra_Vertex : Library_Graph_Vertex_Id;
 
       begin
-         pragma Assert (Present (G));
-         pragma Assert (Present (Vertex));
-         pragma Assert (Needs_Elaboration (G, Vertex));
-         pragma Assert (LGV_Sets.Present (Set));
-
-         if Is_Elaborable_Vertex (G, Vertex) then
-            Add_Vertex
-              (G      => G,
-               Vertex => Vertex,
-               Set    => Set,
-               Msg    => Msg,
-               Step   => Step,
-               Indent => Indent);
-
-            --  Assume that there is no extra vertex that needs to be added
+         Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices);
+         Waiting_Vertices    := LGV_Sets.Create (Num_Of_Vertices);
 
-            Extra_Vertex := No_Library_Graph_Vertex;
-
-            --  A spec-body pair where the spec carries pragma Elaborate_Body
-            --  must be treated as one vertex for elaboration purposes. If one
-            --  of them is elaborable, then the other is also elaborable. This
-            --  property is guaranteed by predicate Is_Elaborable_Vertex.
-
-            if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then
-               Extra_Vertex := Proper_Spec (G, Vertex);
-               pragma Assert (Present (Extra_Vertex));
+         Iter := Iterate_Component_Vertices (G, Comp);
+         while Has_Next (Iter) loop
+            Next (Iter, Vertex);
 
-            elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
-               Extra_Vertex := Proper_Body (G, Vertex);
-               pragma Assert (Present (Extra_Vertex));
-            end if;
+            --  Add the vertex to the proper set depending on whether it can be
+            --  elaborated.
 
-            if Present (Extra_Vertex) then
-               pragma Assert (Needs_Elaboration (G, Extra_Vertex));
+            if Is_Elaborable_Vertex (G, Vertex) then
+               Insert_Vertex
+                 (G      => G,
+                  Vertex => Vertex,
+                  Set    => Elaborable_Vertices,
+                  Msg    => "add elaborable component vertex",
+                  Step   => Step,
+                  Indent => No_Indentation);
 
-               Add_Vertex
+            else
+               Insert_Vertex
                  (G      => G,
-                  Vertex => Extra_Vertex,
-                  Set    => Set,
-                  Msg    => Msg,
+                  Vertex => Vertex,
+                  Set    => Waiting_Vertices,
+                  Msg    => "add waiting component vertex",
                   Step   => Step,
-                  Indent => Indent);
+                  Indent => No_Indentation);
             end if;
-         end if;
-      end Add_Vertex_If_Elaborable;
+         end loop;
+      end Create_Component_Vertex_Sets;
 
-      -------------------------------
-      -- Create_All_Candidates_Set --
-      -------------------------------
+      ------------------------
+      -- Create_Vertex_Sets --
+      ------------------------
 
-      function Create_All_Candidates_Set
-        (G    : Library_Graph;
-         Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set
+      procedure Create_Vertex_Sets
+        (G                   : Library_Graph;
+         Elaborable_Vertices : out LGV_Sets.Membership_Set;
+         Waiting_Vertices    : out LGV_Sets.Membership_Set;
+         Step                : Elaboration_Order_Step)
       is
+         pragma Assert (Present (G));
+
+         Num_Of_Vertices : constant Natural := Number_Of_Vertices (G);
+
          Iter   : Library_Graphs.All_Vertex_Iterator;
-         Set    : LGV_Sets.Membership_Set;
          Vertex : Library_Graph_Vertex_Id;
 
       begin
-         pragma Assert (Present (G));
+         Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices);
+         Waiting_Vertices    := LGV_Sets.Create (Num_Of_Vertices);
 
-         Set  := LGV_Sets.Create (Number_Of_Vertices (G));
          Iter := Iterate_All_Vertices (G);
          while Has_Next (Iter) loop
             Next (Iter, Vertex);
 
-            Add_Vertex_If_Elaborable
-              (G      => G,
-               Vertex => Vertex,
-               Set    => Set,
-               Msg    => Add_To_All_Candidates_Msg,
-               Step   => Step,
-               Indent => No_Indentation);
-         end loop;
-
-         return Set;
-      end Create_All_Candidates_Set;
-
-      -------------------------------------
-      -- Create_Component_Candidates_Set --
-      -------------------------------------
-
-      function Create_Component_Candidates_Set
-        (G    : Library_Graph;
-         Comp : Component_Id;
-         Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set
-      is
-         Iter   : Component_Vertex_Iterator;
-         Set    : LGV_Sets.Membership_Set;
-         Vertex : Library_Graph_Vertex_Id;
-
-      begin
-         pragma Assert (Present (G));
-         pragma Assert (Present (Comp));
+            --  Add the vertex to the proper set depending on whether it can be
+            --  elaborated.
 
-         Set  := LGV_Sets.Create (Number_Of_Component_Vertices (G, Comp));
-         Iter := Iterate_Component_Vertices (G, Comp);
-         while Has_Next (Iter) loop
-            Next (Iter, Vertex);
+            if Is_Elaborable_Vertex (G, Vertex) then
+               Insert_Vertex
+                 (G      => G,
+                  Vertex => Vertex,
+                  Set    => Elaborable_Vertices,
+                  Msg    => "add elaborable vertex",
+                  Step   => Step,
+                  Indent => No_Indentation);
 
-            Add_Vertex_If_Elaborable
-              (G      => G,
-               Vertex => Vertex,
-               Set    => Set,
-               Msg    => Add_To_Comp_Candidates_Msg,
-               Step   => Step,
-               Indent => No_Indentation);
+            else
+               Insert_Vertex
+                 (G      => G,
+                  Vertex => Vertex,
+                  Set    => Waiting_Vertices,
+                  Msg    => "add waiting vertex",
+                  Step   => Step,
+                  Indent => No_Indentation);
+            end if;
          end loop;
-
-         return Set;
-      end Create_Component_Candidates_Set;
+      end Create_Vertex_Sets;
 
       -------------------------
       -- Elaborate_Component --
       -------------------------
 
       procedure Elaborate_Component
-        (G                  : Library_Graph;
-         Comp               : Component_Id;
-         All_Candidates     : LGV_Sets.Membership_Set;
-         Remaining_Vertices : in out Natural;
-         Order              : in out Unit_Id_Table;
-         Step               : Elaboration_Order_Step)
+        (G                       : Library_Graph;
+         Comp                    : Component_Id;
+         All_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Order                   : in out Unit_Id_Table;
+         Step                    : Elaboration_Order_Step)
       is
-         Candidate       : Library_Graph_Vertex_Id;
-         Comp_Candidates : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Vertex                   : Library_Graph_Vertex_Id;
 
       begin
          pragma Assert (Present (G));
          pragma Assert (Present (Comp));
-         pragma Assert (LGV_Sets.Present (All_Candidates));
+         pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
 
          Trace_Component
            (G    => G,
@@ -488,35 +512,81 @@ package body Bindo.Elaborators is
             Msg  => "elaborating component",
             Step => Step);
 
-         Comp_Candidates := Create_Component_Candidates_Set (G, Comp, Step);
+         --  Divide all vertices of the component into an elaborable and
+         --  waiting vertex set.
+
+         Create_Component_Vertex_Sets
+           (G                   => G,
+            Comp                => Comp,
+            Elaborable_Vertices => Comp_Elaborable_Vertices,
+            Waiting_Vertices    => Comp_Waiting_Vertices,
+            Step                => Step);
 
          loop
-            Candidate :=
-              Find_Best_Candidate
+            Trace_Vertices
+              (G          => G,
+               Set        => Comp_Elaborable_Vertices,
+               Set_Msg    => "elaborable component vertices",
+               Vertex_Msg => "elaborable component vertex",
+               Step       => Step,
+               Indent     => Nested_Indentation);
+
+            Trace_Vertices
+              (G          => G,
+               Set        => Comp_Waiting_Vertices,
+               Set_Msg    => "waiting component vertices",
+               Vertex_Msg => "waiting component vertex",
+               Step       => Step,
+               Indent     => Nested_Indentation);
+
+            Vertex :=
+              Find_Best_Elaborable_Vertex
                 (G      => G,
-                 Set    => Comp_Candidates,
+                 Set    => Comp_Elaborable_Vertices,
                  Step   => Step,
                  Indent => Nested_Indentation);
 
-            --  Stop the elaboration of the component when there is no suitable
-            --  candidate. This indicates that either all vertices within the
-            --  component have been elaborated, or the library graph contains a
-            --  circularity.
+            --  The component lacks an elaborable vertex. This indicates that
+            --  either all vertices of the component have been elaborated or
+            --  the graph has a circularity. Locate the best weak vertex that
+            --  was compiled with the dynamic model to elaborate from the set
+            --  waiting vertices. This action assumes that certain invocations
+            --  will not take place at elaboration time. An order produced in
+            --  this fashion may fail an ABE check at run time.
+
+            if not Present (Vertex) then
+               Vertex :=
+                 Find_Best_Weakly_Elaborable_Vertex
+                   (G      => G,
+                    Set    => Comp_Waiting_Vertices,
+                    Step   => Step,
+                    Indent => Nested_Indentation);
+            end if;
+
+            --  Stop the elaboration when either all vertices of the component
+            --  have been elaborated, or the graph contains a circularity.
+
+            exit when not Present (Vertex);
 
-            exit when not Present (Candidate);
+            --  Try to elaborate as many vertices within the component as
+            --  possible. Each successful elaboration signals the appropriate
+            --  successors and components that they have one less predecessor
+            --  to wait on.
 
             Elaborate_Vertex
-              (G                  => G,
-               Vertex             => Candidate,
-               All_Candidates     => All_Candidates,
-               Comp_Candidates    => Comp_Candidates,
-               Remaining_Vertices => Remaining_Vertices,
-               Order              => Order,
-               Step               => Step,
-               Indent             => Nested_Indentation);
+              (G                        => G,
+               Vertex                   => Vertex,
+               All_Elaborable_Vertices  => All_Elaborable_Vertices,
+               All_Waiting_Vertices     => All_Waiting_Vertices,
+               Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
+               Comp_Waiting_Vertices    => Comp_Waiting_Vertices,
+               Order                    => Order,
+               Step                     => Step,
+               Indent                   => Nested_Indentation);
          end loop;
 
-         LGV_Sets.Destroy (Comp_Candidates);
+         LGV_Sets.Destroy (Comp_Elaborable_Vertices);
+         LGV_Sets.Destroy (Comp_Waiting_Vertices);
       end Elaborate_Component;
 
       -----------------------------
@@ -528,73 +598,97 @@ package body Bindo.Elaborators is
          Order  : out Unit_Id_Table;
          Status : out Elaboration_Order_Status)
       is
-         All_Candidates     : LGV_Sets.Membership_Set;
-         Candidate          : Library_Graph_Vertex_Id;
-         Remaining_Vertices : Natural;
-         Step               : Elaboration_Order_Step;
+         Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Step                : Elaboration_Order_Step;
+         Vertex              : Library_Graph_Vertex_Id;
+         Waiting_Vertices    : LGV_Sets.Membership_Set;
 
       begin
          pragma Assert (Present (G));
 
          Step := Initial_Step;
 
-         All_Candidates     := Create_All_Candidates_Set (G, Step);
-         Remaining_Vertices := Number_Of_Vertices (G);
+         --  Divide all vertices of the library graph into an elaborable and
+         --  waiting vertex set.
+
+         Create_Vertex_Sets
+           (G                   => G,
+            Elaborable_Vertices => Elaborable_Vertices,
+            Waiting_Vertices    => Waiting_Vertices,
+            Step                => Step);
 
          loop
             Step := Step + 1;
 
-            Trace_Candidate_Vertices
-              (G    => G,
-               Set  => All_Candidates,
-               Step => Step);
-
-            Trace_Unelaborated_Vertices
-              (G     => G,
-               Count => Remaining_Vertices,
-               Step  => Step);
-
-            Candidate :=
-              Find_Best_Candidate
+            Trace_Vertices
+              (G          => G,
+               Set        => Elaborable_Vertices,
+               Set_Msg    => "elaborable vertices",
+               Vertex_Msg => "elaborable vertex",
+               Step       => Step,
+               Indent     => No_Indentation);
+
+            Trace_Vertices
+              (G          => G,
+               Set        => Waiting_Vertices,
+               Set_Msg    => "waiting vertices",
+               Vertex_Msg => "waiting vertex",
+               Step       => Step,
+               Indent     => No_Indentation);
+
+            Vertex :=
+              Find_Best_Elaborable_Vertex
                 (G      => G,
-                 Set    => All_Candidates,
+                 Set    => Elaborable_Vertices,
                  Step   => Step,
                  Indent => No_Indentation);
 
-            --  Stop the elaboration when there is no suitable candidate. This
-            --  indicates that either all units were elaborated or the library
-            --  graph contains a circularity.
+            --  The graph lacks an elaborable vertex. This indicates that
+            --  either all vertices have been elaborated or the graph has a
+            --  circularity. Find the best weak vertex that was compiled with
+            --  the dynamic model to elaborate from set of waiting vertices.
+            --  This action assumes that certain invocations will not take
+            --  place at elaboration time. An order produced in this fashion
+            --  may fail an ABE check at run time.
+
+            if not Present (Vertex) then
+               Vertex :=
+                 Find_Best_Weakly_Elaborable_Vertex
+                   (G      => G,
+                    Set    => Waiting_Vertices,
+                    Step   => Step,
+                    Indent => No_Indentation);
+            end if;
+
+            --  Stop the elaboration when either all vertices of the graph have
+            --  been elaborated, or the graph contains a circularity.
 
-            exit when not Present (Candidate);
+            exit when not Present (Vertex);
 
-            --  Elaborate the component of the candidate vertex by trying to
-            --  elaborate as many vertices within the component as possible.
-            --  Each successful elaboration signals the appropriate successors
-            --  and their components that they have one less predecessor to
-            --  wait on. This may add new candidates to set All_Candidates.
+            --  Elaborate the component of the vertex by trying to elaborate as
+            --  many vertices within the component as possible. Each successful
+            --  elaboration signals the appropriate successors and components
+            --  that they have one less predecessor to wait on.
 
             Elaborate_Component
-              (G                  => G,
-               Comp               => Component (G, Candidate),
-               All_Candidates     => All_Candidates,
-               Remaining_Vertices => Remaining_Vertices,
-               Order              => Order,
-               Step               => Step);
+              (G                       => G,
+               Comp                    => Component (G, Vertex),
+               All_Elaborable_Vertices => Elaborable_Vertices,
+               All_Waiting_Vertices    => Waiting_Vertices,
+               Order                   => Order,
+               Step                    => Step);
          end loop;
 
-         LGV_Sets.Destroy (All_Candidates);
-
-         --  The library graph contains an Elaborate_All circularity when
-         --  at least one edge subject to the related pragma appears in a
-         --  component.
+         --  The graph contains an Elaborate_All circularity when at least one
+         --  edge subject to the related pragma appears in a component.
 
          if Has_Elaborate_All_Cycle (G) then
             Status := Order_Has_Elaborate_All_Circularity;
 
-         --  The library contains a circularity when at least one vertex failed
+         --  The graph contains a circularity when at least one vertex failed
          --  to elaborate.
 
-         elsif Remaining_Vertices /= 0 then
+         elsif LGV_Sets.Size (Waiting_Vertices) /= 0 then
             Status := Order_Has_Circularity;
 
          --  Otherwise the elaboration order is satisfactory
@@ -602,6 +696,9 @@ package body Bindo.Elaborators is
          else
             Status := Order_OK;
          end if;
+
+         LGV_Sets.Destroy (Elaborable_Vertices);
+         LGV_Sets.Destroy (Waiting_Vertices);
       end Elaborate_Library_Graph;
 
       ---------------------
@@ -612,271 +709,114 @@ package body Bindo.Elaborators is
         (Order         : out Unit_Id_Table;
          Main_Lib_File : File_Name_Type)
       is
-         Main_Lib_Unit : constant Unit_Id :=
-                           Corresponding_Unit (Unit_Name_Type (Main_Lib_File));
+         pragma Unreferenced (Main_Lib_File);
 
-      begin
-         pragma Assert (Present (Main_Lib_Unit));
+         Inv_Graph : Invocation_Graph;
+         Lib_Graph : Library_Graph;
+         Status    : Elaboration_Order_Status;
 
+      begin
          --  Initialize all unit-related data structures and gather all units
          --  that need elaboration.
 
          Initialize_Units;
          Collect_Elaborable_Units;
 
-         Write_ALI_Tables;
-
-         --  Choose the proper elaboration strategy based on whether the main
-         --  library unit was compiled using the dynamic model.
-
-         if Is_Dynamically_Elaborated (Main_Lib_Unit) then
-            Elaborate_Units_Dynamic (Order);
-         else
-            Elaborate_Units_Static (Order);
-         end if;
-
-         Validate_Elaboration_Order (Order);
-         Write_Elaboration_Order    (Order);
-
-         --  Enumerate the sources referenced in the closure of the order
-
-         Write_Unit_Closure (Order);
-
-         --  Destroy all unit-delated data structures
-
-         Finalize_Units;
-
-      exception
-         when others =>
-            Finalize_Units;
-            raise;
-      end Elaborate_Units;
-
-      ----------------------------
-      -- Elaborate_Units_Common --
-      ----------------------------
-
-      procedure Elaborate_Units_Common
-        (Use_Inv_Graph : Boolean;
-         Is_Dyn_Elab   : Boolean;
-         Inv_Graph     : out Invocation_Graph;
-         Lib_Graph     : out Library_Graph;
-         Order         : out Unit_Id_Table;
-         Status        : out Elaboration_Order_Status)
-      is
-      begin
-         --  Create, validate, and output the library graph that captures the
-         --  dependencies between library items.
-
-         Lib_Graph := Build_Library_Graph (Is_Dyn_Elab);
-         Validate_Library_Graph (Lib_Graph);
-         Write_Library_Graph    (Lib_Graph);
-
-         --  Create, validate, output, and use the invocation graph that
-         --  represents the flow of execusion only when requested by the
-         --  caller.
+         --  Create the library graph that captures the dependencies between
+         --  library items.
 
-         if Use_Inv_Graph then
-            Inv_Graph := Build_Invocation_Graph (Lib_Graph);
-            Validate_Invocation_Graph (Inv_Graph);
-            Write_Invocation_Graph    (Inv_Graph);
+         Lib_Graph := Build_Library_Graph;
 
-         --  Otherwise the invocation graph is not used. Create a dummy graph
-         --  as this allows for a uniform behavior on the caller side.
+         --  Create the invocation graph that represents the flow of execution
 
-         else
-            Inv_Graph :=
-              Invocation_Graphs.Create
-                (Initial_Vertices => 1,
-                 Initial_Edges    => 1);
-         end if;
+         Inv_Graph := Build_Invocation_Graph (Lib_Graph);
 
          --  Traverse the invocation graph starting from elaboration code in
          --  order to discover transitions of the execution flow from a unit
          --  to a unit that result in extra edges within the library graph.
 
          Augment_Library_Graph (Inv_Graph, Lib_Graph);
-         Write_Library_Graph (Lib_Graph);
 
-         --  Create and output the component graph by collapsing all library
-         --  items into library units and traversing the library graph.
+         --  Create the component graph by collapsing all library items into
+         --  library units and traversing the library graph.
 
-         Find_Components  (Lib_Graph);
-         Write_Components (Lib_Graph);
+         Find_Components (Lib_Graph);
 
-         --  Traverse the library graph to determine the elaboration order of
-         --  units.
+         --  Output the contents of the ALI tables and both graphs to standard
+         --  output now that they have been fully decorated.
 
-         Elaborate_Library_Graph
-           (G      => Lib_Graph,
-            Order  => Order,
-            Status => Status);
-      end Elaborate_Units_Common;
-
-      -----------------------------
-      -- Elaborate_Units_Dynamic --
-      -----------------------------
+         Write_ALI_Tables;
+         Write_Invocation_Graph (Inv_Graph);
+         Write_Library_Graph    (Lib_Graph);
 
-      procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table) is
-         Dyn_Inv_Graph : Invocation_Graph;
-         Dyn_Lib_Graph : Library_Graph;
-         Dyn_Order     : Unit_Id_Table;
-         Mix_Inv_Graph : Invocation_Graph;
-         Mix_Lib_Graph : Library_Graph;
-         Mix_Order     : Unit_Id_Table;
-         Status        : Elaboration_Order_Status;
+         --  Traverse the library graph to determine the elaboration order of
+         --  units.
 
-      begin
-         --  Attempt to elaborate the units in the library graph by mixing in
-         --  the information from the invocation graph. This assumes that all
-         --  invocations will take place at elaboration time.
-
-         Elaborate_Units_Common
-           (Use_Inv_Graph => True,
-            Is_Dyn_Elab   => True,
-            Inv_Graph     => Mix_Inv_Graph,
-            Lib_Graph     => Mix_Lib_Graph,
-            Order         => Mix_Order,
-            Status        => Status);
+         Elaborate_Library_Graph (Lib_Graph, Order, Status);
 
          --  The elaboration order is satisfactory
 
          if Status = Order_OK then
-            Order := Mix_Order;
+            Validate_Elaboration_Order (Order);
 
-            --  Output the dependencies of vertices when switch -e (output
+            --  Output the dependencies among units when switch -e (output
             --  complete list of elaboration order dependencies) is active.
 
-            Write_Dependencies (Mix_Lib_Graph);
-
-         --  The library graph contains an Elaborate_All circularity. There is
-         --  no point in re-elaborating the units without the information from
-         --  the invocation graph because the circularity will persist.
-
-         elsif Status = Order_Has_Elaborate_All_Circularity then
-            Diagnose_Circularities
-              (Inv_Graph => Mix_Inv_Graph,
-               Lib_Graph => Mix_Lib_Graph);
-
-         --  Otherwise the library graph contains a circularity, or the extra
-         --  information provided by the invocation graph caused a circularity.
-         --  Re-elaborate the units without using the invocation graph. This
-         --  assumes that all invocations will not take place at elaboration
-         --  time.
-
-         else
-            pragma Assert (Status = Order_Has_Circularity);
-
-            Elaborate_Units_Common
-              (Use_Inv_Graph => False,
-               Is_Dyn_Elab   => True,
-               Inv_Graph     => Dyn_Inv_Graph,
-               Lib_Graph     => Dyn_Lib_Graph,
-               Order         => Dyn_Order,
-               Status        => Status);
-
-            --  The elaboration order is satisfactory. The elaboration of the
-            --  program may still fail at runtime with an ABE.
-
-            if Status = Order_OK then
-               Order := Dyn_Order;
-
-               --  Output the dependencies of vertices when switch -e (output
-               --  complete list of elaboration order dependencies) is active.
-
-               Write_Dependencies (Dyn_Lib_Graph);
-
-            --  Otherwise the library graph contains a circularity without the
-            --  extra information provided by the invocation graph. Diagnose
-            --  the circularity.
-
-            else
-               Diagnose_Circularities
-                 (Inv_Graph => Dyn_Inv_Graph,
-                  Lib_Graph => Dyn_Lib_Graph);
-            end if;
-
-            Destroy (Dyn_Inv_Graph);
-            Destroy (Dyn_Lib_Graph);
-         end if;
-
-         Destroy (Mix_Inv_Graph);
-         Destroy (Mix_Lib_Graph);
-
-         --  Halt the bind as there is no satisfactory elaboration order
-
-         if Status /= Order_OK then
-            raise Unrecoverable_Error;
-         end if;
-      end Elaborate_Units_Dynamic;
+            Write_Dependencies (Lib_Graph);
 
-      ----------------------------
-      -- Elaborate_Units_Static --
-      ----------------------------
+            --  Output the elaboration order when switch -l (output chosen
+            --  elaboration order) is in effect.
 
-      procedure Elaborate_Units_Static (Order : out Unit_Id_Table) is
-         Inv_Graph : Invocation_Graph;
-         Lib_Graph : Library_Graph;
-         Status    : Elaboration_Order_Status;
+            Write_Elaboration_Order (Order);
 
-      begin
-         --  Attempt to elaborate the units in the library graph by mixing in
-         --  the information from the invocation graph. This assumes that all
-         --  invocations will take place at elaboration time.
-
-         Elaborate_Units_Common
-           (Use_Inv_Graph => True,
-            Is_Dyn_Elab   => False,
-            Inv_Graph     => Inv_Graph,
-            Lib_Graph     => Lib_Graph,
-            Order         => Order,
-            Status        => Status);
-
-         --  The elaboration order is satisfactory. Output the dependencies of
-         --  vertices when switch -e (output complete list of elaboration order
-         --  dependencies) is active.
+            --  Output the sources referenced in the closure of the order when
+            --  switch -R (list sources referenced in closure) is in effect.
 
-         if Status = Order_OK then
-            Write_Dependencies (Lib_Graph);
+            Write_Unit_Closure (Order);
 
-         --  Otherwise the augmented library graph contains a circularity
+         --  Otherwise the library graph contains at least one circularity
 
          else
-            Diagnose_Circularities
-              (Inv_Graph => Inv_Graph,
-               Lib_Graph => Lib_Graph);
+            Diagnose_Circularities (Inv_Graph, Lib_Graph);
          end if;
 
          Destroy (Inv_Graph);
          Destroy (Lib_Graph);
 
-         --  Halt the bind as there is no satisfactory elaboration order
+         --  Destroy all unit-related data structures
+
+         Finalize_Units;
+
+         --  Halt the bind when there is no satisfactory elaboration order
 
          if Status /= Order_OK then
             raise Unrecoverable_Error;
          end if;
-      end Elaborate_Units_Static;
+      end Elaborate_Units;
 
       ----------------------
       -- Elaborate_Vertex --
       ----------------------
 
       procedure Elaborate_Vertex
-        (G                  : Library_Graph;
-         Vertex             : Library_Graph_Vertex_Id;
-         All_Candidates     : LGV_Sets.Membership_Set;
-         Comp_Candidates    : LGV_Sets.Membership_Set;
-         Remaining_Vertices : in out Natural;
-         Order              : in out Unit_Id_Table;
-         Step               : Elaboration_Order_Step;
-         Indent             : Indentation_Level)
+        (G                        : Library_Graph;
+         Vertex                   : Library_Graph_Vertex_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Order                    : in out Unit_Id_Table;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level)
       is
       begin
          pragma Assert (Present (G));
          pragma Assert (Present (Vertex));
          pragma Assert (Needs_Elaboration (G, Vertex));
-         pragma Assert (LGV_Sets.Present (All_Candidates));
-         pragma Assert (LGV_Sets.Present (Comp_Candidates));
+         pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices));
 
          Trace_Vertex
            (G      => G,
@@ -885,14 +825,20 @@ package body Bindo.Elaborators is
             Step   => Step,
             Indent => Indent);
 
-         --  Remove the vertex from both candidate sets. This is needed when
+         --  Remove the vertex from both elaborable sets. This is needed when
          --  the vertex is both an overall best candidate among all vertices,
-         --  and the best candidate within the component. There is no need to
-         --  check that the vertex is present in either set because the set
-         --  implementation handles this case.
+         --  and the best candidate within the component.
+
+         LGV_Sets.Delete (All_Elaborable_Vertices,  Vertex);
+         LGV_Sets.Delete (Comp_Elaborable_Vertices, Vertex);
 
-         LGV_Sets.Delete (All_Candidates,  Vertex);
-         LGV_Sets.Delete (Comp_Candidates, Vertex);
+         --  Remove the vertex from both waiting sets. This is needed when a
+         --  weakly elaborable vertex is both an overall best candidate among
+         --  all waiting vertices and the best waiting candidate within the
+         --  component.
+
+         LGV_Sets.Delete (All_Waiting_Vertices,  Vertex);
+         LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex);
 
          --  Mark the vertex as elaborated in order to prevent further attempts
          --  to re-elaborate it.
@@ -903,202 +849,469 @@ package body Bindo.Elaborators is
 
          Unit_Id_Tables.Append (Order, Unit (G, Vertex));
 
-         --  There is now one fewer vertex to elaborate
-
-         Remaining_Vertices := Remaining_Vertices - 1;
-
          --  Notify all successors and their components that they have one
          --  fewer predecessor to wait on. This may cause some successors to
          --  be included in one of the sets.
 
          Update_Successors
-           (G               => G,
-            Pred            => Vertex,
-            All_Candidates  => All_Candidates,
-            Comp_Candidates => Comp_Candidates,
-            Step            => Step,
-            Indent          => Indent + Nested_Indentation);
-
-         --  The vertex denotes a spec with a completing body, and is subject
-         --  to pragma Elaborate_Body. Elaborate the body in order to satisfy
-         --  the semantics of the pragma.
-
-         if Is_Spec_With_Elaborate_Body (G, Vertex) then
+           (G                        => G,
+            Vertex                   => Vertex,
+            All_Elaborable_Vertices  => All_Elaborable_Vertices,
+            All_Waiting_Vertices     => All_Waiting_Vertices,
+            Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
+            Comp_Waiting_Vertices    => Comp_Waiting_Vertices,
+            Step                     => Step,
+            Indent                   => Indent + Nested_Indentation);
+
+         --  Elaborate an eligible completing body immediately after its spec.
+         --  This action satisfies the semantics of pragma Elaborate_Body. In
+         --  addition, it ensures that a body will not "drift" too far from its
+         --  spec in case invocation edges are removed from the library graph.
+
+         if Has_Elaborable_Body (G, Vertex) then
             Elaborate_Vertex
-              (G                  => G,
-               Vertex             => Proper_Body (G, Vertex),
-               All_Candidates     => All_Candidates,
-               Comp_Candidates    => Comp_Candidates,
-               Remaining_Vertices => Remaining_Vertices,
-               Order              => Order,
-               Step               => Step,
-               Indent             => Indent);
+              (G                        => G,
+               Vertex                   => Proper_Body (G, Vertex),
+               All_Elaborable_Vertices  => All_Elaborable_Vertices,
+               All_Waiting_Vertices     => All_Waiting_Vertices,
+               Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
+               Comp_Waiting_Vertices    => Comp_Waiting_Vertices,
+               Order                    => Order,
+               Step                     => Step,
+               Indent                   => Indent);
          end if;
       end Elaborate_Vertex;
 
-      -------------------------
-      -- Find_Best_Candidate --
-      -------------------------
+      ---------------------------------
+      -- Find_Best_Elaborable_Vertex --
+      ---------------------------------
 
-      function Find_Best_Candidate
+      function Find_Best_Elaborable_Vertex
         (G      : Library_Graph;
          Set    : LGV_Sets.Membership_Set;
          Step   : Elaboration_Order_Step;
          Indent : Indentation_Level) return Library_Graph_Vertex_Id
       is
-         Best    : Library_Graph_Vertex_Id;
-         Current : Library_Graph_Vertex_Id;
-         Iter    : LGV_Sets.Iterator;
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (LGV_Sets.Present (Set));
+
+         return
+           Find_Best_Vertex
+             (G                   => G,
+              Set                 => Set,
+              Is_Suitable_Vertex  =>
+                Is_Suitable_Elaborable_Vertex'Access,
+              Compare_Vertices    =>
+                Is_Better_Elaborable_Vertex'Access,
+              Initial_Best_Msg    => "initial best elaborable vertex",
+              Subsequent_Best_Msg => "better elaborable vertex",
+              Step                => Step,
+              Indent              => Indent);
+      end Find_Best_Elaborable_Vertex;
+
+      ----------------------
+      -- Find_Best_Vertex --
+      ----------------------
+
+      function Find_Best_Vertex
+        (G                   : Library_Graph;
+         Set                 : LGV_Sets.Membership_Set;
+         Is_Suitable_Vertex  : Predicate_Ptr;
+         Compare_Vertices    : Comparator_Ptr;
+         Initial_Best_Msg    : String;
+         Subsequent_Best_Msg : String;
+         Step                : Elaboration_Order_Step;
+         Indent              : Indentation_Level)
+         return Library_Graph_Vertex_Id
+      is
+         Best_Vertex    : Library_Graph_Vertex_Id;
+         Current_Vertex : Library_Graph_Vertex_Id;
+         Iter           : LGV_Sets.Iterator;
 
       begin
          pragma Assert (Present (G));
          pragma Assert (LGV_Sets.Present (Set));
+         pragma Assert (Is_Suitable_Vertex /= null);
+         pragma Assert (Compare_Vertices /= null);
 
          --  Assume that there is no candidate
 
-         Best := No_Library_Graph_Vertex;
+         Best_Vertex := No_Library_Graph_Vertex;
 
-         --  Inspect all vertices in the set, looking for the best candidate to
-         --  elaborate.
+         --  Inspect all vertices in the set, looking for the best candidate
+         --  according to the comparator.
 
          Iter := LGV_Sets.Iterate (Set);
          while LGV_Sets.Has_Next (Iter) loop
-            LGV_Sets.Next (Iter, Current);
-            pragma Assert (Needs_Elaboration (G, Current));
+            LGV_Sets.Next (Iter, Current_Vertex);
+            pragma Assert (Needs_Elaboration (G, Current_Vertex));
+
+            if Is_Suitable_Vertex.all (G, Current_Vertex) then
+
+               --  A previous iteration already picked the best candidate.
+               --  Update the best candidate when the current vertex is a
+               --  better choice.
+
+               if Present (Best_Vertex) then
+                  if Compare_Vertices.all
+                       (G           => G,
+                        Vertex      => Current_Vertex,
+                        Compared_To => Best_Vertex) = Higher_Precedence
+                  then
+                     Best_Vertex := Current_Vertex;
+
+                     Trace_Vertex
+                       (G      => G,
+                        Vertex => Best_Vertex,
+                        Msg    => Subsequent_Best_Msg,
+                        Step   => Step,
+                        Indent => Indent);
+                  end if;
+
+               --  Otherwise this is the first candidate
+
+               else
+                  Best_Vertex := Current_Vertex;
+
+                  Trace_Vertex
+                    (G      => G,
+                     Vertex => Best_Vertex,
+                     Msg    => Initial_Best_Msg,
+                     Step   => Step,
+                     Indent => Indent);
+               end if;
+            end if;
+         end loop;
 
-            --  Update the best candidate when there is no such candidate
+         return Best_Vertex;
+      end Find_Best_Vertex;
 
-            if not Present (Best) then
-               Best := Current;
+      ----------------------------------------
+      -- Find_Best_Weakly_Elaborable_Vertex --
+      ----------------------------------------
 
-               Trace_Vertex
-                 (G      => G,
-                  Vertex => Best,
-                  Msg    => "initial best candidate vertex",
-                  Step   => Step,
-                  Indent => Indent);
+      function Find_Best_Weakly_Elaborable_Vertex
+        (G      : Library_Graph;
+         Set    : LGV_Sets.Membership_Set;
+         Step   : Elaboration_Order_Step;
+         Indent : Indentation_Level) return Library_Graph_Vertex_Id
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (LGV_Sets.Present (Set));
 
-            --  Update the best candidate when the current vertex is a better
-            --  choice.
+         return
+           Find_Best_Vertex
+             (G                   => G,
+              Set                 => Set,
+              Is_Suitable_Vertex  =>
+                Is_Suitable_Weakly_Elaborable_Vertex'Access,
+              Compare_Vertices    =>
+                Is_Better_Weakly_Elaborable_Vertex'Access,
+              Initial_Best_Msg    => "initial best weakly elaborable vertex",
+              Subsequent_Best_Msg => "better weakly elaborable vertex",
+              Step                => Step,
+              Indent              => Indent);
+      end Find_Best_Weakly_Elaborable_Vertex;
 
-            elsif Is_Better_Candidate
-                    (G           => G,
-                     Best_Candidate => Best,
-                     New_Candidate  => Current)
-            then
-               Best := Current;
+      -------------------------
+      -- Has_Elaborable_Body --
+      -------------------------
 
-               Trace_Vertex
-                 (G      => G,
-                  Vertex => Best,
-                  Msg    => "best candidate vertex",
-                  Step   => Step,
-                  Indent => Indent);
-            end if;
-         end loop;
+      function Has_Elaborable_Body
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
 
-         return Best;
-      end Find_Best_Candidate;
+         --  The body of an already-elaborated spec subject to Elaborate_Body
+         --  is always elaborable.
 
-      -------------------------
-      -- Is_Better_Candidate --
-      -------------------------
+         if Is_Spec_With_Elaborate_Body (G, Vertex) then
+            return True;
+
+         elsif Is_Spec_With_Body (G, Vertex) then
+            return Is_Elaborable_Vertex (G, Proper_Body (G, Vertex));
+         end if;
+
+         return False;
+      end Has_Elaborable_Body;
+
+      ---------------------------------
+      -- Insert_Elaborable_Successor --
+      ---------------------------------
+
+      procedure Insert_Elaborable_Successor
+        (G                     : Library_Graph;
+         Vertex                : Library_Graph_Vertex_Id;
+         Elaborable_Vertices   : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices  : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices : LGV_Sets.Membership_Set;
+         Msg                   : String;
+         Step                  : Elaboration_Order_Step;
+         Indent                : Indentation_Level)
+      is
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+         pragma Assert (LGV_Sets.Present (Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices));
+
+         Complement : constant Library_Graph_Vertex_Id :=
+                        Complementary_Vertex
+                          (G                => G,
+                           Vertex           => Vertex,
+                           Force_Complement => False);
+
+      begin
+         --  Remove the successor from both waiting vertex sets because it may
+         --  be the best vertex to elaborate across the whole graph and within
+         --  its component.
+
+         LGV_Sets.Delete (All_Waiting_Vertices,  Vertex);
+         LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex);
+
+         Insert_Vertex
+           (G      => G,
+            Vertex => Vertex,
+            Set    => Elaborable_Vertices,
+            Msg    => Msg,
+            Step   => Step,
+            Indent => Indent);
+
+         if Present (Complement) then
+
+            --  Remove the complement of the successor from both waiting vertex
+            --  sets because it may be the best vertex to elaborate across the
+            --  whole graph and within its component.
+
+            LGV_Sets.Delete (All_Waiting_Vertices,  Complement);
+            LGV_Sets.Delete (Comp_Waiting_Vertices, Complement);
+
+            Insert_Vertex
+              (G      => G,
+               Vertex => Complement,
+               Set    => Elaborable_Vertices,
+               Msg    => Msg,
+               Step   => Step,
+               Indent => Indent);
+         end if;
+      end Insert_Elaborable_Successor;
+
+      -------------------
+      -- Insert_Vertex --
+      -------------------
+
+      procedure Insert_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id;
+         Set    : LGV_Sets.Membership_Set;
+         Msg    : String;
+         Step   : Elaboration_Order_Step;
+         Indent : Indentation_Level)
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+         pragma Assert (Needs_Elaboration (G, Vertex));
+         pragma Assert (LGV_Sets.Present (Set));
+
+         --  Nothing to do when the vertex is already present in the set
 
-      function Is_Better_Candidate
-        (G              : Library_Graph;
-         Best_Candidate : Library_Graph_Vertex_Id;
-         New_Candidate  : Library_Graph_Vertex_Id) return Boolean
+         if LGV_Sets.Contains (Set, Vertex) then
+            return;
+         end if;
+
+         Trace_Vertex
+           (G      => G,
+            Vertex => Vertex,
+            Msg    => Msg,
+            Step   => Step,
+            Indent => Indent);
+
+         --  Add the vertex to the set
+
+         LGV_Sets.Insert (Set, Vertex);
+      end Insert_Vertex;
+
+      ---------------------------------
+      -- Is_Better_Elaborable_Vertex --
+      ---------------------------------
+
+      function Is_Better_Elaborable_Vertex
+        (G           : Library_Graph;
+         Vertex      : Library_Graph_Vertex_Id;
+         Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind
       is
       begin
          pragma Assert (Present (G));
-         pragma Assert (Present (Best_Candidate));
-         pragma Assert (Present (New_Candidate));
+         pragma Assert (Present (Vertex));
+         pragma Assert (Present (Compared_To));
+
+         --  Prefer a spec with Elaborate_Body over its corresponding body
+
+         if Is_Elaborate_Body_Pair
+              (G           => G,
+               Spec_Vertex => Vertex,
+               Body_Vertex => Compared_To)
+         then
+            return Higher_Precedence;
+
+         elsif Is_Elaborate_Body_Pair
+                 (G           => G,
+                  Spec_Vertex => Compared_To,
+                  Body_Vertex => Vertex)
+         then
+            return Lower_Precedence;
 
          --  Prefer a predefined unit over a non-predefined unit
 
-         if Is_Predefined_Unit (G, Best_Candidate)
-           and then not Is_Predefined_Unit (G, New_Candidate)
+         elsif Is_Predefined_Unit (G, Vertex)
+           and then not Is_Predefined_Unit (G, Compared_To)
          then
-            return False;
+            return Higher_Precedence;
 
-         elsif not Is_Predefined_Unit (G, Best_Candidate)
-           and then Is_Predefined_Unit (G, New_Candidate)
+         elsif not Is_Predefined_Unit (G, Vertex)
+           and then Is_Predefined_Unit (G, Compared_To)
          then
-            return True;
+            return Lower_Precedence;
 
-         --  Prefer an internal unit over a non-iternal unit
+         --  Prefer an internal unit over a non-internal unit
 
-         elsif Is_Internal_Unit (G, Best_Candidate)
-           and then not Is_Internal_Unit (G, New_Candidate)
+         elsif Is_Internal_Unit (G, Vertex)
+           and then not Is_Internal_Unit (G, Compared_To)
          then
-            return False;
+            return Higher_Precedence;
 
-         elsif not Is_Internal_Unit (G, Best_Candidate)
-           and then Is_Internal_Unit (G, New_Candidate)
+         elsif not Is_Internal_Unit (G, Vertex)
+           and then Is_Internal_Unit (G, Compared_To)
          then
-            return True;
+            return Lower_Precedence;
 
          --  Prefer a preelaborated unit over a non-preelaborated unit
 
-         elsif Is_Preelaborated_Unit (G, Best_Candidate)
-           and then not Is_Preelaborated_Unit (G, New_Candidate)
+         elsif Is_Preelaborated_Unit (G, Vertex)
+           and then not Is_Preelaborated_Unit (G, Compared_To)
          then
-            return False;
+            return Higher_Precedence;
 
-         elsif not Is_Preelaborated_Unit (G, Best_Candidate)
-           and then Is_Preelaborated_Unit (G, New_Candidate)
+         elsif not Is_Preelaborated_Unit (G, Vertex)
+           and then Is_Preelaborated_Unit (G, Compared_To)
          then
-            return True;
+            return Lower_Precedence;
 
          --  Otherwise default to lexicographical order to ensure deterministic
          --  behavior.
 
+         elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then
+            return Higher_Precedence;
+
          else
-            return
-              Uname_Less (Name (G, Best_Candidate), Name (G, New_Candidate));
+            return Lower_Precedence;
          end if;
-      end Is_Better_Candidate;
+      end Is_Better_Elaborable_Vertex;
 
-      ------------------------------
-      -- Trace_Candidate_Vertices --
-      ------------------------------
+      ----------------------------------------
+      -- Is_Better_Weakly_Elaborable_Vertex --
+      ----------------------------------------
 
-      procedure Trace_Candidate_Vertices
-        (G    : Library_Graph;
-         Set  : LGV_Sets.Membership_Set;
-         Step : Elaboration_Order_Step)
+      function Is_Better_Weakly_Elaborable_Vertex
+        (G           : Library_Graph;
+         Vertex      : Library_Graph_Vertex_Id;
+         Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind
       is
-         Iter   : LGV_Sets.Iterator;
-         Vertex : Library_Graph_Vertex_Id;
+         Comp_Strong_Preds   : Natural;
+         Comp_Weak_Preds     : Natural;
+         Vertex_Strong_Preds : Natural;
+         Vertex_Weak_Preds   : Natural;
 
       begin
          pragma Assert (Present (G));
-         pragma Assert (LGV_Sets.Present (Set));
+         pragma Assert (Present (Vertex));
+         pragma Assert (Present (Compared_To));
 
-         --  Nothing to do when switch -d_T (output elaboration order and cycle
-         --  detection trace information) is not in effect.
+         --  Obtain the number of pending predecessors for both candidates,
+         --  taking into account Elaborate_Body pairs.
 
-         if not Debug_Flag_Underscore_TT then
-            return;
+         Pending_Predecessors_For_Elaboration
+           (G            => G,
+            Vertex       => Vertex,
+            Strong_Preds => Vertex_Strong_Preds,
+            Weak_Preds   => Vertex_Weak_Preds);
+
+         Pending_Predecessors_For_Elaboration
+           (G            => G,
+            Vertex       => Compared_To,
+            Strong_Preds => Comp_Strong_Preds,
+            Weak_Preds   => Comp_Weak_Preds);
+
+         --  Neither candidate should be waiting on strong predecessors,
+         --  otherwise the candidate cannot be weakly elaborated.
+
+         pragma Assert (Vertex_Strong_Preds = 0);
+         pragma Assert (Comp_Strong_Preds   = 0);
+
+         --  Prefer a unit with fewer weak predecessors over a unit with more
+         --  weak predecessors.
+
+         if Vertex_Weak_Preds < Comp_Weak_Preds then
+            return Higher_Precedence;
+
+         elsif Vertex_Weak_Preds > Comp_Weak_Preds then
+            return Lower_Precedence;
+
+         --  Otherwise default to lexicographical order to ensure deterministic
+         --  behavior.
+
+         elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then
+            return Higher_Precedence;
+
+         else
+            return Lower_Precedence;
          end if;
+      end Is_Better_Weakly_Elaborable_Vertex;
 
-         Trace_Step (Step);
-         Write_Str  ("candidate vertices: ");
-         Write_Int  (Int (LGV_Sets.Size (Set)));
-         Write_Eol;
+      -----------------------------------
+      -- Is_Suitable_Elaborable_Vertex --
+      -----------------------------------
 
-         Iter := LGV_Sets.Iterate (Set);
-         while LGV_Sets.Has_Next (Iter) loop
-            LGV_Sets.Next (Iter, Vertex);
+      function Is_Suitable_Elaborable_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
 
-            Trace_Vertex
-              (G      => G,
-               Vertex => Vertex,
-               Msg    => "candidate vertex",
-               Step   => Step,
-               Indent => Nested_Indentation);
-         end loop;
-      end Trace_Candidate_Vertices;
+         --  A vertex is suitable for elaboration as long it is not waiting on
+         --  any predecessors, ignoring the static or dynamic model.
+
+         return Is_Elaborable_Vertex (G, Vertex);
+      end Is_Suitable_Elaborable_Vertex;
+
+      ------------------------------------------
+      -- Is_Suitable_Weakly_Elaborable_Vertex --
+      ------------------------------------------
+
+      function Is_Suitable_Weakly_Elaborable_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+
+         --  A vertex is suitable for weak elaboration when it is waiting on
+         --  weak predecessors only, and the unit it represents was compiled
+         --  using the dynamic model.
+
+         return
+           Is_Dynamically_Elaborated (G, Vertex)
+             and then Is_Weakly_Elaborable_Vertex (G, Vertex);
+      end Is_Suitable_Weakly_Elaborable_Vertex;
 
       ---------------------
       -- Trace_Component --
@@ -1130,8 +1343,14 @@ package body Bindo.Elaborators is
 
          Trace_Step (Step);
          Indent_By  (Nested_Indentation);
-         Write_Str  ("pending predecessors: ");
-         Write_Num  (Int (Pending_Predecessors (G, Comp)));
+         Write_Str  ("pending strong predecessors: ");
+         Write_Num  (Int (Pending_Strong_Predecessors (G, Comp)));
+         Write_Eol;
+
+         Trace_Step (Step);
+         Indent_By  (Nested_Indentation);
+         Write_Str  ("pending weak predecessors  : ");
+         Write_Num  (Int (Pending_Weak_Predecessors (G, Comp)));
          Write_Eol;
       end Trace_Component;
 
@@ -1154,50 +1373,6 @@ package body Bindo.Elaborators is
          Write_Str (": ");
       end Trace_Step;
 
-      ---------------------------------
-      -- Trace_Unelaborated_Vertices --
-      ---------------------------------
-
-      procedure Trace_Unelaborated_Vertices
-        (G     : Library_Graph;
-         Count : Natural;
-         Step  : Elaboration_Order_Step)
-      is
-         Iter   : Library_Graphs.All_Vertex_Iterator;
-         Vertex : Library_Graph_Vertex_Id;
-
-      begin
-         pragma Assert (Present (G));
-
-         --  Nothing to do when switch -d_T (output elaboration order and cycle
-         --  detection trace information) is not in effect.
-
-         if not Debug_Flag_Underscore_TT then
-            return;
-         end if;
-
-         Trace_Step (Step);
-         Write_Str  ("remaining unelaborated vertices: ");
-         Write_Int  (Int (Count));
-         Write_Eol;
-
-         Iter := Iterate_All_Vertices (G);
-         while Has_Next (Iter) loop
-            Next (Iter, Vertex);
-
-            if Needs_Elaboration (G, Vertex)
-              and then not In_Elaboration_Order (G, Vertex)
-            then
-               Trace_Vertex
-                 (G      => G,
-                  Vertex => Vertex,
-                  Msg    => "remaining vertex",
-                  Step   => Step,
-                  Indent => Nested_Indentation);
-            end if;
-         end loop;
-      end Trace_Unelaborated_Vertices;
-
       ------------------
       -- Trace_Vertex --
       ------------------
@@ -1247,37 +1422,104 @@ package body Bindo.Elaborators is
 
          Trace_Step (Step);
          Indent_By  (Attr_Indent);
-         Write_Str  ("pending predecessors: ");
-         Write_Num  (Int (Pending_Predecessors (G, Vertex)));
+         Write_Str  ("pending strong predecessors: ");
+         Write_Num  (Int (Pending_Strong_Predecessors (G, Vertex)));
+         Write_Eol;
+
+         Trace_Step (Step);
+         Indent_By  (Attr_Indent);
+         Write_Str  ("pending weak predecessors  : ");
+         Write_Num  (Int (Pending_Weak_Predecessors (G, Vertex)));
          Write_Eol;
 
          Trace_Step (Step);
          Indent_By  (Attr_Indent);
-         Write_Str  ("pending components  : ");
-         Write_Num  (Int (Pending_Predecessors (G, Comp)));
+         Write_Str  ("pending strong components  : ");
+         Write_Num  (Int (Pending_Strong_Predecessors (G, Comp)));
+         Write_Eol;
+
+         Trace_Step (Step);
+         Indent_By  (Attr_Indent);
+         Write_Str  ("pending weak components    : ");
+         Write_Num  (Int (Pending_Weak_Predecessors (G, Comp)));
          Write_Eol;
       end Trace_Vertex;
 
+      --------------------
+      -- Trace_Vertices --
+      --------------------
+
+      procedure Trace_Vertices
+        (G          : Library_Graph;
+         Set        : LGV_Sets.Membership_Set;
+         Set_Msg    : String;
+         Vertex_Msg : String;
+         Step       : Elaboration_Order_Step;
+         Indent     : Indentation_Level)
+      is
+         Vertex_Indent : constant Indentation_Level :=
+                           Indent + Nested_Indentation;
+
+         Iter   : LGV_Sets.Iterator;
+         Vertex : Library_Graph_Vertex_Id;
+
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (LGV_Sets.Present (Set));
+
+         --  Nothing to do when switch -d_T (output elaboration order and cycle
+         --  detection trace information) is not in effect.
+
+         if not Debug_Flag_Underscore_TT then
+            return;
+         end if;
+
+         Trace_Step (Step);
+         Indent_By  (Indent);
+         Write_Str  (Set_Msg);
+         Write_Str  (": ");
+         Write_Int  (Int (LGV_Sets.Size (Set)));
+         Write_Eol;
+
+         Iter := LGV_Sets.Iterate (Set);
+         while LGV_Sets.Has_Next (Iter) loop
+            LGV_Sets.Next (Iter, Vertex);
+
+            Trace_Vertex
+              (G      => G,
+               Vertex => Vertex,
+               Msg    => Vertex_Msg,
+               Step   => Step,
+               Indent => Vertex_Indent);
+         end loop;
+      end Trace_Vertices;
+
       ----------------------
       -- Update_Successor --
       ----------------------
 
       procedure Update_Successor
-        (G               : Library_Graph;
-         Pred            : Library_Graph_Vertex_Id;
-         Succ            : Library_Graph_Vertex_Id;
-         All_Candidates  : LGV_Sets.Membership_Set;
-         Comp_Candidates : LGV_Sets.Membership_Set;
-         Step            : Elaboration_Order_Step;
-         Indent          : Indentation_Level)
+        (G                        : Library_Graph;
+         Edge                     : Library_Graph_Edge_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level)
       is
          pragma Assert (Present (G));
-         pragma Assert (Present (Pred));
+         pragma Assert (Present (Edge));
+         pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices));
+
+         Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge);
+         Succ : constant Library_Graph_Vertex_Id := Successor   (G, Edge);
+
          pragma Assert (Needs_Elaboration (G, Pred));
-         pragma Assert (Present (Succ));
          pragma Assert (Needs_Elaboration (G, Succ));
-         pragma Assert (LGV_Sets.Present (All_Candidates));
-         pragma Assert (LGV_Sets.Present (Comp_Candidates));
 
          In_Different_Components : constant Boolean :=
                                      not In_Same_Component
@@ -1289,10 +1531,8 @@ package body Bindo.Elaborators is
          Vertex_Indent : constant Indentation_Level :=
                            Indent + Nested_Indentation;
 
-         Candidate : Library_Graph_Vertex_Id;
-         Iter      : Component_Vertex_Iterator;
-         Msg       : String_Ptr;
-         Set       : LGV_Sets.Membership_Set;
+         Iter   : Component_Vertex_Iterator;
+         Vertex : Library_Graph_Vertex_Id;
 
       begin
          Trace_Vertex
@@ -1305,45 +1545,61 @@ package body Bindo.Elaborators is
          --  Notify the successor that it has one less predecessor to wait on.
          --  This effectively eliminates the edge that links the two.
 
-         Decrement_Pending_Predecessors (G, Succ);
+         Decrement_Pending_Predecessors
+           (G      => G,
+            Vertex => Succ,
+            Edge   => Edge);
 
          --  The predecessor and successor reside in different components.
          --  Notify the successor component it has one fewer components to
          --  wait on.
 
          if In_Different_Components then
-            Decrement_Pending_Predecessors (G, Succ_Comp);
+            Decrement_Pending_Predecessors
+              (G    => G,
+               Comp => Succ_Comp,
+               Edge => Edge);
          end if;
 
          --  At this point the successor may become elaborable when its final
-         --  predecessor or final predecessor component is elaborated.
-
-         --  The predecessor and successor reside in different components.
-         --  The successor must not be added to the candidates of Pred's
-         --  component because this will mix units from the two components.
-         --  Instead, the successor is added to the set of all candidates
-         --  that must be elaborated.
+         --  predecessor or final predecessor component has been elaborated.
+
+         if Is_Elaborable_Vertex (G, Succ) then
+
+            --  The predecessor and successor reside in different components.
+            --  The successor must not be added to the candidates of Pred's
+            --  component because this will mix units from the two components.
+            --  Instead, the successor is added to the set of all elaborable
+            --  vertices.
+
+            if In_Different_Components then
+               Insert_Elaborable_Successor
+                 (G                     => G,
+                  Vertex                => Succ,
+                  Elaborable_Vertices   => All_Elaborable_Vertices,
+                  All_Waiting_Vertices  => All_Waiting_Vertices,
+                  Comp_Waiting_Vertices => Comp_Waiting_Vertices,
+                  Msg                   => "add elaborable successor",
+                  Step                  => Step,
+                  Indent                => Vertex_Indent);
+
+            --  Otherwise the predecessor and successor reside within the same
+            --  component. Pred's component gains another elaborable vertex.
 
-         if In_Different_Components then
-            Msg := Add_To_All_Candidates_Msg'Access;
-            Set := All_Candidates;
-
-         --  Otherwise the predecessor and successor reside within the same
-         --  component. Pred's component gains another elaborable node.
-
-         else
-            Msg := Add_To_Comp_Candidates_Msg'Access;
-            Set := Comp_Candidates;
+            else
+               Insert_Elaborable_Successor
+                 (G                     => G,
+                  Vertex                => Succ,
+                  Elaborable_Vertices   => Comp_Elaborable_Vertices,
+                  All_Waiting_Vertices  => All_Waiting_Vertices,
+                  Comp_Waiting_Vertices => Comp_Waiting_Vertices,
+                  Msg                   =>
+                    "add elaborable component successor",
+                  Step                  => Step,
+                  Indent                => Vertex_Indent);
+            end if;
          end if;
 
-         Add_Vertex_If_Elaborable
-           (G      => G,
-            Vertex => Succ,
-            Set    => Set,
-            Msg    => Msg.all,
-            Step   => Step,
-            Indent => Vertex_Indent);
-
          --  At this point the successor component may become elaborable when
          --  its final predecessor component is elaborated. This in turn may
          --  allow vertices of the successor component to be elaborated.
@@ -1353,15 +1609,19 @@ package body Bindo.Elaborators is
          then
             Iter := Iterate_Component_Vertices (G, Succ_Comp);
             while Has_Next (Iter) loop
-               Next (Iter, Candidate);
-
-               Add_Vertex_If_Elaborable
-                 (G      => G,
-                  Vertex => Candidate,
-                  Set    => All_Candidates,
-                  Msg    => Add_To_All_Candidates_Msg,
-                  Step   => Step,
-                  Indent => Vertex_Indent);
+               Next (Iter, Vertex);
+
+               if Is_Elaborable_Vertex (G, Vertex) then
+                  Insert_Elaborable_Successor
+                    (G                     => G,
+                     Vertex                => Vertex,
+                     Elaborable_Vertices   => All_Elaborable_Vertices,
+                     All_Waiting_Vertices  => All_Waiting_Vertices,
+                     Comp_Waiting_Vertices => Comp_Waiting_Vertices,
+                     Msg                   => "add elaborable vertex",
+                     Step                  => Step,
+                     Indent                => Vertex_Indent);
+               end if;
             end loop;
          end if;
       end Update_Successor;
@@ -1371,36 +1631,41 @@ package body Bindo.Elaborators is
       -----------------------
 
       procedure Update_Successors
-        (G               : Library_Graph;
-         Pred            : Library_Graph_Vertex_Id;
-         All_Candidates  : LGV_Sets.Membership_Set;
-         Comp_Candidates : LGV_Sets.Membership_Set;
-         Step            : Elaboration_Order_Step;
-         Indent          : Indentation_Level)
+        (G                        : Library_Graph;
+         Vertex                   : Library_Graph_Vertex_Id;
+         All_Elaborable_Vertices  : LGV_Sets.Membership_Set;
+         All_Waiting_Vertices     : LGV_Sets.Membership_Set;
+         Comp_Elaborable_Vertices : LGV_Sets.Membership_Set;
+         Comp_Waiting_Vertices    : LGV_Sets.Membership_Set;
+         Step                     : Elaboration_Order_Step;
+         Indent                   : Indentation_Level)
       is
          Edge : Library_Graph_Edge_Id;
          Iter : Edges_To_Successors_Iterator;
 
       begin
          pragma Assert (Present (G));
-         pragma Assert (Present (Pred));
-         pragma Assert (Needs_Elaboration (G, Pred));
-         pragma Assert (LGV_Sets.Present (All_Candidates));
-         pragma Assert (LGV_Sets.Present (Comp_Candidates));
+         pragma Assert (Present (Vertex));
+         pragma Assert (Needs_Elaboration (G, Vertex));
+         pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (All_Waiting_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices));
+         pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices));
 
-         Iter := Iterate_Edges_To_Successors (G, Pred);
+         Iter := Iterate_Edges_To_Successors (G, Vertex);
          while Has_Next (Iter) loop
             Next (Iter, Edge);
-            pragma Assert (Predecessor (G, Edge) = Pred);
+            pragma Assert (Predecessor (G, Edge) = Vertex);
 
             Update_Successor
-              (G               => G,
-               Pred            => Pred,
-               Succ            => Successor (G, Edge),
-               All_Candidates  => All_Candidates,
-               Comp_Candidates => Comp_Candidates,
-               Step            => Step,
-               Indent          => Indent);
+              (G                        => G,
+               Edge                     => Edge,
+               All_Elaborable_Vertices  => All_Elaborable_Vertices,
+               All_Waiting_Vertices     => All_Waiting_Vertices,
+               Comp_Elaborable_Vertices => Comp_Elaborable_Vertices,
+               Comp_Waiting_Vertices    => Comp_Waiting_Vertices,
+               Step                     => Step,
+               Indent                   => Indent);
          end loop;
       end Update_Successors;
    end Invocation_And_Library_Graph_Elaborators;
index c68e367d56799ddd9a4fdaf7d5556919966077cc..387d969f74e327aedfb9973392db0ccaa7b5dc84 100644 (file)
@@ -205,7 +205,7 @@ package body Bindo.Graphs is
         (G   : Invocation_Graph;
          Rel : Source_Target_Relation) return Boolean;
       pragma Inline (Is_Existing_Source_Target_Relation);
-      --  Determine whether a source vertex and a target vertex desctibed by
+      --  Determine whether a source vertex and a target vertex described by
       --  relation Rel are already related in invocation graph G.
 
       procedure Save_Elaboration_Root
@@ -226,7 +226,7 @@ package body Bindo.Graphs is
          Rel : Source_Target_Relation;
          Val : Boolean := True);
       pragma Inline (Set_Is_Existing_Source_Target_Relation);
-      --  Mark a source vertex and a target vertex desctibed by relation Rel as
+      --  Mark a source vertex and a target vertex described by relation Rel as
       --  already related in invocation graph G depending on value Val.
 
       procedure Set_IGE_Attributes
@@ -1026,18 +1026,6 @@ package body Bindo.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 --
       -----------------------
@@ -1064,7 +1052,7 @@ package body Bindo.Graphs is
          Attrs  : Library_Graph_Cycle_Attributes;
          Indent : Indentation_Level);
       pragma Inline (Add_Cycle);
-      --  Store a cycle described by attribytes Attrs in library graph G,
+      --  Store a cycle described by attributes Attrs in library graph G,
       --  unless a prior rotation of it already exists. The edges of the cycle
       --  must be in normalized form. Indent is the desired indentation level
       --  for tracing.
@@ -1090,15 +1078,6 @@ package body Bindo.Graphs is
       --  part of an Elaborate_Body pair, or flag Do_Complement is set, add
       --  the complementary vertex to the set.
 
-      function Complementary_Vertex
-        (G             : Library_Graph;
-         Vertex        : Library_Graph_Vertex_Id;
-         Do_Complement : Boolean) return Library_Graph_Vertex_Id;
-      pragma Inline (Complementary_Vertex);
-      --  If vertex Vertex of library graph G is part of an Elaborate_Body
-      --  pair, or flag Do_Complement is set, return the spec when Vertex is
-      --  a body, the body when Vertex is a spec, or No_Library_Graph_Vertex.
-
       function Copy_Cycle_Path
         (Cycle_Path : LGE_Lists.Doubly_Linked_List)
          return LGE_Lists.Doubly_Linked_List;
@@ -1228,17 +1207,21 @@ package body Bindo.Graphs is
 
       procedure Increment_Pending_Predecessors
         (G    : Library_Graph;
-         Comp : Component_Id);
+         Comp : Component_Id;
+         Edge : Library_Graph_Edge_Id);
       pragma Inline (Increment_Pending_Predecessors);
-      --  Increment the number of pending precedessors component Comp of
-      --  library graph G must wait on before it can be elaborated by one.
+      --  Increment the number of pending predecessors component Comp which was
+      --  reached via edge Edge of library graph G must wait on before it can
+      --  be elaborated by one.
 
       procedure Increment_Pending_Predecessors
         (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id);
+         Vertex : Library_Graph_Vertex_Id;
+         Edge   : Library_Graph_Edge_Id);
       pragma Inline (Increment_Pending_Predecessors);
-      --  Increment the number of pending precedessors vertex Vertex of library
-      --  graph G must wait on before it can be elaborated by one.
+      --  Increment the number of pending predecessors vertex Vertex which was
+      --  reached via edge Edge of library graph G must wait on before it can
+      --  be elaborated by one.
 
       procedure Initialize_Components (G : Library_Graph);
       pragma Inline (Initialize_Components);
@@ -1306,22 +1289,14 @@ package body Bindo.Graphs is
          Edge : Library_Graph_Edge_Id) return Boolean;
       pragma Inline (Is_Cyclic_With_Edge);
       --  Determine whether edge Edge of library graph G participates in a
-      --  cycle and is the result of awith dependency between its successor
+      --  cycle and is the result of a with dependency between its successor
       --  and predecessor.
 
-      function Is_Elaborable_Vertex
-        (G            : Library_Graph;
-         Vertex       : Library_Graph_Vertex_Id;
-         Predecessors : Natural) return Boolean;
-      pragma Inline (Is_Elaborable_Vertex);
-      --  Determine whether vertex Vertex of library graph G can be elaborated
-      --  given that it meets number of predecessors Predecessors.
-
       function Is_Recorded_Cycle
         (G     : Library_Graph;
          Attrs : Library_Graph_Cycle_Attributes) return Boolean;
       pragma Inline (Is_Recorded_Cycle);
-      --  Determine whether a cycle desctibed by its attributes Attrs has
+      --  Determine whether a cycle described by its attributes Attrs has
       --  has already been recorded in library graph G.
 
       function Is_Recorded_Edge
@@ -1329,7 +1304,7 @@ package body Bindo.Graphs is
          Rel : Predecessor_Successor_Relation) return Boolean;
       pragma Inline (Is_Recorded_Edge);
       --  Determine whether a predecessor vertex and a successor vertex
-      --  desctibed by relation Rel are already linked in library graph G.
+      --  described by relation Rel are already linked in library graph G.
 
       function Links_Vertices_In_Same_Component
         (G    : Library_Graph;
@@ -1441,7 +1416,7 @@ package body Bindo.Graphs is
          Rel : Predecessor_Successor_Relation;
          Val : Boolean := True);
       pragma Inline (Set_Is_Recorded_Edge);
-      --  Mark a predecessor vertex and a successor vertex desctibed by
+      --  Mark a predecessor vertex and a successor vertex described by
       --  relation Rel as already linked depending on value Val.
 
       procedure Set_LGC_Attributes
@@ -1493,6 +1468,16 @@ package body Bindo.Graphs is
       --  Write the contents of vertex Vertex of library graph G to standard
       --  output. Indent is the desired indentation level for tracing.
 
+      procedure Update_Pending_Predecessors
+        (Strong_Predecessors : in out Natural;
+         Weak_Predecessors   : in out Natural;
+         Update_Weak         : Boolean;
+         Value               : Integer);
+      pragma Inline (Update_Pending_Predecessors);
+      --  Update the number of pending strong or weak predecessors denoted by
+      --  Strong_Predecessors and Weak_Predecessors respectively depending on
+      --  flag Update_Weak by adding value Value.
+
       procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph);
       pragma Inline (Update_Pending_Predecessors_Of_Components);
       --  Update the number of pending predecessors all components of library
@@ -1523,7 +1508,7 @@ package body Bindo.Graphs is
          pragma Assert (LGE_Lists.Present (Edges));
 
          --  A vertex requires a special Body_Before_Spec edge to its
-         --  Corresponging_Item when it either denotes a
+         --  Corresponding_Item when it either denotes a
          --
          --    * Body that completes a previous spec
          --
@@ -1717,7 +1702,10 @@ package body Bindo.Graphs is
          --  Update the number of pending predecessors the successor must wait
          --  on before it is elaborated.
 
-         Increment_Pending_Predecessors (G, Succ);
+         Increment_Pending_Predecessors
+           (G      => G,
+            Vertex => Succ,
+            Edge   => Edge);
 
          --  Update the edge statistics
 
@@ -1757,10 +1745,12 @@ package body Bindo.Graphs is
          Set_LGV_Attributes
            (G      => G,
             Vertex => Vertex,
-            Val    => (Corresponding_Item   => No_Library_Graph_Vertex,
-                       In_Elaboration_Order => False,
-                       Pending_Predecessors => 0,
-                       Unit                 => U_Id));
+            Val    =>
+              (Corresponding_Item          => No_Library_Graph_Vertex,
+               In_Elaboration_Order        => False,
+               Pending_Strong_Predecessors => 0,
+               Pending_Weak_Predecessors   => 0,
+               Unit                        => U_Id));
 
          --  Associate the unit with its corresponding vertex
 
@@ -1783,9 +1773,9 @@ package body Bindo.Graphs is
 
          Complement : constant Library_Graph_Vertex_Id :=
                         Complementary_Vertex
-                          (G             => G,
-                           Vertex        => Vertex,
-                           Do_Complement => Do_Complement);
+                          (G                => G,
+                           Vertex           => Vertex,
+                           Force_Complement => Do_Complement);
 
       begin
          LGV_Sets.Insert (Set, Vertex);
@@ -1800,9 +1790,9 @@ package body Bindo.Graphs is
       --------------------------
 
       function Complementary_Vertex
-        (G             : Library_Graph;
-         Vertex        : Library_Graph_Vertex_Id;
-         Do_Complement : Boolean) return Library_Graph_Vertex_Id
+        (G                : Library_Graph;
+         Vertex           : Library_Graph_Vertex_Id;
+         Force_Complement : Boolean) return Library_Graph_Vertex_Id
       is
          Complement : Library_Graph_Vertex_Id;
 
@@ -1816,7 +1806,7 @@ package body Bindo.Graphs is
 
          --  The caller requests the complement explicitly
 
-         if Do_Complement then
+         if Force_Complement then
             Complement := Corresponding_Item (G, Vertex);
 
          --  The vertex is a completing body of a spec subject to pragma
@@ -1850,6 +1840,46 @@ package body Bindo.Graphs is
          return DG.Component (G.Graph, Vertex);
       end Component;
 
+      ------------------------------------
+      -- Contains_Weak_Static_Successor --
+      ------------------------------------
+
+      function Contains_Weak_Static_Successor
+        (G     : Library_Graph;
+         Cycle : Library_Graph_Cycle_Id) return Boolean
+      is
+         Edge : Library_Graph_Edge_Id;
+         Iter : Edges_Of_Cycle_Iterator;
+         Seen : Boolean;
+
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Cycle));
+
+         --  Assume that no weak static successor has been seen
+
+         Seen := False;
+
+         --  IMPORTANT:
+         --
+         --    * The iteration must run to completion in order to unlock the
+         --      edges of the cycle.
+
+         Iter := Iterate_Edges_Of_Cycle (G, Cycle);
+         while Has_Next (Iter) loop
+            Next (Iter, Edge);
+
+            if not Seen
+              and then Is_Invocation_Edge (G, Edge)
+              and then not Is_Dynamically_Elaborated (G, Successor (G, Edge))
+            then
+               Seen := True;
+            end if;
+         end loop;
+
+         return Seen;
+      end Contains_Weak_Static_Successor;
+
       ---------------------
       -- Copy_Cycle_Path --
       ---------------------
@@ -1911,15 +1941,12 @@ package body Bindo.Graphs is
       ------------
 
       function Create
-        (Initial_Vertices       : Positive;
-         Initial_Edges          : Positive;
-         Dynamically_Elaborated : Boolean) return Library_Graph
+        (Initial_Vertices : Positive;
+         Initial_Edges    : Positive) return Library_Graph
       is
          G : constant Library_Graph := new Library_Graph_Attributes;
 
       begin
-         G.Dynamically_Elaborated := Dynamically_Elaborated;
-
          G.Component_Attributes := Component_Tables.Create (Initial_Vertices);
          G.Cycle_Attributes     := LGC_Tables.Create       (Initial_Vertices);
          G.Cycles               := LGC_Lists.Create;
@@ -1990,7 +2017,8 @@ package body Bindo.Graphs is
 
       procedure Decrement_Pending_Predecessors
         (G    : Library_Graph;
-         Comp : Component_Id)
+         Comp : Component_Id;
+         Edge : Library_Graph_Edge_Id)
       is
          Attrs : Component_Attributes;
 
@@ -1999,7 +2027,13 @@ package body Bindo.Graphs is
          pragma Assert (Present (Comp));
 
          Attrs := Get_Component_Attributes (G, Comp);
-         Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+
+         Update_Pending_Predecessors
+           (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+            Weak_Predecessors   => Attrs.Pending_Weak_Predecessors,
+            Update_Weak         => Is_Invocation_Edge (G, Edge),
+            Value               => -1);
+
          Set_Component_Attributes (G, Comp, Attrs);
       end Decrement_Pending_Predecessors;
 
@@ -2009,7 +2043,8 @@ package body Bindo.Graphs is
 
       procedure Decrement_Pending_Predecessors
         (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id)
+         Vertex : Library_Graph_Vertex_Id;
+         Edge   : Library_Graph_Edge_Id)
       is
          Attrs : Library_Graph_Vertex_Attributes;
 
@@ -2018,7 +2053,13 @@ package body Bindo.Graphs is
          pragma Assert (Present (Vertex));
 
          Attrs := Get_LGV_Attributes (G, Vertex);
-         Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+
+         Update_Pending_Predecessors
+           (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+            Weak_Predecessors   => Attrs.Pending_Weak_Predecessors,
+            Update_Weak         => Is_Invocation_Edge (G, Edge),
+            Value               => -1);
+
          Set_LGV_Attributes (G, Vertex, Attrs);
       end Decrement_Pending_Predecessors;
 
@@ -2071,7 +2112,10 @@ package body Bindo.Graphs is
          --  Update the number of pending predecessors the successor must wait
          --  on before it is elaborated.
 
-         Decrement_Pending_Predecessors (G, Succ);
+         Decrement_Pending_Predecessors
+           (G      => G,
+            Vertex => Succ,
+            Edge   => Edge);
 
          --  Delete the link between the predecessor and successor. This allows
          --  for further attempts to link the same predecessor and successor.
@@ -2298,9 +2342,9 @@ package body Bindo.Graphs is
               (G                      => G,
                Vertex                 =>
                  Complementary_Vertex
-                   (G             => G,
-                    Vertex        => Vertex,
-                    Do_Complement => Spec_And_Body_Together),
+                   (G                => G,
+                    Vertex           => Vertex,
+                    Force_Complement => Spec_And_Body_Together),
                End_Vertices           => End_Vertices,
                Most_Significant_Edge  => Most_Significant_Edge,
                Invocation_Edge_Count  => Invocation_Edge_Count,
@@ -2343,7 +2387,7 @@ package body Bindo.Graphs is
          Trace_Edge (G, Initial_Edge, Indent);
 
          --  Use a set to represent the end vertices of the cycle. The set is
-         --  needed to accomodate the Elaborate_All and Elaborate_Body cases
+         --  needed to accommodate the Elaborate_All and Elaborate_Body cases
          --  where a cycle may terminate on either a spec or a body vertex.
 
          End_Vertices := LGV_Sets.Create (2);
@@ -2650,7 +2694,10 @@ package body Bindo.Graphs is
          U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
 
       begin
-         return U_Rec.Elaborate_Body;
+         --  Treat the spec and body as decoupled when switch -d_b (ignore the
+         --  effects of pragma Elaborate_Body) is in effect.
+
+         return U_Rec.Elaborate_Body and not Debug_Flag_Underscore_B;
       end Has_Elaborate_Body;
 
       --------------
@@ -2884,7 +2931,8 @@ package body Bindo.Graphs is
 
       procedure Increment_Pending_Predecessors
         (G    : Library_Graph;
-         Comp : Component_Id)
+         Comp : Component_Id;
+         Edge : Library_Graph_Edge_Id)
       is
          Attrs : Component_Attributes;
 
@@ -2893,7 +2941,13 @@ package body Bindo.Graphs is
          pragma Assert (Present (Comp));
 
          Attrs := Get_Component_Attributes (G, Comp);
-         Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+
+         Update_Pending_Predecessors
+           (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+            Weak_Predecessors   => Attrs.Pending_Weak_Predecessors,
+            Update_Weak         => Is_Invocation_Edge (G, Edge),
+            Value               => 1);
+
          Set_Component_Attributes (G, Comp, Attrs);
       end Increment_Pending_Predecessors;
 
@@ -2903,7 +2957,8 @@ package body Bindo.Graphs is
 
       procedure Increment_Pending_Predecessors
         (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id)
+         Vertex : Library_Graph_Vertex_Id;
+         Edge   : Library_Graph_Edge_Id)
       is
          Attrs : Library_Graph_Vertex_Attributes;
 
@@ -2912,7 +2967,13 @@ package body Bindo.Graphs is
          pragma Assert (Present (Vertex));
 
          Attrs := Get_LGV_Attributes (G, Vertex);
-         Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+
+         Update_Pending_Predecessors
+           (Strong_Predecessors => Attrs.Pending_Strong_Predecessors,
+            Weak_Predecessors   => Attrs.Pending_Weak_Predecessors,
+            Update_Weak         => Is_Invocation_Edge (G, Edge),
+            Value               => 1);
+
          Set_LGV_Attributes (G, Vertex, Attrs);
       end Increment_Pending_Predecessors;
 
@@ -2925,7 +2986,7 @@ package body Bindo.Graphs is
          pragma Assert (Present (G));
 
          --  The graph already contains a set of components. Reinitialize
-         --  them in order to accomodate the new set of components about to
+         --  them in order to accommodate the new set of components about to
          --  be computed.
 
          if Number_Of_Components (G) > 0 then
@@ -3216,11 +3277,15 @@ package body Bindo.Graphs is
       -- Is_Dynamically_Elaborated --
       -------------------------------
 
-      function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean is
+      function Is_Dynamically_Elaborated
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
       begin
          pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
 
-         return G.Dynamically_Elaborated;
+         return Is_Dynamically_Elaborated (Unit (G, Vertex));
       end Is_Dynamically_Elaborated;
 
       -----------------------------
@@ -3235,12 +3300,14 @@ package body Bindo.Graphs is
          pragma Assert (Present (G));
          pragma Assert (Present (Comp));
 
-         --  A component can be elaborated when
+         --  A component is elaborable when:
          --
-         --    * The component is no longer wanting on any of its predecessors
-         --      to be elaborated.
+         --    * It is not waiting on strong predecessors, and
+         --    * It is not waiting on weak predecessors
 
-         return Pending_Predecessors (G, Comp) = 0;
+         return
+           Pending_Strong_Predecessors (G, Comp) = 0
+             and then Pending_Weak_Predecessors (G, Comp) = 0;
       end Is_Elaborable_Component;
 
       --------------------------
@@ -3251,80 +3318,47 @@ package body Bindo.Graphs is
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id) return Boolean
       is
-         Check_Vertex : Library_Graph_Vertex_Id;
-
-      begin
          pragma Assert (Present (G));
          pragma Assert (Present (Vertex));
 
-         Check_Vertex := Vertex;
-
-         --  A spec-body pair where the spec carries pragma Elaborate_Body must
-         --  be treated as one vertex for elaboration purposes. Use the spec as
-         --  the point of reference for the composite vertex.
-
-         if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_Vertex) then
-            Check_Vertex := Proper_Spec (G, Check_Vertex);
-         end if;
-
-         return
-           Is_Elaborable_Vertex
-             (G            => G,
-              Vertex       => Check_Vertex,
-              Predecessors => 0);
-      end Is_Elaborable_Vertex;
-
-      --------------------------
-      -- Is_Elaborable_Vertex --
-      --------------------------
+         Complement : constant Library_Graph_Vertex_Id :=
+                        Complementary_Vertex
+                          (G                => G,
+                           Vertex           => Vertex,
+                           Force_Complement => False);
 
-      function Is_Elaborable_Vertex
-        (G            : Library_Graph;
-         Vertex       : Library_Graph_Vertex_Id;
-         Predecessors : Natural) return Boolean
-      is
-         Body_Vertex : Library_Graph_Vertex_Id;
+         Strong_Preds : Natural;
+         Weak_Preds   : Natural;
 
       begin
-         pragma Assert (Present (G));
-         pragma Assert (Present (Vertex));
-
-         --  The vertex must not be re-elaborated once it has been elaborated
+         --  A vertex is elaborable when:
+         --
+         --    * It has not been elaborated yet, and
+         --    * The complement vertex of an Elaborate_Body pair has not been
+         --      elaborated yet, and
+         --    * It resides within an elaborable component, and
+         --    * It is not waiting on strong predecessors, and
+         --    * It is not waiting on weak predecessors
 
          if In_Elaboration_Order (G, Vertex) then
             return False;
 
-         --  The vertex must not be waiting on more precedessors than requested
-         --  to be elaborated.
-
-         elsif Pending_Predecessors (G, Vertex) /= Predecessors then
+         elsif Present (Complement)
+           and then In_Elaboration_Order (G, Complement)
+         then
             return False;
 
-         --  The component where the vertex resides must not be waiting on any
-         --  of its precedessors to be elaborated.
-
          elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then
             return False;
-
-         --  The vertex denotes a spec with a completing body, and is subject
-         --  to pragma Elaborate_Body. The body must be elaborable for the
-         --  vertex to be elaborated. Account for the sole predecessor of the
-         --  body which is the vertex itself.
-
-         elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
-            Body_Vertex := Proper_Body (G, Vertex);
-            pragma Assert (Present (Body_Vertex));
-
-            return
-              Is_Elaborable_Vertex
-                (G            => G,
-                 Vertex       => Body_Vertex,
-                 Predecessors => 1);
          end if;
 
-         --  At this point it is known that the vertex can be elaborated
+         Pending_Predecessors_For_Elaboration
+           (G            => G,
+            Vertex       => Vertex,
+            Strong_Preds => Strong_Preds,
+            Weak_Preds   => Weak_Preds);
 
-         return True;
+         return Strong_Preds = 0 and then Weak_Preds = 0;
       end Is_Elaborable_Vertex;
 
       ---------------------------
@@ -3378,6 +3412,26 @@ package body Bindo.Graphs is
          return Kind (G, Edge) = Elaborate_Edge;
       end Is_Elaborate_Edge;
 
+      ----------------------------
+      -- Is_Elaborate_Body_Pair --
+      ----------------------------
+
+      function Is_Elaborate_Body_Pair
+        (G           : Library_Graph;
+         Spec_Vertex : Library_Graph_Vertex_Id;
+         Body_Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Spec_Vertex));
+         pragma Assert (Present (Body_Vertex));
+
+         return
+           Is_Spec_With_Elaborate_Body (G, Spec_Vertex)
+             and then Is_Body_Of_Spec_With_Elaborate_Body (G, Body_Vertex)
+             and then Proper_Body (G, Spec_Vertex) = Body_Vertex;
+      end Is_Elaborate_Body_Pair;
+
       --------------------
       -- Is_Forced_Edge --
       --------------------
@@ -3539,6 +3593,57 @@ package body Bindo.Graphs is
              and then Has_Elaborate_Body (G, Vertex);
       end Is_Spec_With_Elaborate_Body;
 
+      ---------------------------------
+      -- Is_Weakly_Elaborable_Vertex --
+      ----------------------------------
+
+      function Is_Weakly_Elaborable_Vertex
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Boolean
+      is
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+
+         Complement : constant Library_Graph_Vertex_Id :=
+                        Complementary_Vertex
+                          (G                => G,
+                           Vertex           => Vertex,
+                           Force_Complement => False);
+
+         Strong_Preds : Natural;
+         Weak_Preds   : Natural;
+
+      begin
+         --  A vertex is weakly elaborable when:
+         --
+         --    * It has not been elaborated yet, and
+         --    * The complement vertex of an Elaborate_Body pair has not been
+         --      elaborated yet, and
+         --    * It resides within an elaborable component, and
+         --    * It is not waiting on strong predecessors, and
+         --    * It is waiting on at least one weak predecessor
+
+         if In_Elaboration_Order (G, Vertex) then
+            return False;
+
+         elsif Present (Complement)
+           and then In_Elaboration_Order (G, Complement)
+         then
+            return False;
+
+         elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then
+            return False;
+         end if;
+
+         Pending_Predecessors_For_Elaboration
+           (G            => G,
+            Vertex       => Vertex,
+            Strong_Preds => Strong_Preds,
+            Weak_Preds   => Weak_Preds);
+
+         return Strong_Preds = 0 and then Weak_Preds >= 1;
+      end Is_Weakly_Elaborable_Vertex;
+
       ------------------
       -- Is_With_Edge --
       ------------------
@@ -4044,11 +4149,72 @@ package body Bindo.Graphs is
          return Get_LGC_Attributes (G, Cycle).Path;
       end Path;
 
-      --------------------------
-      -- Pending_Predecessors --
-      --------------------------
+      ------------------------------------------
+      -- Pending_Predecessors_For_Elaboration --
+      ------------------------------------------
 
-      function Pending_Predecessors
+      procedure Pending_Predecessors_For_Elaboration
+        (G            : Library_Graph;
+         Vertex       : Library_Graph_Vertex_Id;
+         Strong_Preds : out Natural;
+         Weak_Preds   : out Natural)
+      is
+         Complement         : Library_Graph_Vertex_Id;
+         Spec_Vertex        : Library_Graph_Vertex_Id;
+         Total_Strong_Preds : Natural;
+         Total_Weak_Preds   : Natural;
+
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+
+         Total_Strong_Preds := Pending_Strong_Predecessors (G, Vertex);
+         Total_Weak_Preds   := Pending_Weak_Predecessors   (G, Vertex);
+
+         --  Assume that there is no complementary vertex that needs to be
+         --  examined.
+
+         Complement  := No_Library_Graph_Vertex;
+         Spec_Vertex := No_Library_Graph_Vertex;
+
+         if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then
+            Complement  := Proper_Spec (G, Vertex);
+            Spec_Vertex := Complement;
+
+         elsif Is_Spec_With_Elaborate_Body (G, Vertex) then
+            Complement  := Proper_Body (G, Vertex);
+            Spec_Vertex := Vertex;
+         end if;
+
+         --  The vertex is part of an Elaborate_Body pair. Take into account
+         --  the strong and weak predecessors of the complementary vertex.
+
+         if Present (Complement) then
+            Total_Strong_Preds :=
+              Pending_Strong_Predecessors (G, Complement) + Total_Strong_Preds;
+            Total_Weak_Preds :=
+              Pending_Weak_Predecessors   (G, Complement) + Total_Weak_Preds;
+
+            --  The body of an Elaborate_Body pair is the successor of a strong
+            --  edge where the predecessor is the spec. This edge must not be
+            --  considered for elaboration purposes because the pair is treated
+            --  as one vertex. Account for the edge only when the spec has not
+            --  been elaborated yet.
+
+            if not In_Elaboration_Order (G, Spec_Vertex) then
+               Total_Strong_Preds := Total_Strong_Preds - 1;
+            end if;
+         end if;
+
+         Strong_Preds := Total_Strong_Preds;
+         Weak_Preds   := Total_Weak_Preds;
+      end Pending_Predecessors_For_Elaboration;
+
+      ---------------------------------
+      -- Pending_Strong_Predecessors --
+      ---------------------------------
+
+      function Pending_Strong_Predecessors
         (G    : Library_Graph;
          Comp : Component_Id) return Natural
       is
@@ -4056,14 +4222,14 @@ package body Bindo.Graphs is
          pragma Assert (Present (G));
          pragma Assert (Present (Comp));
 
-         return Get_Component_Attributes (G, Comp).Pending_Predecessors;
-      end Pending_Predecessors;
+         return Get_Component_Attributes (G, Comp).Pending_Strong_Predecessors;
+      end Pending_Strong_Predecessors;
 
-      --------------------------
-      -- Pending_Predecessors --
-      --------------------------
+      ---------------------------------
+      -- Pending_Strong_Predecessors --
+      ---------------------------------
 
-      function Pending_Predecessors
+      function Pending_Strong_Predecessors
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id) return Natural
       is
@@ -4071,8 +4237,38 @@ package body Bindo.Graphs is
          pragma Assert (Present (G));
          pragma Assert (Present (Vertex));
 
-         return Get_LGV_Attributes (G, Vertex).Pending_Predecessors;
-      end Pending_Predecessors;
+         return Get_LGV_Attributes (G, Vertex).Pending_Strong_Predecessors;
+      end Pending_Strong_Predecessors;
+
+      -------------------------------
+      -- Pending_Weak_Predecessors --
+      -------------------------------
+
+      function Pending_Weak_Predecessors
+        (G    : Library_Graph;
+         Comp : Component_Id) return Natural
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Comp));
+
+         return Get_Component_Attributes (G, Comp).Pending_Weak_Predecessors;
+      end Pending_Weak_Predecessors;
+
+      -------------------------------
+      -- Pending_Weak_Predecessors --
+      -------------------------------
+
+      function Pending_Weak_Predecessors
+        (G      : Library_Graph;
+         Vertex : Library_Graph_Vertex_Id) return Natural
+      is
+      begin
+         pragma Assert (Present (G));
+         pragma Assert (Present (Vertex));
+
+         return Get_LGV_Attributes (G, Vertex).Pending_Weak_Predecessors;
+      end Pending_Weak_Predecessors;
 
       ----------------
       -- Precedence --
@@ -4306,9 +4502,9 @@ package body Bindo.Graphs is
 
          Complement : constant Library_Graph_Vertex_Id :=
                         Complementary_Vertex
-                          (G             => G,
-                           Vertex        => Vertex,
-                           Do_Complement => Do_Complement);
+                          (G                => G,
+                           Vertex           => Vertex,
+                           Force_Complement => Do_Complement);
 
       begin
          LGV_Sets.Delete (Set, Vertex);
@@ -4702,6 +4898,24 @@ package body Bindo.Graphs is
          return Get_LGV_Attributes (G, Vertex).Unit;
       end Unit;
 
+      ---------------------------------
+      -- Update_Pending_Predecessors --
+      ---------------------------------
+
+      procedure Update_Pending_Predecessors
+        (Strong_Predecessors : in out Natural;
+         Weak_Predecessors   : in out Natural;
+         Update_Weak         : Boolean;
+         Value               : Integer)
+      is
+      begin
+         if Update_Weak then
+            Weak_Predecessors := Weak_Predecessors + Value;
+         else
+            Strong_Predecessors := Strong_Predecessors + Value;
+         end if;
+      end Update_Pending_Predecessors;
+
       -----------------------------------------------
       -- Update_Pending_Predecessors_Of_Components --
       -----------------------------------------------
@@ -4748,7 +4962,10 @@ package body Bindo.Graphs is
          --  must wait on another predecessor until it can be elaborated.
 
          if Pred_Comp /= Succ_Comp then
-            Increment_Pending_Predecessors (G, Succ_Comp);
+            Increment_Pending_Predecessors
+              (G    => G,
+               Comp => Succ_Comp,
+               Edge => Edge);
          end if;
       end Update_Pending_Predecessors_Of_Components;
    end Library_Graphs;
@@ -4835,7 +5052,7 @@ package body Bindo.Graphs is
    --------------------------
 
    LGC_Sequencer : Library_Graph_Cycle_Id := First_Library_Graph_Cycle;
-   --  The couhnter for library graph cycles. Do not directly manipulate its
+   --  The counter for library graph cycles. Do not directly manipulate its
    --  value.
 
    function Sequence_Next_Cycle return Library_Graph_Cycle_Id is
index 02f8e52fd64db6288b5207efa31b9b1dd5bd7e1a..3c2fef0182535045d7a1ce1bbf40e6414a325fb0 100644 (file)
@@ -668,7 +668,7 @@ package Bindo.Graphs is
 
       --  The following type represents the various kinds of library graph
       --  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
         (Elaborate_Body_Cycle,
@@ -753,13 +753,11 @@ package Bindo.Graphs is
       --  describes.
 
       function Create
-        (Initial_Vertices       : Positive;
-         Initial_Edges          : Positive;
-         Dynamically_Elaborated : Boolean) return Library_Graph;
+        (Initial_Vertices : Positive;
+         Initial_Edges    : Positive) return Library_Graph;
       pragma Inline (Create);
       --  Create a new empty graph with vertex capacity Initial_Vertices and
-      --  edge capacity Initial_Edges. Flag Dynamically_Elaborated must be set
-      --  when the main library unit was compiled using the dynamic model.
+      --  edge capacity Initial_Edges.
 
       procedure Destroy (G : in out Library_Graph);
       pragma Inline (Destroy);
@@ -809,10 +807,12 @@ package Bindo.Graphs is
 
       procedure Decrement_Pending_Predecessors
         (G      : Library_Graph;
-         Vertex : Library_Graph_Vertex_Id);
+         Vertex : Library_Graph_Vertex_Id;
+         Edge   : Library_Graph_Edge_Id);
       pragma Inline (Decrement_Pending_Predecessors);
-      --  Decrease the number of pending predecessors vertex Vertex of library
-      --  graph G must wait on until it can be elaborated.
+      --  Decrease the number of pending predecessors vertex Vertex which was
+      --  reached via edge Edge of library graph G must wait until it can be
+      --  elaborated.
 
       function File_Name
         (G      : Library_Graph;
@@ -844,12 +844,30 @@ package Bindo.Graphs is
       --  Obtain the name of the unit which vertex Vertex of library graph G
       --  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;
          Vertex : Library_Graph_Vertex_Id) return Natural;
-      pragma Inline (Pending_Predecessors);
-      --  Obtain the number of pending predecessors vertex Vertex of library
-      --  graph G must wait on until it can be elaborated.
+      pragma Inline (Pending_Weak_Predecessors);
+      --  Obtain the number of pending weak predecessors vertex Vertex of
+      --  library graph G must wait on until it can be elaborated.
 
       procedure Set_Corresponding_Item
         (G      : Library_Graph;
@@ -901,17 +919,26 @@ package Bindo.Graphs is
 
       procedure Decrement_Pending_Predecessors
         (G    : Library_Graph;
-         Comp : Component_Id);
+         Comp : Component_Id;
+         Edge : Library_Graph_Edge_Id);
       pragma Inline (Decrement_Pending_Predecessors);
-      --  Decrease the number of pending predecessors component Comp of library
-      --  graph G must wait on until it can be elaborated.
+      --  Decrease the number of pending predecessors component Comp which was
+      --  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;
          Comp : Component_Id) return Natural;
-      pragma Inline (Pending_Predecessors);
-      --  Obtain the number of pending predecessors component Comp of library
-      --  graph G must wait on until it can be elaborated.
+      pragma Inline (Pending_Strong_Predecessors);
+      --  Obtain the number of pending strong predecessors component Comp of
+      --  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 --
@@ -940,6 +967,26 @@ package Bindo.Graphs is
       -- 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;
       pragma Inline (Has_Elaborate_All_Cycle);
       --  Determine whether library graph G contains a cycle involving pragma
@@ -973,22 +1020,26 @@ package Bindo.Graphs is
       --  Determine whether vertex Vertex of library graph G denotes a body
       --  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);
-      --  Determine whether library graph G was created from a set of units
-      --  where the main library unit was compiled using the dynamic model.
+      --  Determine whether vertex Vertex of library graph G was compiled
+      --  using the dynamic model.
 
       function Is_Elaborable_Component
         (G    : Library_Graph;
          Comp : Component_Id) return Boolean;
       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
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id) return Boolean;
       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
         (G    : Library_Graph;
@@ -1012,6 +1063,15 @@ package Bindo.Graphs is
       --  Determine whether edge Edge of library graph G is an edge whose
       --  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
         (G    : Library_Graph;
          Edge : Library_Graph_Edge_Id) return Boolean;
@@ -1045,7 +1105,7 @@ package Bindo.Graphs is
          Vertex : Library_Graph_Vertex_Id) return Boolean;
       pragma Inline (Is_Preelaborated_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
         (G      : Library_Graph;
@@ -1067,6 +1127,14 @@ package Bindo.Graphs is
       --  Determine whether vertex Vertex of library graph G denotes a spec
       --  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
         (G    : Library_Graph;
          Edge : Library_Graph_Edge_Id) return Boolean;
@@ -1320,9 +1388,13 @@ package Bindo.Graphs is
          In_Elaboration_Order : Boolean := False;
          --  Set when this vertex is elaborated
 
-         Pending_Predecessors : Natural := 0;
-         --  The number of pending predecessor vertices this vertex must wait
-         --  on before it can be elaborated.
+         Pending_Strong_Predecessors : Natural := 0;
+         --  The number of pending strong predecessor vertices this vertex must
+         --  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;
          --  The reference to unit this vertex represents
@@ -1330,10 +1402,11 @@ package Bindo.Graphs is
 
       No_Library_Graph_Vertex_Attributes :
         constant Library_Graph_Vertex_Attributes :=
-          (Corresponding_Item   => No_Library_Graph_Vertex,
-           In_Elaboration_Order => False,
-           Pending_Predecessors => 0,
-           Unit                 => No_Unit_Id);
+          (Corresponding_Item          => No_Library_Graph_Vertex,
+           In_Elaboration_Order        => False,
+           Pending_Strong_Predecessors => 0,
+           Pending_Weak_Predecessors   => 0,
+           Unit                        => No_Unit_Id);
 
       procedure Destroy_Library_Graph_Vertex_Attributes
         (Attrs : in out Library_Graph_Vertex_Attributes);
@@ -1391,13 +1464,18 @@ package Bindo.Graphs is
       --  The following type represents the attributes of a component
 
       type Component_Attributes is record
-         Pending_Predecessors : Natural := 0;
-         --  The number of pending predecessor components this component must
-         --  wait on before it can be elaborated.
+         Pending_Strong_Predecessors : Natural := 0;
+         --  The number of pending strong predecessor components this component
+         --  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;
 
       No_Component_Attributes : constant Component_Attributes :=
-        (Pending_Predecessors => 0);
+        (Pending_Strong_Predecessors => 0,
+         Pending_Weak_Predecessors   => 0);
 
       procedure Destroy_Component_Attributes
         (Attrs : in out Component_Attributes);
@@ -1560,10 +1638,6 @@ package Bindo.Graphs is
          Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil;
          --  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;
          --  The map of edge -> edge attributes for all edges in the graph
 
index aed496003699d88d5c05782358a3dd64e4404990..88be2e8f9eddd2be47fcf7ef3fb8eaf32f58ab3b 100644 (file)
@@ -140,7 +140,7 @@ package body Bindo.Validators is
 
          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);
          while Has_Next (Iter) loop
@@ -155,7 +155,7 @@ package body Bindo.Validators is
 
                Write_Str ("  library graph edge (LGE_Id_");
                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_Str (")");
                Write_Eol;
@@ -421,7 +421,7 @@ package body Bindo.Validators is
         (G      : Invocation_Graph;
          Vertex : Invocation_Graph_Vertex_Id);
       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.
 
       procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph);
@@ -468,7 +468,7 @@ package body Bindo.Validators is
          if not Present (Edge) then
             Write_Error (Msg, Has_Invalid_Data);
 
-            Write_Str ("  emply invocation graph edge");
+            Write_Str ("  empty invocation graph edge");
             Write_Eol;
             Write_Eol;
             return;
@@ -530,7 +530,7 @@ package body Bindo.Validators is
          if not Present (Vertex) then
             Write_Error (Msg, Has_Invalid_Data);
 
-            Write_Str ("  emply invocation graph vertex");
+            Write_Str ("  empty invocation graph vertex");
             Write_Eol;
             Write_Eol;
             return;
@@ -662,7 +662,7 @@ package body Bindo.Validators is
          if not Present (Edge) then
             Write_Error (Msg, Has_Invalid_Data);
 
-            Write_Str ("  emply library graph edge");
+            Write_Str ("  empty library graph edge");
             Write_Eol;
             Write_Eol;
             return;
index a3b45fce76627140b9e70ed156d743368da0732e..99f93f5e4030b077927e85c7d57316d4f8295d0d 100644 (file)
@@ -1025,6 +1025,10 @@ package body Bindo.Writers is
       --  Write all vertices of component Comp of library graph G to standard
       --  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
         (G      : Library_Graph;
          Vertex : Library_Graph_Vertex_Id);
@@ -1089,8 +1093,12 @@ package body Bindo.Writers is
          Write_Str (")");
          Write_Eol;
 
-         Write_Str ("  Pending_Predecessors = ");
-         Write_Int (Int (Pending_Predecessors (G, Comp)));
+         Write_Str ("  Pending_Strong_Predecessors = ");
+         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_Component_Vertices (G, Comp);
@@ -1225,6 +1233,7 @@ package body Bindo.Writers is
 
          Write_Statistics (G);
          Write_Library_Graph_Vertices (G);
+         Write_Components (G);
 
          Write_Str ("Library Graph end");
          Write_Eol;
@@ -1312,8 +1321,12 @@ package body Bindo.Writers is
          end if;
 
          Write_Eol;
-         Write_Str ("  Pending_Predecessors = ");
-         Write_Int (Int (Pending_Predecessors (G, Vertex)));
+         Write_Str ("  Pending_Strong_Predecessors = ");
+         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_Str ("  Component (Comp_Id_");
@@ -1612,7 +1625,7 @@ package body Bindo.Writers is
    is
       function Digits_Indentation return Indentation_Level;
       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.
 
       ------------------------
index ff6b9b3b6602a0702b7f45a7b05b3dfd338fe411..01e48e40fce65c35f352c98a5f23f65a267ad4cd 100644 (file)
@@ -127,9 +127,6 @@ package Bindo.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);
       --  Write library graph G to standard output
 
index b3106adfb25373656c527e60bfd852bb29ea1870..897e7467f7d277ba9839cee24ccb60a1b85e897f 100644 (file)
@@ -74,7 +74,7 @@ package body Bindo is
    --
    --    * 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
    --
@@ -95,6 +95,12 @@ package body Bindo is
 
    --  * 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 root - A special invocation construct which denotes the
@@ -136,8 +142,23 @@ package body Bindo is
    --  * Pending predecessor - A vertex that must be elaborated before another
    --    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
    --    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 --
@@ -233,7 +254,7 @@ package body Bindo is
    --      bodies as single vertices.
    --
    --    * 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.
    --
    --    * Validate the consistency of the order, only when switch -d_V is in
@@ -251,7 +272,7 @@ package body Bindo is
    --  The Diagnostics phase has the following objectives:
    --
    --    * 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.
    --
@@ -268,7 +289,7 @@ package body Bindo is
    --    * Diagnose the most important cycle, or all cycles when switch -d_C is
    --      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.
    --
    --        - A detailed traceback of the cycle, showcasing the transition
@@ -276,7 +297,7 @@ package body Bindo is
    --          information.
    --
    --        - 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,
    --          and the state of various relevant switches.
 
@@ -284,6 +305,23 @@ package body Bindo is
    -- 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
    --
    --        GNATbind outputs the contents of ALI table Invocation_Constructs
index 39cf7a49373263be284cd1f8b70297e1e413ebca..940b752e484961cc33f39b9dba72a2f940358da1 100644 (file)
@@ -41,4 +41,14 @@ package Bindo is
    --  exists, it is returned in Order, otherwise Unrecoverable_Error is
    --  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;
index da4bea1fec404e635dde3f0cdeb59db7f9815015..680c38fa4ce8d8930a3d8bffcf384670781bc081 100644 (file)
@@ -349,11 +349,11 @@ package body Debug is
    --  d.8
    --  d.9
 
-   --  d_a
-   --  d_b
+   --  d_a  Ignore the effects of pragma Elaborate_All
+   --  d_b  Ignore the effects of pragma Elaborate_Body
    --  d_c
    --  d_d
-   --  d_e
+   --  d_e  Ignore the effects of pragma Elaborate
    --  d_f
    --  d_g
    --  d_h
@@ -1141,6 +1141,17 @@ package body Debug is
    --  dx  Force the binder to read (and then ignore) the xref information
    --      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
    --       in textual format to standard output.