This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[debugalicious] verification code


Hi folks.

This patch adds verification and sanity checks to the debuglocus code.

With it we now dump which debuglocus entries were added or deleted in a
given pass, as well as which entries are no longer referenced, or which
entries are erroneously shared.  This all happens with
-fdump-tree-*-debuglocus.  

I have also added -fdump-tree-*-debuglocus-details which dumps the
entire debuglocus bitmap.

Andrew approved this off-list.  Committing to branch.

	* debuglocus.c (debuglocus_bitmap_populate_helper): New.
	(debuglocus_bitmap_populate_gimple): New.
	(debuglocus_bitmap_populate_tree): New.
	(debuglocus_bitmap_populate): New.
	(dump_debuglocus_entry): New.
	(dump_debuglocus_table): New.
	(debuglocus_bitmap_verify): New.
	* debuglocus.h: Fix typo.
	* tree-dump.c (dump_option_value_in): Add TDF_DEBUGLOCUS.
	* tree-pass.h (TDF_DEBUGLOCUS): New.
	* gimple-pretty-print.c (dump_gimple_phi): Only dump debuglocus
	info when TDF_DEBUGLOCUS.
	(dump_gimple_stmt): Same.
	(dump_implicit_edges): Same.
	* Makefile.in (debuglocus.o): Depend on INPUT_H.
	* passes.c (execute_one_pass): Verify debuglocus entries before
	and after pass.

Index: debuglocus.c
===================================================================
--- debuglocus.c	(revision 145125)
+++ debuglocus.c	(working copy)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  
 #include "toplev.h"
 #include "debuglocus.h"
 #include "hashtab.h"
+#include "input.h"
 
 
 /* This file contains data and functions required to implement debuglocus 
@@ -512,5 +513,244 @@ debuglocus_var_iter_next (debuglocus_ite
     return next->decl;
   return NULL;
 }
+
+/* Debuglocus verification routines.  */
 
 
+/* Debuglocus bitmap for entire translation unit.  */
+bitmap_head global_dl_bitmap;
+
+/* Callback WI info for the walkers.  */
+struct dlb_info
+{
+  /* The bitmap.  */
+  bitmap bits;
+  /* DUMPFILE to dump errors out to.  */
+  FILE *dumpfile;
+  /* TRUE if BITS is the bitmap for BEFORE the pass ran.  */
+  bool before_pass_p;
+};
+
+/* If the given LOCUS is a debuglocus, set the corresponding bit in
+   bitmap B.  Complain about shared debuglocus entries.
+
+   DUMPFILE is the dump file to output errors to.
+
+   BEFORE_PASS_P is true if this is the bitmap before the pass ran,
+   or false if the bitmap is for after the pass completed.  */
+static void
+debuglocus_bitmap_populate_helper (bitmap b, location_t locus,
+				   FILE *dumpfile, bool before_pass_p)
+{
+  if (is_debuglocus (locus))
+    {
+      unsigned int i = DEBUGLOCUS_INDEX (locus);
+
+      if (bitmap_bit_p (b, i))
+	fprintf (dumpfile, "Duplicated debuglocus %s this pass: %u\n",
+		 before_pass_p ? "before" : "after", i);
+      else
+	bitmap_set_bit (b, (int) i);
+    }
+}
+
+/* Callback to walk gimple statements.  Populate debuglocus bitmap
+   with each statement's debuglocus.  */
+static tree
+debuglocus_bitmap_populate_gimple (gimple_stmt_iterator *gsi,
+				   bool *handled_ops ATTRIBUTE_UNUSED,
+				   struct walk_stmt_info *wi)
+{
+  gimple stmt = gsi_stmt (*gsi);
+  struct dlb_info *dlb = (struct dlb_info *)wi->info;
+
+  debuglocus_bitmap_populate_helper (dlb->bits, gimple_location (stmt),
+				     dlb->dumpfile, dlb->before_pass_p);
+  return NULL_TREE;
+}
+
+/* Same, but for gimple operands (trees).  */
+static tree
+debuglocus_bitmap_populate_tree (tree *tp,
+				 int *walk_subtrees ATTRIBUTE_UNUSED,
+				 void *data)
+{
+  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+  struct dlb_info *dlb = (struct dlb_info *)wi->info;
+
+  if (CAN_HAVE_LOCATION_P (*tp))
+    debuglocus_bitmap_populate_helper (dlb->bits, EXPR_LOCATION (*tp),
+				       dlb->dumpfile, dlb->before_pass_p);
+  return NULL_TREE;
+}
+
+/* Initialize and populate a bitmap of debuglocus entries.
+   B is the bitmap to populate.
+   DUMPFILE is the file to dump errors out to.
+   BEFORE_PASS_P is true if this is the bitmap for before the pass ran.  */
+void
+debuglocus_bitmap_populate (bitmap b, FILE *dumpfile, bool before_pass_p)
+{
+  debuglocus_table_t *tab = current_debuglocus_table ();
+  tree func;
+  struct walk_stmt_info wi;
+  struct dlb_info dlb;
+
+  bitmap_initialize (b, NULL);
+
+  if (!tab || !cfun)
+    return;
+
+  func = cfun->decl;
+
+  dlb.bits = b;
+  dlb.dumpfile = dumpfile;
+  dlb.before_pass_p = before_pass_p;
+  memset (&wi, 0, sizeof (wi));
+  wi.info = (void *)&dlb;
+
+  /* If we haven't lowered to gimple, ignore this pass.  */
+  if (DECL_SAVED_TREE (func) != NULL)
+    return;
+
+  if (bitmap_empty_p (&global_dl_bitmap))
+    bitmap_initialize (&global_dl_bitmap, NULL);
+
+  /* If the CFG has been built, traverse the CFG.  */
+  if (cfun->cfg && basic_block_info)
+    {
+      basic_block bb;
+      gimple_stmt_iterator gsi;
+
+      FOR_EACH_BB (bb)
+	for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	  {
+	    walk_gimple_stmt (&gsi,
+			      debuglocus_bitmap_populate_gimple,
+			      debuglocus_bitmap_populate_tree,
+			      &wi);
+	  }
+    }
+  else
+    {
+      /* Otherwise, plain gimple.  Traverse the sequence of
+	 statements.  */
+      walk_gimple_seq (gimple_body (func),
+		       debuglocus_bitmap_populate_gimple,
+		       debuglocus_bitmap_populate_tree,
+		       &wi);
+    }
+
+  /* If the pass has already run, update the global debugloc
+     bitmap.  */
+  if (before_pass_p == false)
+    bitmap_ior_into (&global_dl_bitmap, b);
+}
+
+/* Dump the contents of debuglocus entry DL.
+   F is the dumpfile.  DL is the debuglocus entry.
+   INDEX is the debuglocus index for the entry.  */
+static void
+dump_debuglocus_entry (FILE *f, debuglocus_p dl, unsigned int index)
+{
+  expanded_location xloc = expand_location (dl->locus);
+
+  fprintf (f, "index #%u\n", index);
+  fputs   ("decl  = [", f);
+  print_generic_decl (f, dl->decl, /*flags=*/0);
+  fputs ("]\n", f);
+  fprintf (f, "order = %d\n", dl->order);
+  fprintf (f, "locus = %u {file='%s', line=%d, col=%d}\n",
+	   (unsigned int) dl->locus, xloc.file, xloc.line, xloc.column);
+  fprintf (f, "prev  = %d\n", dl->prev);
+  fprintf (f, "next  = %d\n", dl->next);
+}
+
+/* Dump the entire contents of the debuglocus table.
+   F is the dumpfile.  TAB is the table.  */
+static void
+dump_debuglocus_table (FILE *f, debuglocus_table_t *tab)
+{
+  unsigned int i;
+  debuglocus_p d;
+
+  if (!tab || tab->size <= 1)
+    return;
+
+  fputs ("\ndebuglocus table contents after pass executed\n", f);
+  fputs ("-----------------------------------------------\n", f);
+  fprintf (f, "number of elements=%d\n", tab->size);
+  for (i = 1; i < tab->size; ++i)
+    {
+      d = get_debuglocus_entry (tab, i);
+      dump_debuglocus_entry (f, d, i);
+    }
+  fputs ("-------------------------\n", f);
+}
+
+/* Verify the debuglocus entries created by the current pass.
+
+   BEFORE is the debuglocus bitmap before the pass.  AFTER is the
+   debuglocus bitmap after the pass.  F is the dumpfile to dump the
+   verification information.  FLAGS is are the TDF dump flags from the
+   pass.  */
+void
+debuglocus_bitmap_verify (FILE *f, bitmap before, bitmap after,
+			  unsigned int flags)
+{
+  const char *comma;
+  unsigned i;
+  bitmap_iterator bi;
+  bool first = true;
+  debuglocus_table_t *tab = current_debuglocus_table ();
+
+  if (tab && flags & TDF_DETAILS)
+    dump_debuglocus_table (f, tab);
+
+  /* Dump new debuglocus entries generated in this pass.  */
+  comma = "";
+  EXECUTE_IF_SET_IN_BITMAP (after, 0, i, bi)
+    {
+      if (!bitmap_bit_p (before, i))
+	{
+	  if (first)
+	    {
+	      fputs ("new debuglocus entries in this pass\n", f);
+	      first = false;
+	    }
+	  fprintf (f, "%s%u", comma, i);
+	  comma = ", ";
+	}
+    }
+  if (!first)
+    fputc ('\n', f);
+
+  /* Dump debuglocus entries that went missing in this pass.  */
+  first  = true;
+  comma = "";
+  EXECUTE_IF_SET_IN_BITMAP (before, 0, i, bi)
+    {
+      if (!bitmap_bit_p (after, i))
+	{
+	  if (first)
+	    {
+	      fputs ("deleted debuglocus entries in this pass:\n", f);
+	      first = false;
+	    }
+	  fprintf (f, "%s%u", comma, i);
+	  comma = ", ";
+	}
+    }
+  if (!first)
+    fputc ('\n', f);
+
+
+  if (tab)
+    {
+      /* Dump debuglocus entries that are no longer referenced after this
+	 pass.  */
+      for (i = 1; i < tab->size; ++i)
+	if (!bitmap_bit_p (&global_dl_bitmap, i))
+	  fprintf (f, "debuglocus: orphaned debuglocus entry: %u\n", i);
+    }
+}
Index: debuglocus.h
===================================================================
--- debuglocus.h	(revision 145125)
+++ debuglocus.h	(working copy)
@@ -64,9 +64,12 @@ void merge_debuglocus (debuglocus_p, deb
 debuglocus_p find_debuglocus (gimple, tree, source_location);
 debuglocus_p find_and_detach_debuglocus (gimple, tree, source_location);
 source_location find_and_detach_or_create_debuglocus (gimple, tree, source_location);
+bitmap current_debuglocus_bitmap (void);
+void debuglocus_bitmap_populate (bitmap, FILE *, bool);
+void debuglocus_bitmap_verify (FILE *, bitmap, bitmap, unsigned int);
 
 /* Iterate over the different debuglocus's in a single list. No iterations are 
-   performed if ther locus is just a regular source location.  
+   performed if their locus is just a regular source location.  
 
    usage:
    source_location locus = gimple_location (stmt);
Index: tree-dump.c
===================================================================
--- tree-dump.c	(revision 145125)
+++ tree-dump.c	(working copy)
@@ -815,13 +815,14 @@ static const struct dump_option_value_in
   {"blocks", TDF_BLOCKS},
   {"vops", TDF_VOPS},
   {"lineno", TDF_LINENO},
+  {"debuglocus", TDF_DEBUGLOCUS},
   {"uid", TDF_UID},
   {"stmtaddr", TDF_STMTADDR},
   {"memsyms", TDF_MEMSYMS},
   {"verbose", TDF_VERBOSE},
   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 
 	    | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
-	    | TDF_RHS_ONLY)},
+	    | TDF_RHS_ONLY | TDF_DEBUGLOCUS)},
   {NULL, 0}
 };
 
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 145125)
+++ tree-pass.h	(working copy)
@@ -75,6 +75,7 @@ enum tree_dump_index
 					   dumper to print stmts.  */
 #define TDF_RHS_ONLY	(1 << 17)	/* a flag to only print the RHS of
 					   a gimple stmt.  */
+#define TDF_DEBUGLOCUS	(1 << 18)	/* dump debuglocus information */
 
 extern char *get_dump_file_name (enum tree_dump_index);
 extern int dump_enabled_p (enum tree_dump_index);
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 145125)
+++ gimple-pretty-print.c	(working copy)
@@ -1183,7 +1183,9 @@ dump_gimple_phi (pretty_printer *buffer,
       pp_character (buffer, '(');
       pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
       pp_character (buffer, ')');
-      if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
+      if (((flags & TDF_LINENO)
+	   || (flags & TDF_DEBUGLOCUS))
+	  && gimple_phi_arg_has_location (phi, i))
         {
 	  expanded_location xloc;
 
@@ -1195,7 +1197,7 @@ dump_gimple_phi (pretty_printer *buffer,
 	      pp_string (buffer, " : ");
 	    }
 	  pp_decimal_int (buffer, xloc.line);
-	  if (xloc.debuglocus != DEBUGLOCUS_NONE)
+	  if ((flags & TDF_DEBUGLOCUS) && xloc.debuglocus != DEBUGLOCUS_NONE)
 	    {
 	      tree decl;
 	      debuglocus_iterator iter;
@@ -1497,7 +1499,9 @@ dump_gimple_stmt (pretty_printer *buffer
   if (flags & TDF_STMTADDR)
     pp_printf (buffer, "<&%p> ", (void *) gs);
 
-  if ((flags & TDF_LINENO) && gimple_has_location (gs))
+  if (((flags & TDF_LINENO)
+       || (flags & TDF_DEBUGLOCUS))
+      && gimple_has_location (gs))
     {
       expanded_location xloc = expand_location (gimple_location (gs));
       pp_character (buffer, '[');
@@ -1507,7 +1511,7 @@ dump_gimple_stmt (pretty_printer *buffer
 	  pp_string (buffer, " : ");
 	}
       pp_decimal_int (buffer, xloc.line);
-      if (xloc.debuglocus != DEBUGLOCUS_NONE)
+      if ((flags & TDF_DEBUGLOCUS) && xloc.debuglocus != DEBUGLOCUS_NONE)
 	{
 	  tree decl;
 	  debuglocus_iterator iter;
@@ -1854,7 +1858,7 @@ dump_implicit_edges (pretty_printer *buf
     {
       INDENT (indent);
 
-      if ((flags & TDF_LINENO)
+      if (((flags & TDF_LINENO) || (flags & TDF_DEBUGLOCUS))
 	  && e->goto_locus != UNKNOWN_LOCATION
 	  )
 	{
@@ -1867,7 +1871,8 @@ dump_implicit_edges (pretty_printer *buf
 	      pp_string (buffer, " : ");
 	    }
 	  pp_decimal_int (buffer, goto_xloc.line);
-	  if (goto_xloc.debuglocus != DEBUGLOCUS_NONE)
+	  if ((flags & TDF_DEBUGLOCUS)
+	      && goto_xloc.debuglocus != DEBUGLOCUS_NONE)
 	    {
 	      tree decl;
 	      debuglocus_iterator iter;
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 145125)
+++ Makefile.in	(working copy)
@@ -2544,7 +2544,7 @@ dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM
    $(TOPLEV_H) $(GGC_H) $(OBSTACK_H) $(EXPR_H) gt-dbxout.h
 debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
 debuglocus.o : debuglocus.c debuglocus.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TM_H)
+   $(TM_H) $(INPUT_H)
 sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) debug.h \
    $(TREE_H) $(GGC_H) $(RTL_H) $(REGS_H) $(FLAGS_H) insn-config.h \
    output.h $(TOPLEV_H) $(TM_P_H) gsyms.h langhooks.h $(TARGET_H) sdbout.h \
Index: passes.c
===================================================================
--- passes.c	(revision 145125)
+++ passes.c	(working copy)
@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-dump.h"
 #include "df.h"
 #include "predict.h"
+#include "debuglocus.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -1218,6 +1219,7 @@ execute_one_pass (struct opt_pass *pass)
 {
   bool initializing_dump;
   unsigned int todo_after = 0;
+  bitmap_head debuglocus_before, debuglocus_after;
 
   /* IPA passes are executed on whole program, so cfun should be NULL.
      Other passes need function context set.  */
@@ -1267,6 +1269,12 @@ execute_one_pass (struct opt_pass *pass)
 
   initializing_dump = pass_init_dump_file (pass);
 
+  if ((dump_flags & TDF_DEBUGLOCUS)
+      && (pass->todo_flags_finish & TODO_dump_func)
+      && dump_file)
+    debuglocus_bitmap_populate (&debuglocus_before, dump_file,
+				/*before_pass_p=*/true);
+
   /* If a timevar is present, start it.  */
   if (pass->tv_id)
     timevar_push (pass->tv_id);
@@ -1282,6 +1290,18 @@ execute_one_pass (struct opt_pass *pass)
   if (pass->tv_id)
     timevar_pop (pass->tv_id);
 
+  if ((dump_flags & TDF_DEBUGLOCUS)
+      && (pass->todo_flags_finish & TODO_dump_func)
+      && dump_file)
+    {
+      debuglocus_bitmap_populate (&debuglocus_after, dump_file,
+				  /*before_pass_p=*/false);
+
+      debuglocus_bitmap_verify (dump_file,
+				&debuglocus_before, &debuglocus_after,
+				dump_flags);
+    }
+
   do_per_function (update_properties_after_pass, pass);
 
   if (initializing_dump


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]