view gcc/ada/bindo-units.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
line wrap: on
line source

------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                          B I N D O . U N I T S                           --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--             Copyright (C) 2019, 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.      --
--                                                                          --
------------------------------------------------------------------------------

with Bindo.Writers;
use  Bindo.Writers;
use  Bindo.Writers.Phase_Writers;

package body Bindo.Units is

   -------------------
   -- Signature set --
   -------------------

   package Signature_Sets is new Membership_Sets
     (Element_Type => Invocation_Signature_Id,
      "="          => "=",
      Hash         => Hash_Invocation_Signature);

   -----------------
   -- Global data --
   -----------------

   --  The following set stores all invocation signatures that appear in
   --  elaborable units.

   Elaborable_Constructs : Signature_Sets.Membership_Set := Signature_Sets.Nil;

   --  The following set stores all units the need to be elaborated

   Elaborable_Units : Unit_Sets.Membership_Set := Unit_Sets.Nil;

   -----------------------
   -- Local subprograms --
   -----------------------

   function Corresponding_Unit (Nam : Name_Id) return Unit_Id;
   pragma Inline (Corresponding_Unit);
   --  Obtain the unit which corresponds to name Nam

   function Is_Stand_Alone_Library_Unit (U_Id : Unit_Id) return Boolean;
   pragma Inline (Is_Stand_Alone_Library_Unit);
   --  Determine whether unit U_Id is part of a stand-alone library

   procedure Process_Invocation_Construct (IC_Id : Invocation_Construct_Id);
   pragma Inline (Process_Invocation_Construct);
   --  Process invocation construct IC_Id by adding its signature to set
   --  Elaborable_Constructs_Set.

   procedure Process_Invocation_Constructs (U_Id : Unit_Id);
   pragma Inline (Process_Invocation_Constructs);
   --  Process all invocation constructs of unit U_Id for classification
   --  purposes.

   procedure Process_Unit (U_Id : Unit_Id);
   pragma Inline (Process_Unit);
   --  Process unit U_Id for unit classification purposes

   ------------------------------
   -- Collect_Elaborable_Units --
   ------------------------------

   procedure Collect_Elaborable_Units is
   begin
      Start_Phase (Unit_Collection);

      for U_Id in ALI.Units.First .. ALI.Units.Last loop
         Process_Unit (U_Id);
      end loop;

      End_Phase (Unit_Collection);
   end Collect_Elaborable_Units;

   ------------------------
   -- Corresponding_Body --
   ------------------------

   function Corresponding_Body (U_Id : Unit_Id) return Unit_Id is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      pragma Assert (U_Rec.Utype = Is_Spec);
      return U_Id - 1;
   end Corresponding_Body;

   ------------------------
   -- Corresponding_Spec --
   ------------------------

   function Corresponding_Spec (U_Id : Unit_Id) return Unit_Id is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      pragma Assert (U_Rec.Utype = Is_Body);
      return U_Id + 1;
   end Corresponding_Spec;

   ------------------------
   -- Corresponding_Unit --
   ------------------------

   function Corresponding_Unit (FNam : File_Name_Type) return Unit_Id is
   begin
      return Corresponding_Unit (Name_Id (FNam));
   end Corresponding_Unit;

   ------------------------
   -- Corresponding_Unit --
   ------------------------

   function Corresponding_Unit (Nam : Name_Id) return Unit_Id is
   begin
      return Unit_Id (Get_Name_Table_Int (Nam));
   end Corresponding_Unit;

   ------------------------
   -- Corresponding_Unit --
   ------------------------

   function Corresponding_Unit (UNam : Unit_Name_Type) return Unit_Id is
   begin
      return Corresponding_Unit (Name_Id (UNam));
   end Corresponding_Unit;

   ---------------
   -- File_Name --
   ---------------

   function File_Name (U_Id : Unit_Id) return File_Name_Type is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.Sfile;
   end File_Name;

   --------------------
   -- Finalize_Units --
   --------------------

   procedure Finalize_Units is
   begin
      Signature_Sets.Destroy (Elaborable_Constructs);
      Unit_Sets.Destroy      (Elaborable_Units);
   end Finalize_Units;

   ------------------------------
   -- For_Each_Elaborable_Unit --
   ------------------------------

   procedure For_Each_Elaborable_Unit (Processor : Unit_Processor_Ptr) is
      Iter : Elaborable_Units_Iterator;
      U_Id : Unit_Id;

   begin
      Iter := Iterate_Elaborable_Units;
      while Has_Next (Iter) loop
         Next (Iter, U_Id);

         Processor.all (U_Id);
      end loop;
   end For_Each_Elaborable_Unit;

   -------------------
   -- For_Each_Unit --
   -------------------

   procedure For_Each_Unit (Processor : Unit_Processor_Ptr) is
   begin
      for U_Id in ALI.Units.First .. ALI.Units.Last loop
         Processor.all (U_Id);
      end loop;
   end For_Each_Unit;

   --------------
   -- Has_Next --
   --------------

   function Has_Next (Iter : Elaborable_Units_Iterator) return Boolean is
   begin
      return Unit_Sets.Has_Next (Unit_Sets.Iterator (Iter));
   end Has_Next;

   -----------------------------
   -- Has_No_Elaboration_Code --
   -----------------------------

   function Has_No_Elaboration_Code (U_Id : Unit_Id) return Boolean is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.No_Elab;
   end Has_No_Elaboration_Code;

   -------------------------------
   -- Hash_Invocation_Signature --
   -------------------------------

   function Hash_Invocation_Signature
     (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type
   is
   begin
      pragma Assert (Present (IS_Id));

      return Bucket_Range_Type (IS_Id);
   end Hash_Invocation_Signature;

   ---------------
   -- Hash_Unit --
   ---------------

   function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type is
   begin
      pragma Assert (Present (U_Id));

      return Bucket_Range_Type (U_Id);
   end Hash_Unit;

   ----------------------
   -- Initialize_Units --
   ----------------------

   procedure Initialize_Units is
   begin
      Elaborable_Constructs := Signature_Sets.Create (Number_Of_Units);
      Elaborable_Units      := Unit_Sets.Create      (Number_Of_Units);
   end Initialize_Units;

   -------------------------------
   -- Invocation_Graph_Encoding --
   -------------------------------

   function Invocation_Graph_Encoding
     (U_Id : Unit_Id) return Invocation_Graph_Encoding_Kind
   is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
      U_ALI : ALIs_Record renames ALI.ALIs.Table  (U_Rec.My_ALI);

   begin
      return U_ALI.Invocation_Graph_Encoding;
   end Invocation_Graph_Encoding;

   -------------------------------
   -- Is_Dynamically_Elaborated --
   -------------------------------

   function Is_Dynamically_Elaborated (U_Id : Unit_Id) return Boolean is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.Dynamic_Elab;
   end Is_Dynamically_Elaborated;

   ----------------------
   -- Is_Internal_Unit --
   ----------------------

   function Is_Internal_Unit (U_Id : Unit_Id) return Boolean is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.Internal;
   end Is_Internal_Unit;

   ------------------------
   -- Is_Predefined_Unit --
   ------------------------

   function Is_Predefined_Unit (U_Id : Unit_Id) return Boolean is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.Predefined;
   end Is_Predefined_Unit;

   ---------------------------------
   -- Is_Stand_Alone_Library_Unit --
   ---------------------------------

   function Is_Stand_Alone_Library_Unit (U_Id : Unit_Id) return Boolean is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.SAL_Interface;
   end Is_Stand_Alone_Library_Unit;

   ------------------------------
   -- Iterate_Elaborable_Units --
   ------------------------------

   function Iterate_Elaborable_Units return Elaborable_Units_Iterator is
   begin
      return Elaborable_Units_Iterator (Unit_Sets.Iterate (Elaborable_Units));
   end Iterate_Elaborable_Units;

   ----------
   -- Name --
   ----------

   function Name (U_Id : Unit_Id) return Unit_Name_Type is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      return U_Rec.Uname;
   end Name;

   -----------------------
   -- Needs_Elaboration --
   -----------------------

   function Needs_Elaboration
     (IS_Id : Invocation_Signature_Id) return Boolean
   is
   begin
      pragma Assert (Present (IS_Id));

      return Signature_Sets.Contains (Elaborable_Constructs, IS_Id);
   end Needs_Elaboration;

   -----------------------
   -- Needs_Elaboration --
   -----------------------

   function Needs_Elaboration (U_Id : Unit_Id) return Boolean is
   begin
      pragma Assert (Present (U_Id));

      return Unit_Sets.Contains (Elaborable_Units, U_Id);
   end Needs_Elaboration;

   ----------
   -- Next --
   ----------

   procedure Next
     (Iter : in out Elaborable_Units_Iterator;
      U_Id : out Unit_Id)
   is
   begin
      Unit_Sets.Next (Unit_Sets.Iterator (Iter), U_Id);
   end Next;

   --------------------------------
   -- Number_Of_Elaborable_Units --
   --------------------------------

   function Number_Of_Elaborable_Units return Natural is
   begin
      return Unit_Sets.Size (Elaborable_Units);
   end Number_Of_Elaborable_Units;

   ---------------------
   -- Number_Of_Units --
   ---------------------

   function Number_Of_Units return Natural is
   begin
      return Natural (ALI.Units.Last) - Natural (ALI.Units.First) + 1;
   end Number_Of_Units;

   ----------------------------------
   -- Process_Invocation_Construct --
   ----------------------------------

   procedure Process_Invocation_Construct (IC_Id : Invocation_Construct_Id) is
      pragma Assert (Present (IC_Id));

      IS_Id : constant Invocation_Signature_Id := Signature (IC_Id);

      pragma Assert (Present (IS_Id));

   begin
      Signature_Sets.Insert (Elaborable_Constructs, IS_Id);
   end Process_Invocation_Construct;

   -----------------------------------
   -- Process_Invocation_Constructs --
   -----------------------------------

   procedure Process_Invocation_Constructs (U_Id : Unit_Id) is
      pragma Assert (Present (U_Id));

      U_Rec : Unit_Record renames ALI.Units.Table (U_Id);

   begin
      for IC_Id in U_Rec.First_Invocation_Construct ..
                   U_Rec.Last_Invocation_Construct
      loop
         Process_Invocation_Construct (IC_Id);
      end loop;
   end Process_Invocation_Constructs;

   ------------------
   -- Process_Unit --
   ------------------

   procedure Process_Unit (U_Id : Unit_Id) is
   begin
      pragma Assert (Present (U_Id));

      --  A stand-alone library unit must not be elaborated as part of the
      --  current compilation because the library already carries its own
      --  elaboration code.

      if Is_Stand_Alone_Library_Unit (U_Id) then
         null;

      --  Otherwise the unit needs to be elaborated. Add it to the set
      --  of units that require elaboration, as well as all invocation
      --  signatures of constructs it declares.

      else
         Unit_Sets.Insert (Elaborable_Units, U_Id);
         Process_Invocation_Constructs (U_Id);
      end if;
   end Process_Unit;

end Bindo.Units;