------------------------------------------------------------------------------ | |

-- -- | |

-- GNAT COMPILER COMPONENTS -- | |

-- -- | |

-- B I N D O . G R A P H S -- | |

-- -- | |

-- S p e c -- | |

-- -- | |

-- Copyright (C) 2019-2022, Free Software Foundation, Inc. -- | |

-- -- | |

-- GNAT is free software; you can redistribute it and/or modify it under -- | |

-- terms of the GNU General Public License as published by the Free Soft- -- | |

-- ware Foundation; either version 3, or (at your option) any later ver- -- | |

-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- | |

-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- | |

-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- | |

-- for more details. You should have received a copy of the GNU General -- | |

-- Public License distributed with GNAT; see file COPYING3. If not, go to -- | |

-- http://www.gnu.org/licenses for a complete copy of the license. -- | |

-- -- | |

-- GNAT was originally developed by the GNAT team at New York University. -- | |

-- Extensive contributions were provided by Ada Core Technologies Inc. -- | |

-- -- | |

------------------------------------------------------------------------------ | |

-- For full architecture, see unit Bindo. | |

-- The following unit defines the various graphs used in determining the | |

-- elaboration order of units. | |

with Types; use Types; | |

with Bindo.Units; use Bindo.Units; | |

with GNAT; use GNAT; | |

with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; | |

with GNAT.Graphs; use GNAT.Graphs; | |

with GNAT.Lists; use GNAT.Lists; | |

with GNAT.Sets; use GNAT.Sets; | |

package Bindo.Graphs is | |

--------------------------- | |

-- Invocation graph edge -- | |

--------------------------- | |

-- The following type denotes an invocation graph edge handle | |

type Invocation_Graph_Edge_Id is new Natural; | |

No_Invocation_Graph_Edge : constant Invocation_Graph_Edge_Id := | |

Invocation_Graph_Edge_Id'First; | |

First_Invocation_Graph_Edge : constant Invocation_Graph_Edge_Id := | |

No_Invocation_Graph_Edge + 1; | |

procedure Destroy_Invocation_Graph_Edge | |

(Edge : in out Invocation_Graph_Edge_Id); | |

pragma Inline (Destroy_Invocation_Graph_Edge); | |

-- Destroy invocation graph edge Edge | |

function Hash_Invocation_Graph_Edge | |

(Edge : Invocation_Graph_Edge_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Invocation_Graph_Edge); | |

-- Obtain the hash value of key Edge | |

function Present (Edge : Invocation_Graph_Edge_Id) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether invocation graph edge Edge exists | |

package IGE_Lists is new Doubly_Linked_Lists | |

(Element_Type => Invocation_Graph_Edge_Id, | |

"=" => "=", | |

Destroy_Element => Destroy_Invocation_Graph_Edge); | |

------------------------------ | |

-- Invocation graph vertex -- | |

------------------------------ | |

-- The following type denotes an invocation graph vertex handle | |

type Invocation_Graph_Vertex_Id is new Natural; | |

No_Invocation_Graph_Vertex : constant Invocation_Graph_Vertex_Id := | |

Invocation_Graph_Vertex_Id'First; | |

First_Invocation_Graph_Vertex : constant Invocation_Graph_Vertex_Id := | |

No_Invocation_Graph_Vertex + 1; | |

function Hash_Invocation_Graph_Vertex | |

(Vertex : Invocation_Graph_Vertex_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Invocation_Graph_Vertex); | |

-- Obtain the hash value of key Vertex | |

function Present (Vertex : Invocation_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether invocation graph vertex Vertex exists | |

package IGV_Sets is new Membership_Sets | |

(Element_Type => Invocation_Graph_Vertex_Id, | |

"=" => "=", | |

Hash => Hash_Invocation_Graph_Vertex); | |

------------------------- | |

-- Library graph cycle -- | |

------------------------- | |

type Library_Graph_Cycle_Id is new Natural; | |

No_Library_Graph_Cycle : constant Library_Graph_Cycle_Id := | |

Library_Graph_Cycle_Id'First; | |

First_Library_Graph_Cycle : constant Library_Graph_Cycle_Id := | |

No_Library_Graph_Cycle + 1; | |

procedure Destroy_Library_Graph_Cycle | |

(Cycle : in out Library_Graph_Cycle_Id); | |

pragma Inline (Destroy_Library_Graph_Cycle); | |

-- Destroy library graph cycle Cycle | |

function Hash_Library_Graph_Cycle | |

(Cycle : Library_Graph_Cycle_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Library_Graph_Cycle); | |

-- Obtain the hash value of key Cycle | |

function Present (Cycle : Library_Graph_Cycle_Id) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether library graph cycle Cycle exists | |

package LGC_Lists is new Doubly_Linked_Lists | |

(Element_Type => Library_Graph_Cycle_Id, | |

"=" => "=", | |

Destroy_Element => Destroy_Library_Graph_Cycle); | |

------------------------ | |

-- Library graph edge -- | |

------------------------ | |

-- The following type denotes a library graph edge handle | |

type Library_Graph_Edge_Id is new Natural; | |

No_Library_Graph_Edge : constant Library_Graph_Edge_Id := | |

Library_Graph_Edge_Id'First; | |

First_Library_Graph_Edge : constant Library_Graph_Edge_Id := | |

No_Library_Graph_Edge + 1; | |

procedure Destroy_Library_Graph_Edge | |

(Edge : in out Library_Graph_Edge_Id); | |

pragma Inline (Destroy_Library_Graph_Edge); | |

-- Destroy library graph edge Edge | |

function Hash_Library_Graph_Edge | |

(Edge : Library_Graph_Edge_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Library_Graph_Edge); | |

-- Obtain the hash value of key Edge | |

function Present (Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether library graph edge Edge exists | |

package LGE_Lists is new Doubly_Linked_Lists | |

(Element_Type => Library_Graph_Edge_Id, | |

"=" => "=", | |

Destroy_Element => Destroy_Library_Graph_Edge); | |

package LGE_Sets is new Membership_Sets | |

(Element_Type => Library_Graph_Edge_Id, | |

"=" => "=", | |

Hash => Hash_Library_Graph_Edge); | |

-------------------------- | |

-- Library graph vertex -- | |

-------------------------- | |

-- The following type denotes a library graph vertex handle | |

type Library_Graph_Vertex_Id is new Natural; | |

No_Library_Graph_Vertex : constant Library_Graph_Vertex_Id := | |

Library_Graph_Vertex_Id'First; | |

First_Library_Graph_Vertex : constant Library_Graph_Vertex_Id := | |

No_Library_Graph_Vertex + 1; | |

procedure Destroy_Library_Graph_Vertex | |

(Vertex : in out Library_Graph_Vertex_Id); | |

pragma Inline (Destroy_Library_Graph_Vertex); | |

-- Destroy library graph vertex Vertex | |

function Hash_Library_Graph_Vertex | |

(Vertex : Library_Graph_Vertex_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Library_Graph_Vertex); | |

-- Obtain the hash value of key Vertex | |

function Present (Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether library graph vertex Vertex exists | |

package LGV_Lists is new Doubly_Linked_Lists | |

(Element_Type => Library_Graph_Vertex_Id, | |

"=" => "=", | |

Destroy_Element => Destroy_Library_Graph_Vertex); | |

package LGV_Sets is new Membership_Sets | |

(Element_Type => Library_Graph_Vertex_Id, | |

"=" => "=", | |

Hash => Hash_Library_Graph_Vertex); | |

-------------------- | |

-- Library_Graphs -- | |

-------------------- | |

package Library_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 higher precedence than one with higher ordinal. | |

type Library_Graph_Cycle_Kind is | |

(Elaborate_Body_Cycle, | |

-- A cycle that involves at least one spec-body pair, where the | |

-- spec is subject to pragma Elaborate_Body. This is the highest | |

-- precedence cycle. | |

Elaborate_Cycle, | |

-- A cycle that involves at least one Elaborate edge | |

Elaborate_All_Cycle, | |

-- A cycle that involves at least one Elaborate_All edge | |

Forced_Cycle, | |

-- A cycle that involves at least one edge which is a byproduct of | |

-- the forced-elaboration-order file. | |

Invocation_Cycle, | |

-- A cycle that involves at least one invocation edge. This is the | |

-- lowest precedence cycle. | |

No_Cycle_Kind); | |

-- The following type represents the various kinds of library edges. The | |

-- order is important here, and corresponds to the order in which edges | |

-- are added to the graph. See Add_Edge_Kind_Check for details. If | |

-- changes are made such that new edge kinds are added or similar, we | |

-- need to make sure this type matches the code in Add_Edge_Kind_Check, | |

-- and Add_Edge_Kind_Check matches the order of edge adding. Likewise, | |

-- if the edge-adding order changes, we need consistency between this | |

-- enumeration type, the edge-adding order, and Add_Edge_Kind_Check. | |

type Library_Graph_Edge_Kind is | |

(Spec_Before_Body_Edge, | |

-- Successor denotes a body, Predecessor denotes a spec | |

Elaborate_Edge, | |

-- Successor withs Predecessor, and has pragma Elaborate for it | |

Elaborate_All_Edge, | |

-- Successor withs Predecessor, and has pragma Elaborate_All for it | |

With_Edge, | |

-- Successor withs Predecessor | |

Forced_Edge, | |

-- Successor is forced to with Predecessor by virtue of an existing | |

-- elaboration order provided in a file. | |

Invocation_Edge, | |

-- An invocation construct in unit Successor invokes a target in unit | |

-- Predecessor. | |

Body_Before_Spec_Edge, | |

-- Successor denotes spec, Predecessor denotes a body. This is a | |

-- special edge kind used only during the discovery of components. | |

-- Note that a body can never be elaborated before its spec. | |

No_Edge); | |

----------- | |

-- Graph -- | |

----------- | |

-- The following type denotes a library graph handle. Each instance must | |

-- be created using routine Create. | |

type Library_Graph is private; | |

Nil : constant Library_Graph; | |

type LGE_Predicate_Ptr is access function | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

type LGV_Comparator_Ptr is access function | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id; | |

Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; | |

type LGV_Predicate_Ptr is access function | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

---------------------- | |

-- Graph operations -- | |

---------------------- | |

procedure Add_Edge | |

(G : Library_Graph; | |

Pred : Library_Graph_Vertex_Id; | |

Succ : Library_Graph_Vertex_Id; | |

Kind : Library_Graph_Edge_Kind; | |

Activates_Task : Boolean); | |

pragma Inline (Add_Edge); | |

-- Create a new edge in library graph G with source vertex Pred and | |

-- destination vertex Succ. Kind denotes the nature of the edge. Flag | |

-- Activates_Task should be set when the edge involves task activation. | |

procedure Add_Vertex | |

(G : Library_Graph; | |

U_Id : Unit_Id); | |

pragma Inline (Add_Vertex); | |

-- Create a new vertex in library graph G. U_Id is the unit the vertex | |

-- describes. | |

function Create | |

(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. | |

procedure Destroy (G : in out Library_Graph); | |

pragma Inline (Destroy); | |

-- Destroy the contents of library graph G, rendering it unusable | |

procedure Find_Components (G : Library_Graph); | |

pragma Inline (Find_Components); | |

-- Find all components in library graph G | |

procedure Find_Cycles (G : Library_Graph); | |

pragma Inline (Find_Cycles); | |

-- Find all cycles in library graph G | |

function Highest_Precedence_Cycle | |

(G : Library_Graph) return Library_Graph_Cycle_Id; | |

pragma Inline (Highest_Precedence_Cycle); | |

-- Obtain the cycle with highest precedence among all other cycles of | |

-- library graph G. | |

function Present (G : Library_Graph) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether library graph G exists | |

----------------------- | |

-- Vertex attributes -- | |

----------------------- | |

function Component | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Component_Id; | |

pragma Inline (Component); | |

-- Obtain the component where vertex Vertex of library graph G resides | |

function Corresponding_Item | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Corresponding_Item); | |

-- Obtain the complementary vertex which represents the corresponding | |

-- spec or body of vertex Vertex of library graph G. | |

function Corresponding_Vertex | |

(G : Library_Graph; | |

U_Id : Unit_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Corresponding_Vertex); | |

-- Obtain the corresponding vertex of library graph G which represents | |

-- unit U_Id. | |

procedure Decrement_Pending_Predecessors | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id; | |

Edge : Library_Graph_Edge_Id); | |

pragma Inline (Decrement_Pending_Predecessors); | |

-- 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; | |

Vertex : Library_Graph_Vertex_Id) return File_Name_Type; | |

pragma Inline (File_Name); | |

-- Obtain the name of the file where vertex Vertex of library graph G | |

-- resides. | |

function In_Elaboration_Order | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (In_Elaboration_Order); | |

-- Determine whether vertex Vertex of library graph G is already in some | |

-- elaboration order. | |

function Invocation_Graph_Encoding | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) | |

return Invocation_Graph_Encoding_Kind; | |

pragma Inline (Invocation_Graph_Encoding); | |

-- Obtain the encoding format used to capture information related to | |

-- invocation vertices and edges that reside within vertex Vertex of | |

-- library graph G. | |

function Name | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Unit_Name_Type; | |

pragma Inline (Name); | |

-- Obtain the name of the unit which vertex Vertex of library graph G | |

-- represents. | |

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_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; | |

Vertex : Library_Graph_Vertex_Id; | |

Val : Library_Graph_Vertex_Id); | |

pragma Inline (Set_Corresponding_Item); | |

-- Set the complementary vertex which represents the corresponding | |

-- spec or body of vertex Vertex of library graph G to value Val. | |

procedure Set_In_Elaboration_Order | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id; | |

Val : Boolean := True); | |

pragma Inline (Set_In_Elaboration_Order); | |

-- Mark vertex Vertex of library graph G as included in some elaboration | |

-- order depending on value Val. | |

function Unit | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Unit_Id; | |

pragma Inline (Unit); | |

-- Obtain the unit vertex Vertex of library graph G represents | |

--------------------- | |

-- Edge attributes -- | |

--------------------- | |

function Activates_Task | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Activates_Task); | |

-- Determine whether edge Edge of library graph G activates a task | |

function Kind | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind; | |

pragma Inline (Kind); | |

-- Obtain the nature of edge Edge of library graph G | |

function Predecessor | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Predecessor); | |

-- Obtain the predecessor vertex of edge Edge of library graph G | |

function Successor | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Successor); | |

-- Obtain the successor vertex of edge Edge of library graph G | |

-------------------------- | |

-- Component attributes -- | |

-------------------------- | |

procedure Decrement_Pending_Predecessors | |

(G : Library_Graph; | |

Comp : Component_Id; | |

Edge : Library_Graph_Edge_Id); | |

pragma Inline (Decrement_Pending_Predecessors); | |

-- 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_Strong_Predecessors | |

(G : Library_Graph; | |

Comp : Component_Id) return Natural; | |

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 -- | |

---------------------- | |

function Invocation_Edge_Count | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Natural; | |

pragma Inline (Invocation_Edge_Count); | |

-- Obtain the number of invocation edges in cycle Cycle of library | |

-- graph G. | |

function Kind | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Kind; | |

pragma Inline (Kind); | |

-- Obtain the nature of cycle Cycle of library graph G | |

function Length | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Natural; | |

pragma Inline (Length); | |

-- Obtain the length of cycle Cycle of library graph G | |

--------------- | |

-- 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_Elaborate_All_Edge | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Boolean; | |

pragma Inline (Contains_Elaborate_All_Edge); | |

-- Determine whether cycle Cycle of library graph G contains an | |

-- Elaborate_All edge. | |

function Contains_Static_Successor_Edge | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Boolean; | |

pragma Inline (Contains_Static_Successor_Edge); | |

-- Determine whether cycle Cycle of library graph G contains an edge | |

-- where the successor was compiled using the static model. | |

function Contains_Task_Activation | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Boolean; | |

pragma Inline (Contains_Task_Activation); | |

-- Determine whether cycle Cycle of library graph G contains an | |

-- invocation edge where the path it represents involves a task | |

-- activation. | |

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 | |

-- Elaborate_All. | |

function Has_No_Elaboration_Code | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Has_No_Elaboration_Code); | |

-- Determine whether vertex Vertex of library graph G represents a unit | |

-- that lacks elaboration code. | |

function In_Same_Component | |

(G : Library_Graph; | |

Left : Library_Graph_Vertex_Id; | |

Right : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (In_Same_Component); | |

-- Determine whether vertices Left and Right of library graph G reside | |

-- in the same component. | |

function Is_Body | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Body); | |

-- Determine whether vertex Vertex of library graph G denotes a body | |

function Is_Body_Of_Spec_With_Elaborate_Body | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Body_Of_Spec_With_Elaborate_Body); | |

-- Determine whether vertex Vertex of library graph G denotes a body | |

-- with a corresponding spec, and the spec has pragma Elaborate_Body. | |

function Is_Body_With_Spec | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Body_With_Spec); | |

-- Determine whether vertex Vertex of library graph G denotes a body | |

-- with a corresponding spec. | |

function Is_Dynamically_Elaborated | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Dynamically_Elaborated); | |

-- 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 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 is not waiting on | |

-- any predecessors, and can thus be elaborated. | |

function Is_Elaborate_All_Edge | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Is_Elaborate_All_Edge); | |

-- Determine whether edge Edge of library graph G is an edge whose | |

-- predecessor is subject to pragma Elaborate_All. | |

function Is_Elaborate_Body_Edge | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Is_Elaborate_Body_Edge); | |

-- Determine whether edge Edge of library graph G has a successor | |

-- that is either a spec subject to pragma Elaborate_Body, or a body | |

-- that completes such a spec. | |

function Is_Elaborate_Edge | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Is_Elaborate_Edge); | |

-- 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; | |

pragma Inline (Is_Forced_Edge); | |

-- Determine whether edge Edge of library graph G is a byproduct of the | |

-- forced-elaboration-order file. | |

function Is_Internal_Unit | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Internal_Unit); | |

-- Determine whether vertex Vertex of library graph G denotes an | |

-- internal unit. | |

function Is_Invocation_Edge | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Is_Invocation_Edge); | |

-- Determine whether edge Edge of library graph G came from the | |

-- traversal of the invocation graph. | |

function Is_Predefined_Unit | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Predefined_Unit); | |

-- Determine whether vertex Vertex of library graph G denotes a | |

-- predefined unit. | |

function Is_Preelaborated_Unit | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Preelaborated_Unit); | |

-- Determine whether vertex Vertex of library graph G denotes a unit | |

-- subject to pragma Pure or Preelaborable. | |

function Is_Spec | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Spec); | |

-- Determine whether vertex Vertex of library graph G denotes a spec | |

function Is_Spec_Before_Body_Edge | |

(G : Library_Graph; | |

Edge : Library_Graph_Edge_Id) return Boolean; | |

pragma Inline (Is_Spec_Before_Body_Edge); | |

-- Determine whether edge Edge of library graph G links a predecessor | |

-- spec and a successor body belonging to the same unit. | |

function Is_Spec_With_Body | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Spec_With_Body); | |

-- Determine whether vertex Vertex of library graph G denotes a spec | |

-- with a corresponding body. | |

function Is_Spec_With_Elaborate_Body | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Is_Spec_With_Elaborate_Body); | |

-- 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; | |

pragma Inline (Is_With_Edge); | |

-- Determine whether edge Edge of library graph G is the result of a | |

-- with dependency between its successor and predecessor. | |

function Needs_Elaboration | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Boolean; | |

pragma Inline (Needs_Elaboration); | |

-- Determine whether vertex Vertex of library graph G represents a unit | |

-- that needs to be elaborated. | |

function Proper_Body | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Proper_Body); | |

-- Obtain the body of vertex Vertex of library graph G | |

function Proper_Spec | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Proper_Spec); | |

-- Obtain the spec of vertex Vertex of library graph G | |

---------------- | |

-- Statistics -- | |

---------------- | |

function Library_Graph_Edge_Count | |

(G : Library_Graph; | |

Kind : Library_Graph_Edge_Kind) return Natural; | |

pragma Inline (Library_Graph_Edge_Count); | |

-- Obtain the total number of edges of kind Kind in library graph G | |

function Number_Of_Component_Vertices | |

(G : Library_Graph; | |

Comp : Component_Id) return Natural; | |

pragma Inline (Number_Of_Component_Vertices); | |

-- Obtain the total number of vertices component Comp of library graph | |

-- contains. | |

function Number_Of_Components (G : Library_Graph) return Natural; | |

pragma Inline (Number_Of_Components); | |

-- Obtain the total number of components in library graph G | |

function Number_Of_Cycles (G : Library_Graph) return Natural; | |

pragma Inline (Number_Of_Cycles); | |

-- Obtain the total number of cycles in library graph G | |

function Number_Of_Edges (G : Library_Graph) return Natural; | |

pragma Inline (Number_Of_Edges); | |

-- Obtain the total number of edges in library graph G | |

function Number_Of_Edges_To_Successors | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Natural; | |

pragma Inline (Number_Of_Edges_To_Successors); | |

-- Obtain the total number of edges to successors vertex Vertex of | |

-- library graph G has. | |

function Number_Of_Vertices (G : Library_Graph) return Natural; | |

pragma Inline (Number_Of_Vertices); | |

-- Obtain the total number of vertices in library graph G | |

--------------- | |

-- Iterators -- | |

--------------- | |

-- The following type represents an iterator over all cycles of a | |

-- library graph. | |

type All_Cycle_Iterator is private; | |

function Has_Next (Iter : All_Cycle_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more cycles to examine | |

function Iterate_All_Cycles | |

(G : Library_Graph) return All_Cycle_Iterator; | |

pragma Inline (Iterate_All_Cycles); | |

-- Obtain an iterator over all cycles of library graph G | |

procedure Next | |

(Iter : in out All_Cycle_Iterator; | |

Cycle : out Library_Graph_Cycle_Id); | |

pragma Inline (Next); | |

-- Return the current cycle referenced by iterator Iter and advance to | |

-- the next available cycle. | |

-- The following type represents an iterator over all edges of a library | |

-- graph. | |

type All_Edge_Iterator is private; | |

function Has_Next (Iter : All_Edge_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more edges to examine | |

function Iterate_All_Edges (G : Library_Graph) return All_Edge_Iterator; | |

pragma Inline (Iterate_All_Edges); | |

-- Obtain an iterator over all edges of library graph G | |

procedure Next | |

(Iter : in out All_Edge_Iterator; | |

Edge : out Library_Graph_Edge_Id); | |

pragma Inline (Next); | |

-- Return the current edge referenced by iterator Iter and advance to | |

-- the next available edge. | |

-- The following type represents an iterator over all vertices of a | |

-- library graph. | |

type All_Vertex_Iterator is private; | |

function Has_Next (Iter : All_Vertex_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more vertices to examine | |

function Iterate_All_Vertices | |

(G : Library_Graph) return All_Vertex_Iterator; | |

pragma Inline (Iterate_All_Vertices); | |

-- Obtain an iterator over all vertices of library graph G | |

procedure Next | |

(Iter : in out All_Vertex_Iterator; | |

Vertex : out Library_Graph_Vertex_Id); | |

pragma Inline (Next); | |

-- Return the current vertex referenced by iterator Iter and advance | |

-- to the next available vertex. | |

-- The following type represents an iterator over all components of a | |

-- library graph. | |

type Component_Iterator is private; | |

function Has_Next (Iter : Component_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more components to examine | |

function Iterate_Components | |

(G : Library_Graph) return Component_Iterator; | |

pragma Inline (Iterate_Components); | |

-- Obtain an iterator over all components of library graph G | |

procedure Next | |

(Iter : in out Component_Iterator; | |

Comp : out Component_Id); | |

pragma Inline (Next); | |

-- Return the current component referenced by iterator Iter and advance | |

-- to the next available component. | |

-- The following type represents an iterator over all vertices of a | |

-- component. | |

type Component_Vertex_Iterator is private; | |

function Has_Next (Iter : Component_Vertex_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more vertices to examine | |

function Iterate_Component_Vertices | |

(G : Library_Graph; | |

Comp : Component_Id) return Component_Vertex_Iterator; | |

pragma Inline (Iterate_Component_Vertices); | |

-- Obtain an iterator over all vertices of component Comp of library | |

-- graph G. | |

procedure Next | |

(Iter : in out Component_Vertex_Iterator; | |

Vertex : out Library_Graph_Vertex_Id); | |

pragma Inline (Next); | |

-- Return the current vertex referenced by iterator Iter and advance | |

-- to the next available vertex. | |

-- The following type represents an iterator over all edges that form a | |

-- cycle. | |

type Edges_Of_Cycle_Iterator is private; | |

function Has_Next (Iter : Edges_Of_Cycle_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more edges to examine | |

function Iterate_Edges_Of_Cycle | |

(G : Library_Graph; | |

Cycle : Library_Graph_Cycle_Id) return Edges_Of_Cycle_Iterator; | |

pragma Inline (Iterate_Edges_Of_Cycle); | |

-- Obtain an iterator over all edges that form cycle Cycle of library | |

-- graph G. | |

procedure Next | |

(Iter : in out Edges_Of_Cycle_Iterator; | |

Edge : out Library_Graph_Edge_Id); | |

pragma Inline (Next); | |

-- Return the current edge referenced by iterator Iter and advance to | |

-- the next available edge. | |

-- The following type represents an iterator over all edges that reach | |

-- successors starting from a particular predecessor vertex. | |

type Edges_To_Successors_Iterator is private; | |

function Has_Next (Iter : Edges_To_Successors_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more edges to examine | |

function Iterate_Edges_To_Successors | |

(G : Library_Graph; | |

Vertex : Library_Graph_Vertex_Id) return Edges_To_Successors_Iterator; | |

pragma Inline (Iterate_Edges_To_Successors); | |

-- Obtain an iterator over all edges to successors with predecessor | |

-- vertex Vertex of library graph G. | |

procedure Next | |

(Iter : in out Edges_To_Successors_Iterator; | |

Edge : out Library_Graph_Edge_Id); | |

pragma Inline (Next); | |

-- Return the current edge referenced by iterator Iter and advance to | |

-- the next available edge. | |

private | |

-------------- | |

-- Vertices -- | |

-------------- | |

-- The following type represents the attributes of a library graph | |

-- vertex. | |

type Library_Graph_Vertex_Attributes is record | |

Corresponding_Item : Library_Graph_Vertex_Id := | |

No_Library_Graph_Vertex; | |

-- The reference to the corresponding spec or body. This attribute is | |

-- set as follows: | |

-- | |

-- * If predicate Is_Body_With_Spec is True, the reference denotes | |

-- the corresponding spec. | |

-- | |

-- * If predicate Is_Spec_With_Body is True, the reference denotes | |

-- the corresponding body. | |

-- | |

-- * Otherwise the attribute remains empty. | |

In_Elaboration_Order : Boolean := False; | |

-- Set when this vertex is 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 | |

end record; | |

No_Library_Graph_Vertex_Attributes : | |

constant Library_Graph_Vertex_Attributes := | |

(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); | |

pragma Inline (Destroy_Library_Graph_Vertex_Attributes); | |

-- Destroy the contents of attributes Attrs | |

package LGV_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Library_Graph_Vertex_Id, | |

Value_Type => Library_Graph_Vertex_Attributes, | |

No_Value => No_Library_Graph_Vertex_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Library_Graph_Vertex_Attributes, | |

Hash => Hash_Library_Graph_Vertex); | |

----------- | |

-- Edges -- | |

----------- | |

-- The following type represents the attributes of a library graph edge | |

type Library_Graph_Edge_Attributes is record | |

Activates_Task : Boolean := False; | |

-- Set for an invocation edge, where at least one of the paths the | |

-- edge represents activates a task. | |

Kind : Library_Graph_Edge_Kind := No_Edge; | |

-- The nature of the library graph edge | |

end record; | |

No_Library_Graph_Edge_Attributes : | |

constant Library_Graph_Edge_Attributes := | |

(Activates_Task => False, | |

Kind => No_Edge); | |

procedure Destroy_Library_Graph_Edge_Attributes | |

(Attrs : in out Library_Graph_Edge_Attributes); | |

pragma Inline (Destroy_Library_Graph_Edge_Attributes); | |

-- Destroy the contents of attributes Attrs | |

package LGE_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Library_Graph_Edge_Id, | |

Value_Type => Library_Graph_Edge_Attributes, | |

No_Value => No_Library_Graph_Edge_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Library_Graph_Edge_Attributes, | |

Hash => Hash_Library_Graph_Edge); | |

---------------- | |

-- Components -- | |

---------------- | |

-- The following type represents the attributes of a component | |

type Component_Attributes is record | |

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_Strong_Predecessors => 0, | |

Pending_Weak_Predecessors => 0); | |

procedure Destroy_Component_Attributes | |

(Attrs : in out Component_Attributes); | |

pragma Inline (Destroy_Component_Attributes); | |

-- Destroy the contents of attributes Attrs | |

package Component_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Component_Id, | |

Value_Type => Component_Attributes, | |

No_Value => No_Component_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Component_Attributes, | |

Hash => Hash_Component); | |

------------ | |

-- Cycles -- | |

------------ | |

-- The following type represents the attributes of a cycle | |

type Library_Graph_Cycle_Attributes is record | |

Invocation_Edge_Count : Natural := 0; | |

-- The number of invocation edges within the cycle | |

Kind : Library_Graph_Cycle_Kind := No_Cycle_Kind; | |

-- The nature of the cycle | |

Path : LGE_Lists.Doubly_Linked_List := LGE_Lists.Nil; | |

-- The path of edges that form the cycle | |

end record; | |

No_Library_Graph_Cycle_Attributes : | |

constant Library_Graph_Cycle_Attributes := | |

(Invocation_Edge_Count => 0, | |

Kind => No_Cycle_Kind, | |

Path => LGE_Lists.Nil); | |

procedure Destroy_Library_Graph_Cycle_Attributes | |

(Attrs : in out Library_Graph_Cycle_Attributes); | |

pragma Inline (Destroy_Library_Graph_Cycle_Attributes); | |

-- Destroy the contents of attributes Attrs | |

function Hash_Library_Graph_Cycle_Attributes | |

(Attrs : Library_Graph_Cycle_Attributes) return Bucket_Range_Type; | |

pragma Inline (Hash_Library_Graph_Cycle_Attributes); | |

-- Obtain the hash of key Attrs | |

function Same_Library_Graph_Cycle_Attributes | |

(Left : Library_Graph_Cycle_Attributes; | |

Right : Library_Graph_Cycle_Attributes) return Boolean; | |

pragma Inline (Same_Library_Graph_Cycle_Attributes); | |

-- Determine whether cycle attributes Left and Right are the same | |

package LGC_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Library_Graph_Cycle_Id, | |

Value_Type => Library_Graph_Cycle_Attributes, | |

No_Value => No_Library_Graph_Cycle_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Library_Graph_Cycle_Attributes, | |

Hash => Hash_Library_Graph_Cycle); | |

-------------------- | |

-- Recorded edges -- | |

-------------------- | |

-- The following type represents a relation between a predecessor and | |

-- successor vertices. | |

type Predecessor_Successor_Relation is record | |

Predecessor : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; | |

-- The source vertex | |

Successor : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; | |

-- The destination vertex | |

end record; | |

No_Predecessor_Successor_Relation : | |

constant Predecessor_Successor_Relation := | |

(Predecessor => No_Library_Graph_Vertex, | |

Successor => No_Library_Graph_Vertex); | |

function Hash_Predecessor_Successor_Relation | |

(Rel : Predecessor_Successor_Relation) return Bucket_Range_Type; | |

pragma Inline (Hash_Predecessor_Successor_Relation); | |

-- Obtain the hash value of key Rel | |

package RE_Sets is new Membership_Sets | |

(Element_Type => Predecessor_Successor_Relation, | |

"=" => "=", | |

Hash => Hash_Predecessor_Successor_Relation); | |

---------------- | |

-- Statistics -- | |

---------------- | |

type Library_Graph_Edge_Counts is | |

array (Library_Graph_Edge_Kind) of Natural; | |

----------- | |

-- Units -- | |

----------- | |

package Unit_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Unit_Id, | |

Value_Type => Library_Graph_Vertex_Id, | |

No_Value => No_Library_Graph_Vertex, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Library_Graph_Vertex, | |

Hash => Hash_Unit); | |

----------- | |

-- Graph -- | |

----------- | |

package DG is new Directed_Graphs | |

(Vertex_Id => Library_Graph_Vertex_Id, | |

No_Vertex => No_Library_Graph_Vertex, | |

Hash_Vertex => Hash_Library_Graph_Vertex, | |

Same_Vertex => "=", | |

Edge_Id => Library_Graph_Edge_Id, | |

No_Edge => No_Library_Graph_Edge, | |

Hash_Edge => Hash_Library_Graph_Edge, | |

Same_Edge => "="); | |

-- The following type represents the attributes of a library graph | |

type Library_Graph_Attributes is record | |

Component_Attributes : Component_Tables.Dynamic_Hash_Table := | |

Component_Tables.Nil; | |

-- The map of component -> component attributes for all components in | |

-- the graph. | |

Counts : Library_Graph_Edge_Counts := (others => 0); | |

-- Edge statistics | |

Cycle_Attributes : LGC_Tables.Dynamic_Hash_Table := LGC_Tables.Nil; | |

-- The map of cycle -> cycle attributes for all cycles in the graph | |

Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil; | |

-- The list of all cycles in the graph, sorted based on precedence | |

Edge_Attributes : LGE_Tables.Dynamic_Hash_Table := LGE_Tables.Nil; | |

-- The map of edge -> edge attributes for all edges in the graph | |

Graph : DG.Directed_Graph := DG.Nil; | |

-- The underlying graph describing the relations between edges and | |

-- vertices. | |

Recorded_Edges : RE_Sets.Membership_Set := RE_Sets.Nil; | |

-- The set of recorded edges, used to prevent duplicate edges in the | |

-- graph. | |

Unit_To_Vertex : Unit_Tables.Dynamic_Hash_Table := Unit_Tables.Nil; | |

-- The map of unit -> vertex | |

Vertex_Attributes : LGV_Tables.Dynamic_Hash_Table := LGV_Tables.Nil; | |

-- The map of vertex -> vertex attributes for all vertices in the | |

-- graph. | |

end record; | |

type Library_Graph is access Library_Graph_Attributes; | |

Nil : constant Library_Graph := null; | |

--------------- | |

-- Iterators -- | |

--------------- | |

type All_Cycle_Iterator is new LGC_Lists.Iterator; | |

type All_Edge_Iterator is new DG.All_Edge_Iterator; | |

type All_Vertex_Iterator is new DG.All_Vertex_Iterator; | |

type Component_Iterator is new DG.Component_Iterator; | |

type Component_Vertex_Iterator is new DG.Component_Vertex_Iterator; | |

type Edges_Of_Cycle_Iterator is new LGE_Lists.Iterator; | |

type Edges_To_Successors_Iterator is new DG.Outgoing_Edge_Iterator; | |

end Library_Graphs; | |

----------------------- | |

-- Invocation_Graphs -- | |

----------------------- | |

package Invocation_Graphs is | |

----------- | |

-- Graph -- | |

----------- | |

-- The following type denotes an invocation graph handle. Each instance | |

-- must be created using routine Create. | |

type Invocation_Graph is private; | |

Nil : constant Invocation_Graph; | |

---------------------- | |

-- Graph operations -- | |

---------------------- | |

procedure Add_Edge | |

(G : Invocation_Graph; | |

Source : Invocation_Graph_Vertex_Id; | |

Target : Invocation_Graph_Vertex_Id; | |

IR_Id : Invocation_Relation_Id); | |

pragma Inline (Add_Edge); | |

-- Create a new edge in invocation graph G with source vertex Source and | |

-- destination vertex Target. IR_Id is the invocation relation the edge | |

-- describes. | |

procedure Add_Vertex | |

(G : Invocation_Graph; | |

IC_Id : Invocation_Construct_Id; | |

Body_Vertex : Library_Graph_Vertex_Id; | |

Spec_Vertex : Library_Graph_Vertex_Id); | |

pragma Inline (Add_Vertex); | |

-- Create a new vertex in invocation graph G. IC_Id is the invocation | |

-- construct the vertex describes. Body_Vertex denotes the library graph | |

-- vertex where the invocation construct's body is declared. Spec_Vertex | |

-- is the library graph vertex where the invocation construct's spec is | |

-- declared. | |

function Create | |

(Initial_Vertices : Positive; | |

Initial_Edges : Positive; | |

Lib_Graph : Library_Graphs.Library_Graph) | |

return Invocation_Graph; | |

pragma Inline (Create); | |

-- Create a new empty graph with vertex capacity Initial_Vertices | |

-- and edge capacity Initial_Edges. Lib_Graph is the library graph | |

-- corresponding to this invocation graph. | |

function Get_Lib_Graph | |

(G : Invocation_Graph) return Library_Graphs.Library_Graph; | |

pragma Inline (Get_Lib_Graph); | |

-- Return the library graph corresponding to this invocation graph | |

procedure Destroy (G : in out Invocation_Graph); | |

pragma Inline (Destroy); | |

-- Destroy the contents of invocation graph G, rendering it unusable | |

function Present (G : Invocation_Graph) return Boolean; | |

pragma Inline (Present); | |

-- Determine whether invocation graph G exists | |

----------------------- | |

-- Vertex attributes -- | |

----------------------- | |

function Body_Vertex | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Body_Vertex); | |

-- Obtain the library graph vertex where the body of the invocation | |

-- construct represented by vertex Vertex of invocation graph G is | |

-- declared. | |

function Column | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Nat; | |

pragma Inline (Column); | |

-- Obtain the column number where the invocation construct vertex Vertex | |

-- of invocation graph G describes. | |

function Construct | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id; | |

pragma Inline (Construct); | |

-- Obtain the invocation construct vertex Vertex of invocation graph G | |

-- describes. | |

function Corresponding_Vertex | |

(G : Invocation_Graph; | |

IS_Id : Invocation_Signature_Id) return Invocation_Graph_Vertex_Id; | |

pragma Inline (Corresponding_Vertex); | |

-- Obtain the vertex of invocation graph G that corresponds to signature | |

-- IS_Id. | |

function Line | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Nat; | |

pragma Inline (Line); | |

-- Obtain the line number where the invocation construct vertex Vertex | |

-- of invocation graph G describes. | |

function Name | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Name_Id; | |

pragma Inline (Name); | |

-- Obtain the name of the construct vertex Vertex of invocation graph G | |

-- describes. | |

function Spec_Vertex | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id; | |

pragma Inline (Spec_Vertex); | |

-- Obtain the library graph vertex where the spec of the invocation | |

-- construct represented by vertex Vertex of invocation graph G is | |

-- declared. | |

--------------------- | |

-- Edge attributes -- | |

--------------------- | |

function Extra | |

(G : Invocation_Graph; | |

Edge : Invocation_Graph_Edge_Id) return Name_Id; | |

pragma Inline (Extra); | |

-- Obtain the extra name used in error diagnostics of edge Edge of | |

-- invocation graph G. | |

function Kind | |

(G : Invocation_Graph; | |

Edge : Invocation_Graph_Edge_Id) return Invocation_Kind; | |

pragma Inline (Kind); | |

-- Obtain the nature of edge Edge of invocation graph G | |

function Relation | |

(G : Invocation_Graph; | |

Edge : Invocation_Graph_Edge_Id) return Invocation_Relation_Id; | |

pragma Inline (Relation); | |

-- Obtain the relation edge Edge of invocation graph G describes | |

function Target | |

(G : Invocation_Graph; | |

Edge : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id; | |

pragma Inline (Target); | |

-- Obtain the target vertex edge Edge of invocation graph G designates | |

---------------- | |

-- Statistics -- | |

---------------- | |

function Invocation_Graph_Edge_Count | |

(G : Invocation_Graph; | |

Kind : Invocation_Kind) return Natural; | |

pragma Inline (Invocation_Graph_Edge_Count); | |

-- Obtain the total number of edges of kind Kind in invocation graph G | |

function Number_Of_Edges (G : Invocation_Graph) return Natural; | |

pragma Inline (Number_Of_Edges); | |

-- Obtain the total number of edges in invocation graph G | |

function Number_Of_Edges_To_Targets | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Natural; | |

pragma Inline (Number_Of_Edges_To_Targets); | |

-- Obtain the total number of edges to targets vertex Vertex of | |

-- invocation graph G has. | |

function Number_Of_Elaboration_Roots | |

(G : Invocation_Graph) return Natural; | |

pragma Inline (Number_Of_Elaboration_Roots); | |

-- Obtain the total number of elaboration roots in invocation graph G | |

function Number_Of_Vertices (G : Invocation_Graph) return Natural; | |

pragma Inline (Number_Of_Vertices); | |

-- Obtain the total number of vertices in invocation graph G | |

--------------- | |

-- Iterators -- | |

--------------- | |

-- The following type represents an iterator over all edges of an | |

-- invocation graph. | |

type All_Edge_Iterator is private; | |

function Has_Next (Iter : All_Edge_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more edges to examine | |

function Iterate_All_Edges | |

(G : Invocation_Graph) return All_Edge_Iterator; | |

pragma Inline (Iterate_All_Edges); | |

-- Obtain an iterator over all edges of invocation graph G | |

procedure Next | |

(Iter : in out All_Edge_Iterator; | |

Edge : out Invocation_Graph_Edge_Id); | |

pragma Inline (Next); | |

-- Return the current edge referenced by iterator Iter and advance to | |

-- the next available edge. | |

-- The following type represents an iterator over all vertices of an | |

-- invocation graph. | |

type All_Vertex_Iterator is private; | |

function Has_Next (Iter : All_Vertex_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more vertices to examine | |

function Iterate_All_Vertices | |

(G : Invocation_Graph) return All_Vertex_Iterator; | |

pragma Inline (Iterate_All_Vertices); | |

-- Obtain an iterator over all vertices of invocation graph G | |

procedure Next | |

(Iter : in out All_Vertex_Iterator; | |

Vertex : out Invocation_Graph_Vertex_Id); | |

pragma Inline (Next); | |

-- Return the current vertex referenced by iterator Iter and advance | |

-- to the next available vertex. | |

-- The following type represents an iterator over all edges that reach | |

-- targets starting from a particular source vertex. | |

type Edges_To_Targets_Iterator is private; | |

function Has_Next (Iter : Edges_To_Targets_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more edges to examine | |

function Iterate_Edges_To_Targets | |

(G : Invocation_Graph; | |

Vertex : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator; | |

pragma Inline (Iterate_Edges_To_Targets); | |

-- Obtain an iterator over all edges to targets with source vertex | |

-- Vertex of invocation graph G. | |

procedure Next | |

(Iter : in out Edges_To_Targets_Iterator; | |

Edge : out Invocation_Graph_Edge_Id); | |

pragma Inline (Next); | |

-- Return the current edge referenced by iterator Iter and advance to | |

-- the next available edge. | |

-- The following type represents an iterator over all vertices of an | |

-- invocation graph that denote the elaboration procedure or a spec or | |

-- a body, referred to as elaboration root. | |

type Elaboration_Root_Iterator is private; | |

function Has_Next (Iter : Elaboration_Root_Iterator) return Boolean; | |

pragma Inline (Has_Next); | |

-- Determine whether iterator Iter has more elaboration roots to examine | |

function Iterate_Elaboration_Roots | |

(G : Invocation_Graph) return Elaboration_Root_Iterator; | |

pragma Inline (Iterate_Elaboration_Roots); | |

-- Obtain an iterator over all elaboration roots of invocation graph G | |

procedure Next | |

(Iter : in out Elaboration_Root_Iterator; | |

Root : out Invocation_Graph_Vertex_Id); | |

pragma Inline (Next); | |

-- Return the current elaboration root referenced by iterator Iter and | |

-- advance to the next available elaboration root. | |

private | |

-------------- | |

-- Vertices -- | |

-------------- | |

procedure Destroy_Invocation_Graph_Vertex | |

(Vertex : in out Invocation_Graph_Vertex_Id); | |

pragma Inline (Destroy_Invocation_Graph_Vertex); | |

-- Destroy invocation graph vertex Vertex | |

-- The following type represents the attributes of an invocation graph | |

-- vertex. | |

type Invocation_Graph_Vertex_Attributes is record | |

Body_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; | |

-- Reference to the library graph vertex where the body of this | |

-- vertex resides. | |

Construct : Invocation_Construct_Id := No_Invocation_Construct; | |

-- Reference to the invocation construct this vertex represents | |

Spec_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; | |

-- Reference to the library graph vertex where the spec of this | |

-- vertex resides. | |

end record; | |

No_Invocation_Graph_Vertex_Attributes : | |

constant Invocation_Graph_Vertex_Attributes := | |

(Body_Vertex => No_Library_Graph_Vertex, | |

Construct => No_Invocation_Construct, | |

Spec_Vertex => No_Library_Graph_Vertex); | |

procedure Destroy_Invocation_Graph_Vertex_Attributes | |

(Attrs : in out Invocation_Graph_Vertex_Attributes); | |

pragma Inline (Destroy_Invocation_Graph_Vertex_Attributes); | |

-- Destroy the contents of attributes Attrs | |

package IGV_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Invocation_Graph_Vertex_Id, | |

Value_Type => Invocation_Graph_Vertex_Attributes, | |

No_Value => No_Invocation_Graph_Vertex_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Invocation_Graph_Vertex_Attributes, | |

Hash => Hash_Invocation_Graph_Vertex); | |

----------- | |

-- Edges -- | |

----------- | |

procedure Destroy_Invocation_Graph_Edge | |

(Edge : in out Invocation_Graph_Edge_Id); | |

pragma Inline (Destroy_Invocation_Graph_Edge); | |

-- Destroy invocation graph edge Edge | |

-- The following type represents the attributes of an invocation graph | |

-- edge. | |

type Invocation_Graph_Edge_Attributes is record | |

Relation : Invocation_Relation_Id := No_Invocation_Relation; | |

-- Reference to the invocation relation this edge represents | |

end record; | |

No_Invocation_Graph_Edge_Attributes : | |

constant Invocation_Graph_Edge_Attributes := | |

(Relation => No_Invocation_Relation); | |

procedure Destroy_Invocation_Graph_Edge_Attributes | |

(Attrs : in out Invocation_Graph_Edge_Attributes); | |

pragma Inline (Destroy_Invocation_Graph_Edge_Attributes); | |

-- Destroy the contents of attributes Attrs | |

package IGE_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Invocation_Graph_Edge_Id, | |

Value_Type => Invocation_Graph_Edge_Attributes, | |

No_Value => No_Invocation_Graph_Edge_Attributes, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Invocation_Graph_Edge_Attributes, | |

Hash => Hash_Invocation_Graph_Edge); | |

--------------- | |

-- Relations -- | |

--------------- | |

-- The following type represents a relation between a source and target | |

-- vertices. | |

type Source_Target_Relation is record | |

Source : Invocation_Graph_Vertex_Id := No_Invocation_Graph_Vertex; | |

-- The source vertex | |

Target : Invocation_Graph_Vertex_Id := No_Invocation_Graph_Vertex; | |

-- The destination vertex | |

end record; | |

No_Source_Target_Relation : | |

constant Source_Target_Relation := | |

(Source => No_Invocation_Graph_Vertex, | |

Target => No_Invocation_Graph_Vertex); | |

function Hash_Source_Target_Relation | |

(Rel : Source_Target_Relation) return Bucket_Range_Type; | |

pragma Inline (Hash_Source_Target_Relation); | |

-- Obtain the hash value of key Rel | |

package Relation_Sets is new Membership_Sets | |

(Element_Type => Source_Target_Relation, | |

"=" => "=", | |

Hash => Hash_Source_Target_Relation); | |

---------------- | |

-- Statistics -- | |

---------------- | |

type Invocation_Graph_Edge_Counts is array (Invocation_Kind) of Natural; | |

---------------- | |

-- Signatures -- | |

---------------- | |

function Hash_Invocation_Signature | |

(IS_Id : Invocation_Signature_Id) return Bucket_Range_Type; | |

pragma Inline (Hash_Invocation_Signature); | |

-- Obtain the hash value of key IS_Id | |

package Signature_Tables is new Dynamic_Hash_Tables | |

(Key_Type => Invocation_Signature_Id, | |

Value_Type => Invocation_Graph_Vertex_Id, | |

No_Value => No_Invocation_Graph_Vertex, | |

Expansion_Threshold => 1.5, | |

Expansion_Factor => 2, | |

Compression_Threshold => 0.3, | |

Compression_Factor => 2, | |

"=" => "=", | |

Destroy_Value => Destroy_Invocation_Graph_Vertex, | |

Hash => Hash_Invocation_Signature); | |

----------------------- | |

-- Elaboration roots -- | |

----------------------- | |

package IGV_Sets is new Membership_Sets | |

(Element_Type => Invocation_Graph_Vertex_Id, | |

"=" => "=", | |

Hash => Hash_Invocation_Graph_Vertex); | |

----------- | |

-- Graph -- | |

----------- | |

package DG is new Directed_Graphs | |

(Vertex_Id => Invocation_Graph_Vertex_Id, | |

No_Vertex => No_Invocation_Graph_Vertex, | |

Hash_Vertex => Hash_Invocation_Graph_Vertex, | |

Same_Vertex => "=", | |

Edge_id => Invocation_Graph_Edge_Id, | |

No_Edge => No_Invocation_Graph_Edge, | |

Hash_Edge => Hash_Invocation_Graph_Edge, | |

Same_Edge => "="); | |

-- The following type represents the attributes of an invocation graph | |

type Invocation_Graph_Attributes is record | |

Counts : Invocation_Graph_Edge_Counts := (others => 0); | |

-- Edge statistics | |

Edge_Attributes : IGE_Tables.Dynamic_Hash_Table := IGE_Tables.Nil; | |

-- The map of edge -> edge attributes for all edges in the graph | |

Graph : DG.Directed_Graph := DG.Nil; | |

-- The underlying graph describing the relations between edges and | |

-- vertices. | |

Relations : Relation_Sets.Membership_Set := Relation_Sets.Nil; | |

-- The set of relations between source and targets, used to prevent | |

-- duplicate edges in the graph. | |

Roots : IGV_Sets.Membership_Set := IGV_Sets.Nil; | |

-- The set of elaboration root vertices | |

Signature_To_Vertex : Signature_Tables.Dynamic_Hash_Table := | |

Signature_Tables.Nil; | |

-- The map of signature -> vertex | |

Vertex_Attributes : IGV_Tables.Dynamic_Hash_Table := IGV_Tables.Nil; | |

-- The map of vertex -> vertex attributes for all vertices in the | |

-- graph. | |

Lib_Graph : Library_Graphs.Library_Graph; | |

end record; | |

type Invocation_Graph is access Invocation_Graph_Attributes; | |

Nil : constant Invocation_Graph := null; | |

--------------- | |

-- Iterators -- | |

--------------- | |

type All_Edge_Iterator is new DG.All_Edge_Iterator; | |

type All_Vertex_Iterator is new DG.All_Vertex_Iterator; | |

type Edges_To_Targets_Iterator is new DG.Outgoing_Edge_Iterator; | |

type Elaboration_Root_Iterator is new IGV_Sets.Iterator; | |

end Invocation_Graphs; | |

end Bindo.Graphs; |