diff gcc/ada/ali.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/ada/ali.adb	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/ada/ali.adb	Thu Feb 13 11:34:05 2020 +0900
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2018, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-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- --
@@ -29,39 +29,584 @@
 with Opt;    use Opt;
 with Osint;  use Osint;
 with Output; use Output;
+with Snames; use Snames;
+
+with GNAT;                 use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
 
 package body ALI is
 
    use ASCII;
    --  Make control characters visible
 
+   -----------
+   -- Types --
+   -----------
+
+   --  The following type represents an invocation construct
+
+   type Invocation_Construct_Record is record
+      Body_Placement : Declaration_Placement_Kind := No_Declaration_Placement;
+      --  The location of the invocation construct's body with respect to the
+      --  unit where it is declared.
+
+      Kind : Invocation_Construct_Kind := Regular_Construct;
+      --  The nature of the invocation construct
+
+      Signature : Invocation_Signature_Id := No_Invocation_Signature;
+      --  The invocation signature that uniquely identifies the invocation
+      --  construct in the ALI space.
+
+      Spec_Placement : Declaration_Placement_Kind := No_Declaration_Placement;
+      --  The location of the invocation construct's spec with respect to the
+      --  unit where it is declared.
+   end record;
+
+   --  The following type represents an invocation relation. It associates an
+   --  invoker that activates/calls/instantiates with a target.
+
+   type Invocation_Relation_Record is record
+      Extra : Name_Id := No_Name;
+      --  The name of an additional entity used in error diagnostics
+
+      Invoker : Invocation_Signature_Id := No_Invocation_Signature;
+      --  The invocation signature that uniquely identifies the invoker within
+      --  the ALI space.
+
+      Kind : Invocation_Kind := No_Invocation;
+      --  The nature of the invocation
+
+      Target : Invocation_Signature_Id := No_Invocation_Signature;
+      --  The invocation signature that uniquely identifies the target within
+      --  the ALI space.
+   end record;
+
+   --  The following type represents an invocation signature. Its purpose is
+   --  to uniquely identify an invocation construct within the ALI space. The
+   --  signature comprises several pieces, some of which are used in error
+   --  diagnostics by the binder. Identification issues are resolved as
+   --  follows:
+   --
+   --    * The Column, Line, and Locations attributes together differentiate
+   --      between homonyms. In most cases, the Column and Line are sufficient
+   --      except when generic instantiations are involved. Together, the three
+   --      attributes offer a sequence of column-line pairs that eventually
+   --      reflect the location within the generic template.
+   --
+   --    * The Name attribute differentiates between invocation constructs at
+   --      the scope level. Since it is illegal for two entities with the same
+   --      name to coexist in the same scope, the Name attribute is sufficient
+   --      to distinguish them. Overloaded entities are already handled by the
+   --      Column, Line, and Locations attributes.
+   --
+   --    * The Scope attribute differentiates between invocation constructs at
+   --      various levels of nesting.
+
+   type Invocation_Signature_Record is record
+      Column : Nat := 0;
+      --  The column number where the invocation construct is declared
+
+      Line : Nat := 0;
+      --  The line number where the invocation construct is declared
+
+      Locations : Name_Id := No_Name;
+      --  Sequence of column and line numbers within nested instantiations
+
+      Name : Name_Id := No_Name;
+      --  The name of the invocation construct
+
+      Scope : Name_Id := No_Name;
+      --  The qualified name of the scope where the invocation construct is
+      --  declared.
+   end record;
+
+   ---------------------
+   -- Data structures --
+   ---------------------
+
+   package Invocation_Constructs is new Table.Table
+     (Table_Index_Type     => Invocation_Construct_Id,
+      Table_Component_Type => Invocation_Construct_Record,
+      Table_Low_Bound      => First_Invocation_Construct,
+      Table_Initial        => 2500,
+      Table_Increment      => 200,
+      Table_Name           => "Invocation_Constructs");
+
+   package Invocation_Relations is new Table.Table
+     (Table_Index_Type     => Invocation_Relation_Id,
+      Table_Component_Type => Invocation_Relation_Record,
+      Table_Low_Bound      => First_Invocation_Relation,
+      Table_Initial        => 2500,
+      Table_Increment      => 200,
+      Table_Name           => "Invocation_Relation");
+
+   package Invocation_Signatures is new Table.Table
+     (Table_Index_Type     => Invocation_Signature_Id,
+      Table_Component_Type => Invocation_Signature_Record,
+      Table_Low_Bound      => First_Invocation_Signature,
+      Table_Initial        => 2500,
+      Table_Increment      => 200,
+      Table_Name           => "Invocation_Signatures");
+
+   procedure Destroy (IS_Id : in out Invocation_Signature_Id);
+   --  Destroy an invocation signature with id IS_Id
+
+   function Hash
+     (IS_Rec : Invocation_Signature_Record) return Bucket_Range_Type;
+   --  Obtain the hash of key IS_Rec
+
+   package Sig_Map is new Dynamic_Hash_Tables
+     (Key_Type              => Invocation_Signature_Record,
+      Value_Type            => Invocation_Signature_Id,
+      No_Value              => No_Invocation_Signature,
+      Expansion_Threshold   => 1.5,
+      Expansion_Factor      => 2,
+      Compression_Threshold => 0.3,
+      Compression_Factor    => 2,
+      "="                   => "=",
+      Destroy_Value         => Destroy,
+      Hash                  => Hash);
+
+   --  The following map relates invocation signature records to invocation
+   --  signature ids.
+
+   Sig_To_Sig_Map : constant Sig_Map.Dynamic_Hash_Table :=
+                      Sig_Map.Create (500);
+
+   --  The folowing table maps declaration placement kinds to character codes
+   --  for invocation construct encoding in ALI files.
+
+   Declaration_Placement_Codes :
+     constant array (Declaration_Placement_Kind) of Character :=
+       (In_Body                  => 'b',
+        In_Spec                  => 's',
+        No_Declaration_Placement => 'Z');
+
+   Compile_Time_Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind :=
+                                              No_Encoding;
+   --  The invocation-graph encoding format as specified at compile time. Do
+   --  not manipulate this value directly.
+
+   --  The following table maps invocation kinds to character codes for
+   --  invocation relation encoding in ALI files.
+
+   Invocation_Codes :
+     constant array (Invocation_Kind) of Character :=
+       (Accept_Alternative                     => 'a',
+        Access_Taken                           => 'b',
+        Call                                   => 'c',
+        Controlled_Adjustment                  => 'd',
+        Controlled_Finalization                => 'e',
+        Controlled_Initialization              => 'f',
+        Default_Initial_Condition_Verification => 'g',
+        Initial_Condition_Verification         => 'h',
+        Instantiation                          => 'i',
+        Internal_Controlled_Adjustment         => 'j',
+        Internal_Controlled_Finalization       => 'k',
+        Internal_Controlled_Initialization     => 'l',
+        Invariant_Verification                 => 'm',
+        Postcondition_Verification             => 'n',
+        Protected_Entry_Call                   => 'o',
+        Protected_Subprogram_Call              => 'p',
+        Task_Activation                        => 'q',
+        Task_Entry_Call                        => 'r',
+        Type_Initialization                    => 's',
+        No_Invocation                          => 'Z');
+
+   --  The following table maps invocation construct kinds to character codes
+   --  for invocation construct encoding in ALI files.
+
+   Invocation_Construct_Codes :
+     constant array (Invocation_Construct_Kind) of Character :=
+       (Elaborate_Body_Procedure => 'b',
+        Elaborate_Spec_Procedure => 's',
+        Regular_Construct        => 'Z');
+
+   --  The following table maps invocation-graph encoding kinds to character
+   --  codes for invocation-graph encoding in ALI files.
+
+   Invocation_Graph_Encoding_Codes :
+     constant array (Invocation_Graph_Encoding_Kind) of Character :=
+       (Full_Path_Encoding => 'f',
+        Endpoints_Encoding => 'e',
+        No_Encoding        => 'Z');
+
+   --  The following table maps invocation-graph line kinds to character codes
+   --  used in ALI files.
+
+   Invocation_Graph_Line_Codes :
+     constant array (Invocation_Graph_Line_Kind) of Character :=
+       (Invocation_Construct_Line        => 'c',
+        Invocation_Graph_Attributes_Line => 'a',
+        Invocation_Relation_Line         => 'r');
+
    --  The following variable records which characters currently are used as
    --  line type markers in the ALI file. This is used in Scan_ALI to detect
    --  (or skip) invalid lines. The following letters are still available:
    --
-   --    B F G H J K O Q Z
+   --    B F H J K O Q Z
 
    Known_ALI_Lines : constant array (Character range 'A' .. 'Z') of Boolean :=
-     ('V'    => True,   -- version
-      'M'    => True,   -- main program
-      'A'    => True,   -- argument
-      'P'    => True,   -- program
-      'R'    => True,   -- restriction
-      'I'    => True,   -- interrupt
-      'U'    => True,   -- unit
-      'W'    => True,   -- with
-      'L'    => True,   -- linker option
-      'N'    => True,   -- notes
-      'E'    => True,   -- external
-      'D'    => True,   -- dependency
-      'X'    => True,   -- xref
-      'S'    => True,   -- specific dispatching
-      'Y'    => True,   -- limited_with
-      'Z'    => True,   -- implicit with from instantiation
-      'C'    => True,   -- SCO information
-      'T'    => True,   -- task stack information
+     ('A'    => True,  --  argument
+      'C'    => True,  --  SCO information
+      'D'    => True,  --  dependency
+      'E'    => True,  --  external
+      'G'    => True,  --  invocation graph
+      'I'    => True,  --  interrupt
+      'L'    => True,  --  linker option
+      'M'    => True,  --  main program
+      'N'    => True,  --  notes
+      'P'    => True,  --  program
+      'R'    => True,  --  restriction
+      'S'    => True,  --  specific dispatching
+      'T'    => True,  --  task stack information
+      'U'    => True,  --  unit
+      'V'    => True,  --  version
+      'W'    => True,  --  with
+      'X'    => True,  --  xref
+      'Y'    => True,  --  limited_with
+      'Z'    => True,  --  implicit with from instantiation
       others => False);
 
+   ------------------------------
+   -- Add_Invocation_Construct --
+   ------------------------------
+
+   procedure Add_Invocation_Construct
+     (Body_Placement : Declaration_Placement_Kind;
+      Kind           : Invocation_Construct_Kind;
+      Signature      : Invocation_Signature_Id;
+      Spec_Placement : Declaration_Placement_Kind;
+      Update_Units   : Boolean := True)
+   is
+   begin
+      pragma Assert (Present (Signature));
+
+      --  Create a invocation construct from the scanned attributes
+
+      Invocation_Constructs.Append
+        ((Body_Placement => Body_Placement,
+          Kind           => Kind,
+          Signature      => Signature,
+          Spec_Placement => Spec_Placement));
+
+      --  Update the invocation construct counter of the current unit only when
+      --  requested by the caller.
+
+      if Update_Units then
+         declare
+            Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+
+         begin
+            Curr_Unit.Last_Invocation_Construct := Invocation_Constructs.Last;
+         end;
+      end if;
+   end Add_Invocation_Construct;
+
+   -----------------------------
+   -- Add_Invocation_Relation --
+   -----------------------------
+
+   procedure Add_Invocation_Relation
+     (Extra        : Name_Id;
+      Invoker      : Invocation_Signature_Id;
+      Kind         : Invocation_Kind;
+      Target       : Invocation_Signature_Id;
+      Update_Units : Boolean := True)
+   is
+   begin
+      pragma Assert (Present (Invoker));
+      pragma Assert (Kind /= No_Invocation);
+      pragma Assert (Present (Target));
+
+      --  Create an invocation relation from the scanned attributes
+
+      Invocation_Relations.Append
+        ((Extra   => Extra,
+          Invoker => Invoker,
+          Kind    => Kind,
+          Target  => Target));
+
+      --  Update the invocation relation counter of the current unit only when
+      --  requested by the caller.
+
+      if Update_Units then
+         declare
+            Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+
+         begin
+            Curr_Unit.Last_Invocation_Relation := Invocation_Relations.Last;
+         end;
+      end if;
+   end Add_Invocation_Relation;
+
+   --------------------
+   -- Body_Placement --
+   --------------------
+
+   function Body_Placement
+     (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind
+   is
+   begin
+      pragma Assert (Present (IC_Id));
+      return Invocation_Constructs.Table (IC_Id).Body_Placement;
+   end Body_Placement;
+
+   ----------------------------------------
+   -- Code_To_Declaration_Placement_Kind --
+   ----------------------------------------
+
+   function Code_To_Declaration_Placement_Kind
+     (Code : Character) return Declaration_Placement_Kind
+   is
+   begin
+      --  Determine which placement kind corresponds to the character code by
+      --  traversing the contents of the mapping table.
+
+      for Kind in Declaration_Placement_Kind loop
+         if Declaration_Placement_Codes (Kind) = Code then
+            return Kind;
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Code_To_Declaration_Placement_Kind;
+
+   ---------------------------------------
+   -- Code_To_Invocation_Construct_Kind --
+   ---------------------------------------
+
+   function Code_To_Invocation_Construct_Kind
+     (Code : Character) return Invocation_Construct_Kind
+   is
+   begin
+      --  Determine which invocation construct kind matches the character code
+      --  by traversing the contents of the mapping table.
+
+      for Kind in Invocation_Construct_Kind loop
+         if Invocation_Construct_Codes (Kind) = Code then
+            return Kind;
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Code_To_Invocation_Construct_Kind;
+
+   --------------------------------------------
+   -- Code_To_Invocation_Graph_Encoding_Kind --
+   --------------------------------------------
+
+   function Code_To_Invocation_Graph_Encoding_Kind
+     (Code : Character) return Invocation_Graph_Encoding_Kind
+   is
+   begin
+      --  Determine which invocation-graph encoding kind matches the character
+      --  code by traversing the contents of the mapping table.
+
+      for Kind in Invocation_Graph_Encoding_Kind loop
+         if Invocation_Graph_Encoding_Codes (Kind) = Code then
+            return Kind;
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Code_To_Invocation_Graph_Encoding_Kind;
+
+   -----------------------------
+   -- Code_To_Invocation_Kind --
+   -----------------------------
+
+   function Code_To_Invocation_Kind
+     (Code : Character) return Invocation_Kind
+   is
+   begin
+      --  Determine which invocation kind corresponds to the character code by
+      --  traversing the contents of the mapping table.
+
+      for Kind in Invocation_Kind loop
+         if Invocation_Codes (Kind) = Code then
+            return Kind;
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Code_To_Invocation_Kind;
+
+   ----------------------------------------
+   -- Code_To_Invocation_Graph_Line_Kind --
+   ----------------------------------------
+
+   function Code_To_Invocation_Graph_Line_Kind
+     (Code : Character) return Invocation_Graph_Line_Kind
+   is
+   begin
+      --  Determine which invocation-graph line kind matches the character
+      --  code by traversing the contents of the mapping table.
+
+      for Kind in Invocation_Graph_Line_Kind loop
+         if Invocation_Graph_Line_Codes (Kind) = Code then
+            return Kind;
+         end if;
+      end loop;
+
+      raise Program_Error;
+   end Code_To_Invocation_Graph_Line_Kind;
+
+   ------------
+   -- Column --
+   ------------
+
+   function Column (IS_Id : Invocation_Signature_Id) return Nat is
+   begin
+      pragma Assert (Present (IS_Id));
+      return Invocation_Signatures.Table (IS_Id).Column;
+   end Column;
+
+   ----------------------------------------
+   -- Declaration_Placement_Kind_To_Code --
+   ----------------------------------------
+
+   function Declaration_Placement_Kind_To_Code
+     (Kind : Declaration_Placement_Kind) return Character
+   is
+   begin
+      return Declaration_Placement_Codes (Kind);
+   end Declaration_Placement_Kind_To_Code;
+
+   -------------
+   -- Destroy --
+   -------------
+
+   procedure Destroy (IS_Id : in out Invocation_Signature_Id) is
+      pragma Unreferenced (IS_Id);
+   begin
+      null;
+   end Destroy;
+
+   -----------
+   -- Extra --
+   -----------
+
+   function Extra (IR_Id : Invocation_Relation_Id) return Name_Id is
+   begin
+      pragma Assert (Present (IR_Id));
+      return Invocation_Relations.Table (IR_Id).Extra;
+   end Extra;
+
+   -----------------------------------
+   -- For_Each_Invocation_Construct --
+   -----------------------------------
+
+   procedure For_Each_Invocation_Construct
+     (Processor : Invocation_Construct_Processor_Ptr)
+   is
+   begin
+      pragma Assert (Processor /= null);
+
+      for IC_Id in Invocation_Constructs.First ..
+                   Invocation_Constructs.Last
+      loop
+         Processor.all (IC_Id);
+      end loop;
+   end For_Each_Invocation_Construct;
+
+   -----------------------------------
+   -- For_Each_Invocation_Construct --
+   -----------------------------------
+
+   procedure For_Each_Invocation_Construct
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Construct_Processor_Ptr)
+   is
+      pragma Assert (Present (U_Id));
+      pragma Assert (Processor /= null);
+
+      U_Rec : Unit_Record renames Units.Table (U_Id);
+
+   begin
+      for IC_Id in U_Rec.First_Invocation_Construct ..
+                   U_Rec.Last_Invocation_Construct
+      loop
+         Processor.all (IC_Id);
+      end loop;
+   end For_Each_Invocation_Construct;
+
+   ----------------------------------
+   -- For_Each_Invocation_Relation --
+   ----------------------------------
+
+   procedure For_Each_Invocation_Relation
+     (Processor : Invocation_Relation_Processor_Ptr)
+   is
+   begin
+      pragma Assert (Processor /= null);
+
+      for IR_Id in Invocation_Relations.First ..
+                   Invocation_Relations.Last
+      loop
+         Processor.all (IR_Id);
+      end loop;
+   end For_Each_Invocation_Relation;
+
+   ----------------------------------
+   -- For_Each_Invocation_Relation --
+   ----------------------------------
+
+   procedure For_Each_Invocation_Relation
+     (U_Id      : Unit_Id;
+      Processor : Invocation_Relation_Processor_Ptr)
+   is
+      pragma Assert (Present (U_Id));
+      pragma Assert (Processor /= null);
+
+      U_Rec : Unit_Record renames Units.Table (U_Id);
+
+   begin
+      for IR_Id in U_Rec.First_Invocation_Relation ..
+                   U_Rec.Last_Invocation_Relation
+      loop
+         Processor.all (IR_Id);
+      end loop;
+   end For_Each_Invocation_Relation;
+
+   ----------
+   -- Hash --
+   ----------
+
+   function Hash
+     (IS_Rec : Invocation_Signature_Record) return Bucket_Range_Type
+   is
+      Buffer : Bounded_String (2052);
+      IS_Nam : Name_Id;
+
+   begin
+      --  The hash is obtained in the following manner:
+      --
+      --    * A String signature based on the scope, name, line number, column
+      --      number, and locations, in the following format:
+      --
+      --         scope__name__line_column__locations
+      --
+      --    * The String is converted into a Name_Id
+      --    * The Name_Id is used as the hash
+
+      Append (Buffer, IS_Rec.Scope);
+      Append (Buffer, "__");
+      Append (Buffer, IS_Rec.Name);
+      Append (Buffer, "__");
+      Append (Buffer, IS_Rec.Line);
+      Append (Buffer, '_');
+      Append (Buffer, IS_Rec.Column);
+
+      if IS_Rec.Locations /= No_Name then
+         Append (Buffer, "__");
+         Append (Buffer, IS_Rec.Locations);
+      end if;
+
+      IS_Nam := Name_Find (Buffer);
+      return Bucket_Range_Type (IS_Nam);
+   end Hash;
+
    --------------------
    -- Initialize_ALI --
    --------------------
@@ -90,18 +635,21 @@
       --  Initialize all tables
 
       ALIs.Init;
+      Invocation_Constructs.Init;
+      Invocation_Relations.Init;
+      Invocation_Signatures.Init;
+      Linker_Options.Init;
       No_Deps.Init;
-      Units.Init;
-      Withs.Init;
+      Notes.Init;
       Sdep.Init;
-      Linker_Options.Init;
-      Notes.Init;
-      Xref_Section.Init;
+      Units.Init;
+      Version_Ref.Reset;
+      Withs.Init;
       Xref_Entity.Init;
       Xref.Init;
-      Version_Ref.Reset;
-
-      --  Add dummy zero'th item in Linker_Options and Notes for sort calls
+      Xref_Section.Init;
+
+      --  Add dummy zeroth item in Linker_Options and Notes for sort calls
 
       Linker_Options.Increment_Last;
       Notes.Increment_Last;
@@ -125,6 +673,215 @@
       Zero_Cost_Exceptions_Specified         := False;
    end Initialize_ALI;
 
+   ---------------------------------------
+   -- Invocation_Construct_Kind_To_Code --
+   ---------------------------------------
+
+   function Invocation_Construct_Kind_To_Code
+     (Kind : Invocation_Construct_Kind) return Character
+   is
+   begin
+      return Invocation_Construct_Codes (Kind);
+   end Invocation_Construct_Kind_To_Code;
+
+   -------------------------------
+   -- Invocation_Graph_Encoding --
+   -------------------------------
+
+   function Invocation_Graph_Encoding return Invocation_Graph_Encoding_Kind is
+   begin
+      return Compile_Time_Invocation_Graph_Encoding;
+   end Invocation_Graph_Encoding;
+
+   --------------------------------------------
+   -- Invocation_Graph_Encoding_Kind_To_Code --
+   --------------------------------------------
+
+   function Invocation_Graph_Encoding_Kind_To_Code
+     (Kind : Invocation_Graph_Encoding_Kind) return Character
+   is
+   begin
+      return Invocation_Graph_Encoding_Codes (Kind);
+   end Invocation_Graph_Encoding_Kind_To_Code;
+
+   ----------------------------------------
+   -- Invocation_Graph_Line_Kind_To_Code --
+   ----------------------------------------
+
+   function Invocation_Graph_Line_Kind_To_Code
+     (Kind : Invocation_Graph_Line_Kind) return Character
+   is
+   begin
+      return Invocation_Graph_Line_Codes (Kind);
+   end Invocation_Graph_Line_Kind_To_Code;
+
+   -----------------------------
+   -- Invocation_Kind_To_Code --
+   -----------------------------
+
+   function Invocation_Kind_To_Code
+     (Kind : Invocation_Kind) return Character
+   is
+   begin
+      return Invocation_Codes (Kind);
+   end Invocation_Kind_To_Code;
+
+   -----------------------------
+   -- Invocation_Signature_Of --
+   -----------------------------
+
+   function Invocation_Signature_Of
+     (Column    : Nat;
+      Line      : Nat;
+      Locations : Name_Id;
+      Name      : Name_Id;
+      Scope     : Name_Id) return Invocation_Signature_Id
+   is
+      IS_Rec : constant Invocation_Signature_Record :=
+                 (Column    => Column,
+                  Line      => Line,
+                  Locations => Locations,
+                  Name      => Name,
+                  Scope     => Scope);
+      IS_Id  : Invocation_Signature_Id;
+
+   begin
+      IS_Id := Sig_Map.Get (Sig_To_Sig_Map, IS_Rec);
+
+      --  The invocation signature lacks an id. This indicates that it
+      --  is encountered for the first time during the construction of
+      --  the graph.
+
+      if not Present (IS_Id) then
+         Invocation_Signatures.Append (IS_Rec);
+         IS_Id := Invocation_Signatures.Last;
+
+         --  Map the invocation signature record to its corresponding id
+
+         Sig_Map.Put (Sig_To_Sig_Map, IS_Rec, IS_Id);
+      end if;
+
+      return IS_Id;
+   end Invocation_Signature_Of;
+
+   -------------
+   -- Invoker --
+   -------------
+
+   function Invoker
+     (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id
+   is
+   begin
+      pragma Assert (Present (IR_Id));
+      return Invocation_Relations.Table (IR_Id).Invoker;
+   end Invoker;
+
+   ----------
+   -- Kind --
+   ----------
+
+   function Kind
+     (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind
+   is
+   begin
+      pragma Assert (Present (IC_Id));
+      return Invocation_Constructs.Table (IC_Id).Kind;
+   end Kind;
+
+   ----------
+   -- Kind --
+   ----------
+
+   function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind is
+   begin
+      pragma Assert (Present (IR_Id));
+      return Invocation_Relations.Table (IR_Id).Kind;
+   end Kind;
+
+   ----------
+   -- Line --
+   ----------
+
+   function Line (IS_Id : Invocation_Signature_Id) return Nat is
+   begin
+      pragma Assert (Present (IS_Id));
+      return Invocation_Signatures.Table (IS_Id).Line;
+   end Line;
+
+   ---------------
+   -- Locations --
+   ---------------
+
+   function Locations (IS_Id : Invocation_Signature_Id) return Name_Id is
+   begin
+      pragma Assert (Present (IS_Id));
+      return Invocation_Signatures.Table (IS_Id).Locations;
+   end Locations;
+
+   ----------
+   -- Name --
+   ----------
+
+   function Name (IS_Id : Invocation_Signature_Id) return Name_Id is
+   begin
+      pragma Assert (Present (IS_Id));
+      return Invocation_Signatures.Table (IS_Id).Name;
+   end Name;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (IC_Id : Invocation_Construct_Id) return Boolean is
+   begin
+      return IC_Id /= No_Invocation_Construct;
+   end Present;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (IR_Id : Invocation_Relation_Id) return Boolean is
+   begin
+      return IR_Id /= No_Invocation_Relation;
+   end Present;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (IS_Id : Invocation_Signature_Id) return Boolean is
+   begin
+      return IS_Id /= No_Invocation_Signature;
+   end Present;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (Dep : Sdep_Id) return Boolean is
+   begin
+      return Dep /= No_Sdep_Id;
+   end Present;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (U_Id : Unit_Id) return Boolean is
+   begin
+      return U_Id /= No_Unit_Id;
+   end Present;
+
+   -------------
+   -- Present --
+   -------------
+
+   function Present (W_Id : With_Id) return Boolean is
+   begin
+      return W_Id /= No_With_Id;
+   end Present;
+
    --------------
    -- Scan_ALI --
    --------------
@@ -221,7 +978,7 @@
       --
       --    If Ignore_Special is False (normal case), the scan is terminated by
       --    a typeref bracket or an equal sign except for the special case of
-      --    an operator name starting with a double quote which is terminated
+      --    an operator name starting with a double quote that is terminated
       --    by another double quote.
       --
       --    If May_Be_Quoted is True and the first non blank character is '"'
@@ -256,6 +1013,9 @@
          Standard_Entity : out Name_Id);
       --  Parse the definition of a typeref (<...>, {...} or (...))
 
+      procedure Scan_Invocation_Graph_Line;
+      --  Parse a single line that encodes a piece of the invocation graph
+
       procedure Skip_Eol;
       --  Skip past spaces, then skip past end of line (fatal error if not
       --  at end of line). Also skips past any following blank lines.
@@ -771,6 +1531,239 @@
          return T (P);
       end Nextc;
 
+      --------------------------------
+      -- Scan_Invocation_Graph_Line --
+      --------------------------------
+
+      procedure Scan_Invocation_Graph_Line is
+         procedure Scan_Invocation_Construct_Line;
+         pragma Inline (Scan_Invocation_Construct_Line);
+         --  Parse an invocation construct line and construct the corresponding
+         --  construct. The following data structures are updated:
+         --
+         --    * Invocation_Constructs
+         --    * Units
+
+         procedure Scan_Invocation_Graph_Attributes_Line;
+         pragma Inline (Scan_Invocation_Graph_Attributes_Line);
+         --  Parse an invocation-graph attributes line. The following data
+         --  structures are updated:
+         --
+         --    * Units
+
+         procedure Scan_Invocation_Relation_Line;
+         pragma Inline (Scan_Invocation_Relation_Line);
+         --  Parse an invocation relation line and construct the corresponding
+         --  relation. The following data structures are updated:
+         --
+         --    * Invocation_Relations
+         --    * Units
+
+         function Scan_Invocation_Signature return Invocation_Signature_Id;
+         pragma Inline (Scan_Invocation_Signature);
+         --  Parse a single invocation signature while populating the following
+         --  data structures:
+         --
+         --    * Invocation_Signatures
+         --    * Sig_To_Sig_Map
+
+         ------------------------------------
+         -- Scan_Invocation_Construct_Line --
+         ------------------------------------
+
+         procedure Scan_Invocation_Construct_Line is
+            Body_Placement : Declaration_Placement_Kind;
+            Kind           : Invocation_Construct_Kind;
+            Signature      : Invocation_Signature_Id;
+            Spec_Placement : Declaration_Placement_Kind;
+
+         begin
+            --  construct-kind
+
+            Kind := Code_To_Invocation_Construct_Kind (Getc);
+            Checkc (' ');
+            Skip_Space;
+
+            --  construct-spec-placement
+
+            Spec_Placement := Code_To_Declaration_Placement_Kind (Getc);
+            Checkc (' ');
+            Skip_Space;
+
+            --  construct-body-placement
+
+            Body_Placement := Code_To_Declaration_Placement_Kind (Getc);
+            Checkc (' ');
+            Skip_Space;
+
+            --  construct-signature
+
+            Signature := Scan_Invocation_Signature;
+            Skip_Eol;
+
+            Add_Invocation_Construct
+              (Body_Placement => Body_Placement,
+               Kind           => Kind,
+               Signature      => Signature,
+               Spec_Placement => Spec_Placement);
+         end Scan_Invocation_Construct_Line;
+
+         -------------------------------------------
+         -- Scan_Invocation_Graph_Attributes_Line --
+         -------------------------------------------
+
+         procedure Scan_Invocation_Graph_Attributes_Line is
+         begin
+            --  encoding-kind
+
+            Set_Invocation_Graph_Encoding
+              (Code_To_Invocation_Graph_Encoding_Kind (Getc));
+            Skip_Eol;
+         end Scan_Invocation_Graph_Attributes_Line;
+
+         -----------------------------------
+         -- Scan_Invocation_Relation_Line --
+         -----------------------------------
+
+         procedure Scan_Invocation_Relation_Line is
+            Extra   : Name_Id;
+            Invoker : Invocation_Signature_Id;
+            Kind    : Invocation_Kind;
+            Target  : Invocation_Signature_Id;
+
+         begin
+            --  relation-kind
+
+            Kind := Code_To_Invocation_Kind (Getc);
+            Checkc (' ');
+            Skip_Space;
+
+            --  (extra-name | "none")
+
+            Extra := Get_Name;
+
+            if Extra = Name_None then
+               Extra := No_Name;
+            end if;
+
+            Checkc (' ');
+            Skip_Space;
+
+            --  invoker-signature
+
+            Invoker := Scan_Invocation_Signature;
+            Checkc (' ');
+            Skip_Space;
+
+            --  target-signature
+
+            Target := Scan_Invocation_Signature;
+            Skip_Eol;
+
+            Add_Invocation_Relation
+              (Extra   => Extra,
+               Invoker => Invoker,
+               Kind    => Kind,
+               Target  => Target);
+         end Scan_Invocation_Relation_Line;
+
+         -------------------------------
+         -- Scan_Invocation_Signature --
+         -------------------------------
+
+         function Scan_Invocation_Signature return Invocation_Signature_Id is
+            Column    : Nat;
+            Line      : Nat;
+            Locations : Name_Id;
+            Name      : Name_Id;
+            Scope     : Name_Id;
+
+         begin
+            --  [
+
+            Checkc ('[');
+
+            --  name
+
+            Name := Get_Name;
+            Checkc (' ');
+            Skip_Space;
+
+            --  scope
+
+            Scope := Get_Name;
+            Checkc (' ');
+            Skip_Space;
+
+            --  line
+
+            Line := Get_Nat;
+            Checkc (' ');
+            Skip_Space;
+
+            --  column
+
+            Column := Get_Nat;
+            Checkc (' ');
+            Skip_Space;
+
+            --  (locations | "none")
+
+            Locations := Get_Name;
+
+            if Locations = Name_None then
+               Locations := No_Name;
+            end if;
+
+            --  ]
+
+            Checkc (']');
+
+            --  Create an invocation signature from the scanned attributes
+
+            return
+              Invocation_Signature_Of
+                (Column    => Column,
+                 Line      => Line,
+                 Locations => Locations,
+                 Name      => Name,
+                 Scope     => Scope);
+         end Scan_Invocation_Signature;
+
+         --  Local variables
+
+         Line : Invocation_Graph_Line_Kind;
+
+      --  Start of processing for Scan_Invocation_Graph_Line
+
+      begin
+         if Ignore ('G') then
+            return;
+         end if;
+
+         Checkc (' ');
+         Skip_Space;
+
+         --  line-kind
+
+         Line := Code_To_Invocation_Graph_Line_Kind (Getc);
+         Checkc (' ');
+         Skip_Space;
+
+         --  line-attributes
+
+         case Line is
+            when Invocation_Construct_Line =>
+               Scan_Invocation_Construct_Line;
+
+            when Invocation_Graph_Attributes_Line =>
+               Scan_Invocation_Graph_Attributes_Line;
+
+            when Invocation_Relation_Line =>
+               Scan_Invocation_Relation_Line;
+         end case;
+      end Scan_Invocation_Graph_Line;
+
       --------------
       -- Skip_Eol --
       --------------
@@ -880,6 +1873,7 @@
         First_Specific_Dispatching   => Specific_Dispatching.Last + 1,
         First_Unit                   => No_Unit_Id,
         GNATprove_Mode               => False,
+        Invocation_Graph_Encoding    => No_Encoding,
         Last_Interrupt_State         => Interrupt_States.Last,
         Last_Sdep                    => No_Sdep_Id,
         Last_Specific_Dispatching    => Specific_Dispatching.Last,
@@ -1716,38 +2710,42 @@
             UL : Unit_Record renames Units.Table (Units.Last);
 
          begin
-            UL.Uname                    := Get_Unit_Name;
-            UL.Predefined               := Is_Predefined_Unit;
-            UL.Internal                 := Is_Internal_Unit;
-            UL.My_ALI                   := Id;
-            UL.Sfile                    := Get_File_Name (Lower => True);
-            UL.Pure                     := False;
-            UL.Preelab                  := False;
-            UL.No_Elab                  := False;
-            UL.Shared_Passive           := False;
-            UL.RCI                      := False;
-            UL.Remote_Types             := False;
-            UL.Serious_Errors           := False;
-            UL.Has_RACW                 := False;
-            UL.Init_Scalars             := False;
-            UL.Is_Generic               := False;
-            UL.Icasing                  := Mixed_Case;
-            UL.Kcasing                  := All_Lower_Case;
-            UL.Dynamic_Elab             := False;
-            UL.Elaborate_Body           := False;
-            UL.Set_Elab_Entity          := False;
-            UL.Version                  := "00000000";
-            UL.First_With               := Withs.Last + 1;
-            UL.First_Arg                := First_Arg;
-            UL.Elab_Position            := 0;
-            UL.SAL_Interface            := ALIs.Table (Id).SAL_Interface;
-            UL.Directly_Scanned         := Directly_Scanned;
-            UL.Body_Needed_For_SAL      := False;
-            UL.Elaborate_Body_Desirable := False;
-            UL.Optimize_Alignment       := 'O';
-            UL.Has_Finalizer            := False;
-            UL.Primary_Stack_Count      := 0;
-            UL.Sec_Stack_Count          := 0;
+            UL.Uname                      := Get_Unit_Name;
+            UL.Predefined                 := Is_Predefined_Unit;
+            UL.Internal                   := Is_Internal_Unit;
+            UL.My_ALI                     := Id;
+            UL.Sfile                      := Get_File_Name (Lower => True);
+            UL.Pure                       := False;
+            UL.Preelab                    := False;
+            UL.No_Elab                    := False;
+            UL.Shared_Passive             := False;
+            UL.RCI                        := False;
+            UL.Remote_Types               := False;
+            UL.Serious_Errors             := False;
+            UL.Has_RACW                   := False;
+            UL.Init_Scalars               := False;
+            UL.Is_Generic                 := False;
+            UL.Icasing                    := Mixed_Case;
+            UL.Kcasing                    := All_Lower_Case;
+            UL.Dynamic_Elab               := False;
+            UL.Elaborate_Body             := False;
+            UL.Set_Elab_Entity            := False;
+            UL.Version                    := "00000000";
+            UL.First_With                 := Withs.Last + 1;
+            UL.First_Arg                  := First_Arg;
+            UL.First_Invocation_Construct := Invocation_Constructs.Last + 1;
+            UL.Last_Invocation_Construct  := No_Invocation_Construct;
+            UL.First_Invocation_Relation  := Invocation_Relations.Last + 1;
+            UL.Last_Invocation_Relation   := No_Invocation_Relation;
+            UL.Elab_Position              := 0;
+            UL.SAL_Interface              := ALIs.Table (Id).SAL_Interface;
+            UL.Directly_Scanned           := Directly_Scanned;
+            UL.Body_Needed_For_SAL        := False;
+            UL.Elaborate_Body_Desirable   := False;
+            UL.Optimize_Alignment         := 'O';
+            UL.Has_Finalizer              := False;
+            UL.Primary_Stack_Count        := 0;
+            UL.Sec_Stack_Count            := 0;
 
             if Debug_Flag_U then
                Write_Str (" ----> reading unit ");
@@ -2206,9 +3204,6 @@
 
             Linker_Options.Table (Linker_Options.Last).Internal_File :=
               Is_Internal_File_Name (F);
-
-            Linker_Options.Table (Linker_Options.Last).Original_Pos :=
-              Linker_Options.Last;
          end if;
 
          --  If there are notes present, scan them
@@ -2444,6 +3439,17 @@
 
       ALIs.Table (Id).Last_Sdep := Sdep.Last;
 
+      --  Loop through invocation-graph lines
+
+      G_Loop : loop
+         Check_Unknown_Line;
+         exit G_Loop when C /= 'G';
+
+         Scan_Invocation_Graph_Line;
+
+         C := Getc;
+      end loop G_Loop;
+
       --  We must at this stage be at an Xref line or the end of file
 
       if C = EOF then
@@ -2786,7 +3792,6 @@
             --  Record last entity
 
             XS.Last_Entity := Xref_Entity.Last;
-
          end Read_Refs_For_One_File;
 
          C := Getc;
@@ -2806,6 +3811,16 @@
          return No_ALI_Id;
    end Scan_ALI;
 
+   -----------
+   -- Scope --
+   -----------
+
+   function Scope (IS_Id : Invocation_Signature_Id) return Name_Id is
+   begin
+      pragma Assert (Present (IS_Id));
+      return Invocation_Signatures.Table (IS_Id).Scope;
+   end Scope;
+
    ---------
    -- SEq --
    ---------
@@ -2815,6 +3830,31 @@
       return F1.all = F2.all;
    end SEq;
 
+   -----------------------------------
+   -- Set_Invocation_Graph_Encoding --
+   -----------------------------------
+
+   procedure Set_Invocation_Graph_Encoding
+     (Kind         : Invocation_Graph_Encoding_Kind;
+      Update_Units : Boolean := True)
+   is
+   begin
+      Compile_Time_Invocation_Graph_Encoding := Kind;
+
+      --  Update the invocation-graph encoding of the current unit only when
+      --  requested by the caller.
+
+      if Update_Units then
+         declare
+            Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+            Curr_ALI  : ALIs_Record renames ALIs.Table  (Curr_Unit.My_ALI);
+
+         begin
+            Curr_ALI.Invocation_Graph_Encoding := Kind;
+         end;
+      end if;
+   end Set_Invocation_Graph_Encoding;
+
    -----------
    -- SHash --
    -----------
@@ -2831,4 +3871,40 @@
       return Vindex (Vindex'First + Vindex (H mod Vindex'Range_Length));
    end SHash;
 
+   ---------------
+   -- Signature --
+   ---------------
+
+   function Signature
+     (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id
+   is
+   begin
+      pragma Assert (Present (IC_Id));
+      return Invocation_Constructs.Table (IC_Id).Signature;
+   end Signature;
+
+   --------------------
+   -- Spec_Placement --
+   --------------------
+
+   function Spec_Placement
+     (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind
+   is
+   begin
+      pragma Assert (Present (IC_Id));
+      return Invocation_Constructs.Table (IC_Id).Spec_Placement;
+   end Spec_Placement;
+
+   ------------
+   -- Target --
+   ------------
+
+   function Target
+     (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id
+   is
+   begin
+      pragma Assert (Present (IR_Id));
+      return Invocation_Relations.Table (IR_Id).Target;
+   end Target;
+
 end ALI;