Introduce instance discriminators
authorAlexandre Oliva <oliva@adacore.com>
Tue, 31 Jul 2018 21:19:13 +0000 (21:19 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Tue, 31 Jul 2018 21:19:13 +0000 (21:19 +0000)
With -gnateS, the Ada compiler sets itself up to output discriminators
for different instantiations of generics, but the middle and back ends
have lacked support for that.  This patch introduces the missing bits,
translating the GNAT-internal representation of the per-file instance
map to an instance_table that maps decls to instance discriminators.

From: Alexandre Oliva  <oliva@adacore.com>, Olivier Hainque  <hainque@adacore.com>
for  gcc/ChangeLog

* debug.h (decl_to_instance_map_t): New type.
(decl_to_instance_map): Declare.
(maybe_create_decl_to_instance_map): New inline function.
     * final.c (bb_discriminator, last_bb_discriminator): New statics,
     to track basic block discriminators.
     (final_start_function_1): Initialize them.
     (final_scan_insn_1): On NOTE_INSN_BASIC_BLOCK, track
bb_discriminator.
(decl_to_instance_map): New variable.
(map_decl_to_instance, maybe_set_discriminator): New functions.
     (notice_source_line): Set discriminator.

for  gcc/ada/ChangeLog

* trans.c: Include debug.h.
(file_map): New static variable.
(gigi): Set it.  Create decl_to_instance_map when needed.
(Subprogram_Body_to_gnu): Pass gnu_subprog_decl to...
(Sloc_to_locus): ... this.  Add decl parm, map it to instance.
* gigi.h (Sloc_to_locus): Adjust declaration.

for  gcc/testsuite/ChangeLog

* gnat.dg/dinst.adb: New.
* gnat.dg/dinst_pkg.ads, gnat.dg/dinst_pkg.adb: New.

Co-Authored-By: Olivier Hainque <hainque@adacore.com>
From-SVN: r263182

gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/gigi.h
gcc/ada/gcc-interface/trans.c
gcc/debug.h
gcc/final.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/dinst.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/dinst_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/dinst_pkg.ads [new file with mode: 0644]

index 4d0efad289ddbf3de214cf57103cb6447c44a786..4eda71bca0faa484ebcc8fa197989adaabe86332 100644 (file)
@@ -1,3 +1,18 @@
+2018-07-31  Alexandre Oliva  <oliva@adacore.com>
+            Olivier Hainque  <hainque@adacore.com>
+
+       * debug.h (decl_to_instance_map_t): New type.
+       (decl_to_instance_map): Declare.
+       (maybe_create_decl_to_instance_map): New inline function.
+       * final.c (bb_discriminator, last_bb_discriminator): New statics,
+       to track basic block discriminators.
+       (final_start_function_1): Initialize them.
+       (final_scan_insn_1): On NOTE_INSN_BASIC_BLOCK, track
+       bb_discriminator.
+       (decl_to_instance_map): New variable.
+       (map_decl_to_instance, maybe_set_discriminator): New functions.
+       (notice_source_line): Set discriminator.
+
 2018-07-31  Ian Lance Taylor  <iant@golang.org>
 
        * targhooks.c (default_have_speculation_safe_value): Add
index c6f1911684de1ad0bd37ffbca5e94fb541f098aa..8b1de0c95539f5846a9dc6f3eda104880ac6430a 100644 (file)
@@ -1,3 +1,13 @@
+2018-07-31  Alexandre Oliva  <oliva@adacore.com>
+            Olivier Hainque  <hainque@adacore.com>
+
+       * trans.c: Include debug.h.
+       (file_map): New static variable.
+       (gigi): Set it.  Create decl_to_instance_map when needed.
+       (Subprogram_Body_to_gnu): Pass gnu_subprog_decl to...
+       (Sloc_to_locus): ... this.  Add decl parm, map it to instance.
+       * gigi.h (Sloc_to_locus): Adjust declaration.
+
 2018-07-31  Arnaud Charlet  <charlet@adacore.com>
 
        * clean.adb, gnatchop.adb, gnatfind.adb, gnatls.adb,
index a75cb90944919e1f962834b2e143eba0b05f326f..b890195cefc3ae031772b9524b02ec3bd06e2d1a 100644 (file)
@@ -285,7 +285,7 @@ extern void process_type (Entity_Id gnat_entity);
    location and false if it doesn't.  If CLEAR_COLUMN is true, set the column
    information to 0.  */
 extern bool Sloc_to_locus (Source_Ptr Sloc, location_t *locus,
-                          bool clear_column = false);
+                          bool clear_column = false, const_tree decl = 0);
 
 /* Post an error message.  MSG is the error message, properly annotated.
    NODE is the node at which to post the error and the node to use for the
index 31e098a0c707a60e8b244dbc8cc295dd27ff4657..0371d00fce18910acd8e3f4a09c997d9a3b9bcca 100644 (file)
@@ -41,6 +41,7 @@
 #include "stmt.h"
 #include "varasm.h"
 #include "output.h"
+#include "debug.h"
 #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
 #include "tree-iterator.h"
 #include "gimplify.h"
@@ -255,6 +256,12 @@ static tree create_init_temporary (const char *, tree, tree *, Node_Id);
 static const char *extract_encoding (const char *) ATTRIBUTE_UNUSED;
 static const char *decode_name (const char *) ATTRIBUTE_UNUSED;
 \f
+/* This makes gigi's file_info_ptr visible in this translation unit,
+   so that Sloc_to_locus can look it up when deciding whether to map
+   decls to instances.  */
+
+static struct File_Info_Type *file_map;
+
 /* This is the main program of the back-end.  It sets up all the table
    structures and then generates code.  */
 
@@ -300,6 +307,12 @@ gigi (Node_Id gnat_root,
 
   type_annotate_only = (gigi_operating_mode == 1);
 
+  if (Generate_SCO_Instance_Table != 0)
+    {
+      file_map = file_info_ptr;
+      maybe_create_decl_to_instance_map (number_file);
+    }
+
   for (i = 0; i < number_file; i++)
     {
       /* Use the identifier table to make a permanent copy of the filename as
@@ -701,6 +714,7 @@ gigi (Node_Id gnat_root,
     }
 
   /* Destroy ourselves.  */
+  file_map = NULL;
   destroy_gnat_decl ();
   destroy_gnat_utils ();
 
@@ -3771,7 +3785,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
     }
 
   /* Set the line number in the decl to correspond to that of the body.  */
-  if (!Sloc_to_locus (Sloc (gnat_node), &locus))
+  if (!Sloc_to_locus (Sloc (gnat_node), &locus, false, gnu_subprog_decl))
     locus = input_location;
   DECL_SOURCE_LOCATION (gnu_subprog_decl) = locus;
 
@@ -9970,12 +9984,14 @@ maybe_implicit_deref (tree exp)
   return exp;
 }
 \f
-/* Convert SLOC into LOCUS.  Return true if SLOC corresponds to a source code
-   location and false if it doesn't.  If CLEAR_COLUMN is true, set the column
-   information to 0.  */
+/* Convert SLOC into LOCUS.  Return true if SLOC corresponds to a
+   source code location and false if it doesn't.  If CLEAR_COLUMN is
+   true, set the column information to 0.  If DECL is given and SLOC
+   refers to a File with an instance, map DECL to that instance.  */
 
 bool
-Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
+Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column,
+              const_tree decl)
 {
   if (Sloc == No_Location)
     return false;
@@ -9999,6 +10015,9 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
   *locus
     = linemap_position_for_line_and_column (line_table, map, line, column);
 
+  if (file_map && file_map[file - 1].Instance)
+    decl_to_instance_map->put (decl, file_map[file - 1].Instance);
+
   return true;
 }
 
index 126e56e8c8d704540eedcded2026633cc8350658..3f78d06022527e328f374003e86dedab5113f1ae 100644 (file)
@@ -256,4 +256,19 @@ extern bool dwarf2out_default_as_locview_support (void);
 extern const struct gcc_debug_hooks *
 dump_go_spec_init (const char *, const struct gcc_debug_hooks *);
 
+/* Instance discriminator mapping table.  See final.c.  */
+typedef hash_map<const_tree, int> decl_to_instance_map_t;
+extern decl_to_instance_map_t *decl_to_instance_map;
+
+/* Allocate decl_to_instance_map with COUNT slots to begin wtih, if it
+ * hasn't been allocated yet.  */
+
+static inline decl_to_instance_map_t *
+maybe_create_decl_to_instance_map (int count = 13)
+{
+  if (!decl_to_instance_map)
+    decl_to_instance_map = new decl_to_instance_map_t (count);
+  return decl_to_instance_map;
+}
+
 #endif /* !GCC_DEBUG_H  */
index 6fa4acdaa2e950cfb26a50c8475378f3ab16e4ff..a8338e0394c1d62aa01a414da22aabbee48d3242 100644 (file)
@@ -122,12 +122,20 @@ static int last_linenum;
 /* Column number of last NOTE.  */
 static int last_columnnum;
 
-/* Last discriminator written to assembly.  */
+/* Discriminator written to assembly.  */
 static int last_discriminator;
 
-/* Discriminator of current block.  */
+/* Discriminator to be written to assembly for current instruction.
+   Note: actual usage depends on loc_discriminator_kind setting.  */
 static int discriminator;
 
+/* Discriminator identifying current basic block among others sharing
+   the same locus.  */
+static int bb_discriminator;
+
+/* Basic block discriminator for previous instruction.  */
+static int last_bb_discriminator;
+
 /* Highest line number in current block.  */
 static int high_block_linenum;
 
@@ -1701,6 +1709,7 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
   last_linenum = LOCATION_LINE (prologue_location);
   last_columnnum = LOCATION_COLUMN (prologue_location);
   last_discriminator = discriminator = 0;
+  last_bb_discriminator = bb_discriminator = 0;
 
   high_block_linenum = high_function_linenum = last_linenum;
 
@@ -2236,8 +2245,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          if (targetm.asm_out.unwind_emit)
            targetm.asm_out.unwind_emit (asm_out_file, insn);
 
-          discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
-
+         bb_discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
          break;
 
        case NOTE_INSN_EH_REGION_BEG:
@@ -3144,6 +3152,58 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
 }
 
 \f
+
+/* Map DECLs to instance discriminators.  This is allocated and
+   defined in ada/gcc-interfaces/trans.c, when compiling with -gnateS.  */
+
+decl_to_instance_map_t *decl_to_instance_map;
+
+/* Return the instance number assigned to DECL.  */
+
+static inline int
+map_decl_to_instance (const_tree decl)
+{
+  int *inst;
+
+  if (!decl_to_instance_map || !decl || !DECL_P (decl))
+    return 0;
+
+  inst = decl_to_instance_map->get (decl);
+
+  if (!inst)
+    return 0;
+
+  return *inst;
+}
+
+/* Set DISCRIMINATOR to the appropriate value, possibly derived from LOC.  */
+
+static inline void
+maybe_set_discriminator (location_t loc)
+{
+  if (!decl_to_instance_map)
+    discriminator = bb_discriminator;
+  else
+    {
+      tree block = LOCATION_BLOCK (loc);
+
+      while (block && TREE_CODE (block) == BLOCK
+            && !inlined_function_outer_scope_p (block))
+       block = BLOCK_SUPERCONTEXT (block);
+
+      tree decl;
+
+      if (!block)
+       decl = current_function_decl;
+      else if (DECL_P (block))
+       decl = block;
+      else
+       decl = block_ultimate_origin (block);
+
+      discriminator = map_decl_to_instance (decl);
+    }
+}
+
 /* Return whether a source line note needs to be emitted before INSN.
    Sets IS_STMT to TRUE if the line should be marked as a possible
    breakpoint location.  */
@@ -3178,6 +3238,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
       filename = xloc.file;
       linenum = xloc.line;
       columnnum = xloc.column;
+      maybe_set_discriminator (loc);
       force_source_line = true;
     }
   else if (override_filename)
@@ -3192,6 +3253,7 @@ notice_source_line (rtx_insn *insn, bool *is_stmt)
       filename = xloc.file;
       linenum = xloc.line;
       columnnum = xloc.column;
+      maybe_set_discriminator (INSN_LOCATION (insn));
     }
   else
     {
index b764a6504a5fb61b4377949dc98b210b3049edc3..d6e0a62f5fedc7bb45d1048c3ddd0a651f28a789 100644 (file)
@@ -1,3 +1,9 @@
+2018-07-31  Alexandre Oliva  <oliva@adacore.com>
+            Olivier Hainque  <hainque@adacore.com>
+
+       * gnat.dg/dinst.adb: New.
+       * gnat.dg/dinst_pkg.ads, gnat.dg/dinst_pkg.adb: New.
+
 2018-07-31  David Malcolm  <dmalcolm@redhat.com>
 
        * gcc.dg/format/gcc_diag-1.c (foo): Update the %v tests for
diff --git a/gcc/testsuite/gnat.dg/dinst.adb b/gcc/testsuite/gnat.dg/dinst.adb
new file mode 100644 (file)
index 0000000..460e6c5
--- /dev/null
@@ -0,0 +1,20 @@
+-- { dg-do compile { target *-*-gnu* } }
+-- { dg-options "-gnateS -gdwarf -g -O -gno-column-info" }
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 1\n" } } */
+-- { dg-final { scan-assembler-not "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 2\n" } } */
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 3\n" } } */
+-- { dg-final { scan-assembler "loc \[0-9] 5 \[0-9]( is_stmt \[0-9])? discriminator 4\n" } } */
+
+
+with DInst_Pkg;
+procedure DInst is
+   package I1 is new DInst_Pkg; -- instance 1 
+   package I2 is new DInst_Pkg; -- instance 2
+   package I3 is new DInst_Pkg; -- instance 3
+   package I4 is new DInst_Pkg; -- instance 4
+begin
+   I1.Foo;
+   -- I2.Foo;
+   I3.Foo;
+   I4.Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/dinst_pkg.adb b/gcc/testsuite/gnat.dg/dinst_pkg.adb
new file mode 100644 (file)
index 0000000..09a9bae
--- /dev/null
@@ -0,0 +1,7 @@
+with Ada.Text_IO; use Ada.Text_IO;
+package body DInst_Pkg is
+   procedure Foo is
+   begin
+      Put_Line ("hello there");
+   end;
+end;
diff --git a/gcc/testsuite/gnat.dg/dinst_pkg.ads b/gcc/testsuite/gnat.dg/dinst_pkg.ads
new file mode 100644 (file)
index 0000000..d22afdb
--- /dev/null
@@ -0,0 +1,4 @@
+generic
+package DInst_Pkg is
+   procedure Foo;
+end;