[Ada] Management of internal data structures in Sem_Elab
authorHristian Kirtchev <kirtchev@adacore.com>
Thu, 4 Jul 2019 08:06:54 +0000 (08:06 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Thu, 4 Jul 2019 08:06:54 +0000 (08:06 +0000)
This patch modifies the timing of Sem_Elab's internal data structure
creation and destruction, and adds the concept of "active" elaboration
compiler phase.

The elaboration phase of the compiler is active after the frontend
initializes Sem_Elab. It is at this point that all internal data
structures of Sem_Elab are created and become ready to accept data.

The elaboration phase of the compiler is completed after all elaboration
scenarios are examined, all ABE checks are intalled, and diagnostics are
emitted. It is at this point that all internal data structures of
Sem_Elab are destroyed. Further attempts to reintroduce data into
Sem_Elab by subsequent compiler phases are cut off.

Compilation using GCC unaffected.

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

gcc/ada/

* sem_elab.adb: Add new type Elaboration_Phase_Status along with
a global to keep track of the elaboration phase status.
Initialize all internal data structures to Nil for services
Elaborated_Units, Internal_Representation, and Scenario_Storage.
(Build_Call_Marker): Do not create a call marker when the
elaboration phase is not active.
(Build_Variable_Reference_Marker): Do not create a call marker
when the elaboration phase is not active.
(Check_Elaboration_Scenarios): Destroy all internal structures
when the elaboration phase does not have to run. Do not execute
when the elaboration phase is not active.
(Elaboration_Phase_Active): New routine.
(Finalize_All_Data_Structures): New routine.
(Initialize): Initialize all internal data structures and signal
that the elaboration phase has started.
(Initialize_All_Data_Structures): New routine.
(Initialize_Elaborated_Units): Initialize all internal data
structures.
(Initialize_Internal_Representation): Initialize all internal
data structures.
(Initialize_Scenario_Storage): Initialize all internal data
structures.
(Kill_Elaboration_Scenario): Do not execute when the elaboration
phase is not active.
(Set_Elaboration_Phase): New routine.
(Update_Elaboration_Scenario): Do not execute when the
elaboration phase is not active.

From-SVN: r273066

gcc/ada/ChangeLog
gcc/ada/sem_elab.adb

index 5eb10d285391f98ec1adf18274e580afe0ae169c..9d46f39912a5cc59b3a085863b54eedf30b28a28 100644 (file)
@@ -1,3 +1,33 @@
+2019-07-04  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * sem_elab.adb: Add new type Elaboration_Phase_Status along with
+       a global to keep track of the elaboration phase status.
+       Initialize all internal data structures to Nil for services
+       Elaborated_Units, Internal_Representation, and Scenario_Storage.
+       (Build_Call_Marker): Do not create a call marker when the
+       elaboration phase is not active.
+       (Build_Variable_Reference_Marker): Do not create a call marker
+       when the elaboration phase is not active.
+       (Check_Elaboration_Scenarios): Destroy all internal structures
+       when the elaboration phase does not have to run. Do not execute
+       when the elaboration phase is not active.
+       (Elaboration_Phase_Active): New routine.
+       (Finalize_All_Data_Structures): New routine.
+       (Initialize): Initialize all internal data structures and signal
+       that the elaboration phase has started.
+       (Initialize_All_Data_Structures): New routine.
+       (Initialize_Elaborated_Units): Initialize all internal data
+       structures.
+       (Initialize_Internal_Representation): Initialize all internal
+       data structures.
+       (Initialize_Scenario_Storage): Initialize all internal data
+       structures.
+       (Kill_Elaboration_Scenario): Do not execute when the elaboration
+       phase is not active.
+       (Set_Elaboration_Phase): New routine.
+       (Update_Elaboration_Scenario): Do not execute when the
+       elaboration phase is not active.
+
 2019-07-04  Gary Dismukes  <dismukes@adacore.com>
 
        * sem_ch6.adb (Analyze_Subprogram_Body_Helper): The special
index f57b3b1151ab92e11ec21f47f2e104155659b92a..ce0950d2a32c9a92759e17a68bab1800732a74b1 100644 (file)
@@ -676,6 +676,22 @@ package body Sem_Elab is
    -- Kinds --
    -----------
 
+   --  The following type enumerates all possible elaboration phase statutes
+
+   type Elaboration_Phase_Status is
+     (Inactive,
+      --  The elaboration phase of the compiler has not started yet
+
+      Active,
+      --  The elaboration phase of the compiler is currently in progress
+
+      Completed);
+      --  The elaboration phase of the compiler has finished
+
+   Elaboration_Phase : Elaboration_Phase_Status := Inactive;
+   --  The status of the elaboration phase. Use routine Set_Elaboration_Phase
+   --  to alter its value.
+
    --  The following type enumerates all subprogram body traversal modes
 
    type Body_Traversal_Kind is
@@ -1958,6 +1974,14 @@ package body Sem_Elab is
    --  Return the type of subprogram Subp_Id's first formal parameter. If the
    --  subprogram lacks formal parameters, return Empty.
 
+   function Elaboration_Phase_Active return Boolean;
+   pragma Inline (Elaboration_Phase_Active);
+   --  Determine whether the elaboration phase of the compilation has started
+
+   procedure Finalize_All_Data_Structures;
+   pragma Inline (Finalize_All_Data_Structures);
+   --  Destroy all internal data structures
+
    function Has_Body (Pack_Decl : Node_Id) return Boolean;
    pragma Inline (Has_Body);
    --  Determine whether package declaration Pack_Decl has a corresponding body
@@ -1984,6 +2008,10 @@ package body Sem_Elab is
    --  context ignoring enclosing library levels. Nested_OK should be set when
    --  the context of N1 can enclose that of N2.
 
+   procedure Initialize_All_Data_Structures;
+   pragma Inline (Initialize_All_Data_Structures);
+   --  Create all internal data structures
+
    function Instantiated_Generic (Inst : Node_Id) return Entity_Id;
    pragma Inline (Instantiated_Generic);
    --  Obtain the generic instantiated by instance Inst
@@ -2027,6 +2055,10 @@ package body Sem_Elab is
    pragma Inline (Scenario);
    --  Return the appropriate scenario node for scenario N
 
+   procedure Set_Elaboration_Phase (Status : Elaboration_Phase_Status);
+   pragma Inline (Set_Elaboration_Phase);
+   --  Change the status of the elaboration phase of the compiler to Status
+
    procedure Spec_And_Body_From_Entity
      (Id        : Node_Id;
       Spec_Decl : out Node_Id;
@@ -3572,6 +3604,12 @@ package body Sem_Elab is
       elsif Preanalysis_Active then
          return;
 
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
+
+      elsif not Elaboration_Phase_Active then
+         return;
+
       --  Nothing to do when the input does not denote a call or a requeue
 
       elsif not Nkind_In (N, N_Entry_Call_Statement,
@@ -3789,6 +3827,13 @@ package body Sem_Elab is
    --  Start of processing for Build_Variable_Reference_Marker
 
    begin
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
+
+      if not Elaboration_Phase_Active then
+         return;
+      end if;
+
       Marker := Make_Variable_Reference_Marker (Sloc (N));
 
       --  Inherit the attributes of the original variable reference
@@ -3887,23 +3932,23 @@ package body Sem_Elab is
       --  to carry out this action.
 
       if Legacy_Elaboration_Checks then
+         Finalize_All_Data_Structures;
          return;
 
       --  Nothing to do for ASIS because ABE checks and diagnostics are not
       --  performed in this mode.
 
       elsif ASIS_Mode then
+         Finalize_All_Data_Structures;
          return;
-      end if;
 
-      --  Create all internal data structures
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
 
-      Initialize_Body_Processor;
-      Initialize_Early_Call_Region_Processor;
-      Initialize_Elaborated_Units;
-      Initialize_Internal_Representation;
-      Initialize_Invocation_Graph;
-      Initialize_Scenario_Storage;
+      elsif not Elaboration_Phase_Active then
+         Finalize_All_Data_Structures;
+         return;
+      end if;
 
       --  Restore the original elaboration model which was in effect when the
       --  scenarios were first recorded. The model may be specified by pragma
@@ -3949,14 +3994,11 @@ package body Sem_Elab is
 
       Record_Invocation_Graph;
 
-      --  Destroy all internal data structures
+      --  Destroy all internal data structures and complete the elaboration
+      --  phase of the compiler.
 
-      Finalize_Body_Processor;
-      Finalize_Early_Call_Region_Processor;
-      Finalize_Elaborated_Units;
-      Finalize_Internal_Representation;
-      Finalize_Invocation_Graph;
-      Finalize_Scenario_Storage;
+      Finalize_All_Data_Structures;
+      Set_Elaboration_Phase (Completed);
    end Check_Elaboration_Scenarios;
 
    ---------------------
@@ -7676,8 +7718,7 @@ package body Sem_Elab is
       --  The following map relates an elaboration attributes of a unit to the
       --  unit.
 
-      Unit_To_Attributes_Map : UA_Map.Dynamic_Hash_Table :=
-                                 UA_Map.Create (250);
+      Unit_To_Attributes_Map : UA_Map.Dynamic_Hash_Table := UA_Map.Nil;
 
       ------------------
       -- Constructors --
@@ -8519,7 +8560,7 @@ package body Sem_Elab is
 
       procedure Initialize_Elaborated_Units is
       begin
-         null;
+         Unit_To_Attributes_Map := UA_Map.Create (250);
       end Initialize_Elaborated_Units;
 
       ----------------------------------
@@ -8800,6 +8841,29 @@ package body Sem_Elab is
       end With_Clause;
    end Elaborated_Units;
 
+   ------------------------------
+   -- Elaboration_Phase_Active --
+   ------------------------------
+
+   function Elaboration_Phase_Active return Boolean is
+   begin
+      return Elaboration_Phase = Active;
+   end Elaboration_Phase_Active;
+
+   ----------------------------------
+   -- Finalize_All_Data_Structures --
+   ----------------------------------
+
+   procedure Finalize_All_Data_Structures is
+   begin
+      Finalize_Body_Processor;
+      Finalize_Early_Call_Region_Processor;
+      Finalize_Elaborated_Units;
+      Finalize_Internal_Representation;
+      Finalize_Invocation_Graph;
+      Finalize_Scenario_Storage;
+   end Finalize_All_Data_Structures;
+
    -----------------------------
    -- Find_Enclosing_Instance --
    -----------------------------
@@ -10072,8 +10136,28 @@ package body Sem_Elab is
       --  each time it is transformed into another node.
 
       Set_Rewriting_Proc (Update_Elaboration_Scenario'Access);
+
+      --  Create all internal data structures and activate the elaboration
+      --  phase of the compiler.
+
+      Initialize_All_Data_Structures;
+      Set_Elaboration_Phase (Active);
    end Initialize;
 
+   ------------------------------------
+   -- Initialize_All_Data_Structures --
+   ------------------------------------
+
+   procedure Initialize_All_Data_Structures is
+   begin
+      Initialize_Body_Processor;
+      Initialize_Early_Call_Region_Processor;
+      Initialize_Elaborated_Units;
+      Initialize_Internal_Representation;
+      Initialize_Invocation_Graph;
+      Initialize_Scenario_Storage;
+   end Initialize_All_Data_Structures;
+
    --------------------------
    -- Instantiated_Generic --
    --------------------------
@@ -10201,8 +10285,7 @@ package body Sem_Elab is
 
       --  The following map relates target representations to entities
 
-      Entity_To_Target_Map : ETT_Map.Dynamic_Hash_Table :=
-                               ETT_Map.Create (500);
+      Entity_To_Target_Map : ETT_Map.Dynamic_Hash_Table := ETT_Map.Nil;
 
       procedure Destroy (S_Id : in out Scenario_Rep_Id);
       --  Destroy a scenario representation S_Id
@@ -10221,8 +10304,7 @@ package body Sem_Elab is
 
       --  The following map relates scenario representations to nodes
 
-      Node_To_Scenario_Map : NTS_Map.Dynamic_Hash_Table :=
-                               NTS_Map.Create (500);
+      Node_To_Scenario_Map : NTS_Map.Dynamic_Hash_Table := NTS_Map.Nil;
 
       --  The following table stores all scenario representations
 
@@ -11058,7 +11140,8 @@ package body Sem_Elab is
 
       procedure Initialize_Internal_Representation is
       begin
-         null;
+         Entity_To_Target_Map := ETT_Map.Create (500);
+         Node_To_Scenario_Map := NTS_Map.Create (500);
       end Initialize_Internal_Representation;
 
       -------------------------
@@ -13422,6 +13505,12 @@ package body Sem_Elab is
 
       if Legacy_Elaboration_Checks then
          return;
+
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
+
+      elsif not Elaboration_Phase_Active then
+         return;
       end if;
 
       --  Eliminate a recorded scenario when it appears within dead code
@@ -13785,6 +13874,12 @@ package body Sem_Elab is
 
       elsif Preanalysis_Active then
          return;
+
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
+
+      elsif not Elaboration_Phase_Active then
+         return;
       end if;
 
       Scen_Lvl := Find_Enclosing_Level (Scen);
@@ -13889,16 +13984,11 @@ package body Sem_Elab is
 
       --  The following sets store all scenarios
 
-      Declaration_Scenarios       : NE_Set.Membership_Set :=
-                                      NE_Set.Create (1000);
-      Dynamic_ABE_Check_Scenarios : NE_Set.Membership_Set :=
-                                      NE_Set.Create (500);
-      Library_Body_Scenarios      : NE_Set.Membership_Set :=
-                                      NE_Set.Create (1000);
-      Library_Spec_Scenarios      : NE_Set.Membership_Set :=
-                                      NE_Set.Create (1000);
-      SPARK_Scenarios             : NE_Set.Membership_Set :=
-                                      NE_Set.Create (100);
+      Declaration_Scenarios       : NE_Set.Membership_Set := NE_Set.Nil;
+      Dynamic_ABE_Check_Scenarios : NE_Set.Membership_Set := NE_Set.Nil;
+      Library_Body_Scenarios      : NE_Set.Membership_Set := NE_Set.Nil;
+      Library_Spec_Scenarios      : NE_Set.Membership_Set := NE_Set.Nil;
+      SPARK_Scenarios             : NE_Set.Membership_Set := NE_Set.Nil;
 
       -------------------------------
       -- Finalize_Scenario_Storage --
@@ -13919,7 +14009,11 @@ package body Sem_Elab is
 
       procedure Initialize_Scenario_Storage is
       begin
-         null;
+         Declaration_Scenarios       := NE_Set.Create (1000);
+         Dynamic_ABE_Check_Scenarios := NE_Set.Create (500);
+         Library_Body_Scenarios      := NE_Set.Create (1000);
+         Library_Spec_Scenarios      := NE_Set.Create (1000);
+         SPARK_Scenarios             := NE_Set.Create (100);
       end Initialize_Scenario_Storage;
 
       ------------------------------
@@ -14796,6 +14890,15 @@ package body Sem_Elab is
       end Is_Up_Level_Target;
    end Semantics;
 
+   ---------------------------
+   -- Set_Elaboration_Phase --
+   ---------------------------
+
+   procedure Set_Elaboration_Phase (Status : Elaboration_Phase_Status) is
+   begin
+      Elaboration_Phase := Status;
+   end Set_Elaboration_Phase;
+
    ---------------------
    -- SPARK_Processor --
    ---------------------
@@ -15700,17 +15803,24 @@ package body Sem_Elab is
 
    procedure Update_Elaboration_Scenario (New_N : Node_Id; Old_N : Node_Id) is
    begin
+      --  Nothing to do when the elaboration phase of the compiler is not
+      --  active.
+
+      if not Elaboration_Phase_Active then
+         return;
+
       --  Nothing to do when the old and new scenarios are one and the same
 
-      if Old_N = New_N then
+      elsif Old_N = New_N then
          return;
+      end if;
 
       --  A scenario is being transformed by Atree.Rewrite. Update all relevant
       --  internal data structures to reflect this change. This ensures that a
       --  potential run-time conditional ABE check or a guaranteed ABE failure
       --  is inserted at the proper place in the tree.
 
-      elsif Is_Scenario (Old_N) then
+      if Is_Scenario (Old_N) then
          Replace_Scenario (Old_N, New_N);
       end if;
    end Update_Elaboration_Scenario;