diff mbox

Symbol table 9/many: symtab verifier

Message ID 20120418172227.GA28335@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka April 18, 2012, 5:22 p.m. UTC
Hi,
this patch introduce symbol table verificatoin facility. In addition to what
can be broken out of cgraph verifier, the assembler hash consistency is
checked.  The patch also fixes one latent LTO bug caught by the verifier where
we did not dissolve varpool same comdat group lists when bringing variables
static.

Bootstrapped/regtested x86_64-linux. Will commit it shortly.
Honza

	* cgraph.h (verify_symtab, verify_symtab_node, verify_symtab_base):
	Declare.
	* cgraphunit.c (verify_cgraph_node): Verify symtab base; do not verify 
	cgraph hash and same comdat groups.
	(cgraph_optimize); Verify symbol table.
	* ipa.c (cgraph_remove_unreachable_nodes): Verify symbol table.
	(dissolve_same_comdat_group_list): Work on symtab nodes.
	(function_and_variable_visibility): Dissolve variable same comdat group
	lists, too.
	* symtab.c: Include timevar.h
	(verify_symtab_base, verify_symtab_node, verify_symtab): New functions.
diff mbox

Patch

Index: cgraph.h
===================================================================
--- cgraph.h	(revision 186564)
+++ cgraph.h	(working copy)
@@ -512,6 +512,9 @@  void debug_symtab (void);
 void dump_symtab_node (FILE *, symtab_node);
 void debug_symtab_node (symtab_node);
 void dump_symtab_base (FILE *, symtab_node);
+void verify_symtab (void);
+void verify_symtab_node (symtab_node);
+bool verify_symtab_base (symtab_node);
 
 /* In cgraph.c  */
 void dump_cgraph (FILE *);
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 186564)
+++ cgraphunit.c	(working copy)
@@ -577,6 +577,7 @@  verify_cgraph_node (struct cgraph_node *
     return;
 
   timevar_push (TV_CGRAPH_VERIFY);
+  error_found |= verify_symtab_base ((symtab_node) node);
   for (e = node->callees; e; e = e->next_callee)
     if (e->aux)
       {
@@ -663,12 +664,6 @@  verify_cgraph_node (struct cgraph_node *
       error_found = true;
     }
 
-  if (!cgraph_get_node (node->symbol.decl))
-    {
-      error ("node not found in cgraph_hash");
-      error_found = true;
-    }
-
   if (node->clone_of)
     {
       struct cgraph_node *n;
@@ -708,32 +703,6 @@  verify_cgraph_node (struct cgraph_node *
       error ("double linked list of clones corrupted");
       error_found = true;
     }
-  if (node->symbol.same_comdat_group)
-    {
-      symtab_node n = node->symbol.same_comdat_group;
-
-      if (!DECL_ONE_ONLY (n->symbol.decl))
-	{
-	  error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
-	  error_found = true;
-	}
-      if (n == (symtab_node)node)
-	{
-	  error ("node is alone in a comdat group");
-	  error_found = true;
-	}
-      do
-	{
-	  if (!n->symbol.same_comdat_group)
-	    {
-	      error ("same_comdat_group is not a circular list");
-	      error_found = true;
-	      break;
-	    }
-	  n = n->symbol.same_comdat_group;
-	}
-      while (n != (symtab_node)node);
-    }
 
   if (node->analyzed && node->alias)
     {
@@ -2654,7 +2623,7 @@  cgraph_optimize (void)
     return;
 
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
 #endif
 
   /* Frontend may output common variables after the unit has been finalized.
@@ -2704,7 +2673,7 @@  cgraph_optimize (void)
   if (!quiet_flag)
     fprintf (stderr, "Assembling functions:\n");
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
 #endif
 
   cgraph_materialize_all_clones ();
@@ -2712,7 +2681,7 @@  cgraph_optimize (void)
   execute_ipa_pass_list (all_late_ipa_passes);
   cgraph_remove_unreachable_nodes (true, dump_file);
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
 #endif
   bitmap_obstack_release (NULL);
   cgraph_mark_functions_to_output ();
@@ -2740,7 +2709,7 @@  cgraph_optimize (void)
       dump_symtab (cgraph_dump_file);
     }
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
   /* Double check that all inline clones are gone and that all
      function bodies have been released from memory.  */
   if (!seen_error ())
Index: ipa.c
===================================================================
--- ipa.c	(revision 186564)
+++ ipa.c	(working copy)
@@ -176,7 +176,7 @@  cgraph_remove_unreachable_nodes (bool be
   bool changed = false;
 
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
 #endif
   if (file)
     fprintf (file, "\nReclaiming functions:");
@@ -467,7 +467,7 @@  cgraph_remove_unreachable_nodes (bool be
     return changed;
 
 #ifdef ENABLE_CHECKING
-  verify_cgraph ();
+  verify_symtab ();
 #endif
 
   /* Reclaim alias pairs for functions that have disappeared from the
@@ -730,12 +730,12 @@  varpool_externally_visible_p (struct var
 /* Dissolve the same_comdat_group list in which NODE resides.  */
 
 static void
-dissolve_same_comdat_group_list (struct cgraph_node *node)
+dissolve_same_comdat_group_list (symtab_node node)
 {
-  struct cgraph_node *n = node, *next;
+  symtab_node n = node, next;
   do
     {
-      next = cgraph (n->symbol.same_comdat_group);
+      next = n->symbol.same_comdat_group;
       n->symbol.same_comdat_group = NULL;
       n = next;
     }
@@ -838,7 +838,7 @@  function_and_variable_visibility (bool w
 		 all of them have to be, otherwise it is a front-end bug.  */
 	      gcc_assert (DECL_EXTERNAL (n->symbol.decl));
 #endif
-	  dissolve_same_comdat_group_list (node);
+	  dissolve_same_comdat_group_list ((symtab_node) node);
 	}
       gcc_assert ((!DECL_WEAK (node->symbol.decl)
 		  && !DECL_COMDAT (node->symbol.decl))
@@ -865,7 +865,7 @@  function_and_variable_visibility (bool w
 	       in the group and they will all be made local.  We need to
 	       dissolve the group at once so that the predicate does not
 	       segfault though. */
-	    dissolve_same_comdat_group_list (node);
+	    dissolve_same_comdat_group_list ((symtab_node) node);
 	}
 
       if (node->thunk.thunk_p
@@ -936,6 +936,8 @@  function_and_variable_visibility (bool w
 	{
 	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
 	  cgraph_make_decl_local (vnode->symbol.decl);
+	  if (vnode->symbol.same_comdat_group)
+	    dissolve_same_comdat_group_list ((symtab_node) vnode);
 	  vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
 	}
      gcc_assert (TREE_STATIC (vnode->symbol.decl));
Index: symtab.c
===================================================================
--- symtab.c	(revision 186564)
+++ symtab.c	(working copy)
@@ -29,6 +29,7 @@  along with GCC; see the file COPYING3.  
 #include "ggc.h"
 #include "cgraph.h"
 #include "diagnostic.h"
+#include "timevar.h"
 
 /* Hash table used to convert declarations into nodes.  */
 static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
@@ -471,4 +472,129 @@  debug_symtab (void)
   dump_symtab (stderr);
 }
 
+/* Verify common part of symtab nodes.  */
+
+DEBUG_FUNCTION bool
+verify_symtab_base (symtab_node node)
+{
+  bool error_found = false;
+  symtab_node hashed_node;
+
+  if (symtab_function_p (node))
+    {
+      if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
+	{
+          error ("function symbol is not function");
+          error_found = true;
+	}
+    }
+  else if (symtab_variable_p (node))
+    {
+      if (TREE_CODE (node->symbol.decl) != VAR_DECL)
+	{
+          error ("variable symbol is not variable");
+          error_found = true;
+	}
+    }
+  else
+    {
+      error ("node has unknown type");
+      error_found = true;
+    }
+   
+  hashed_node = symtab_get_node (node->symbol.decl);
+  if (!hashed_node)
+    {
+      error ("node not found in symtab decl hashtable");
+      error_found = true;
+    }
+  if (assembler_name_hash)
+    {
+      hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->symbol.decl));
+      if (hashed_node && hashed_node->symbol.previous_sharing_asm_name)
+	{
+          error ("assembler name hash list corrupted");
+          error_found = true;
+	}
+      while (hashed_node)
+	{
+	  if (hashed_node == node)
+	    break;
+	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
+	}
+      if (!hashed_node)
+	{
+          error ("node not found in symtab assembler name hash");
+          error_found = true;
+	}
+    }
+  if (node->symbol.previous_sharing_asm_name
+      && node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node)
+    {
+      error ("double linked list of assembler names corrupted");
+    }
+  if (node->symbol.same_comdat_group)
+    {
+      symtab_node n = node->symbol.same_comdat_group;
+
+      if (!DECL_ONE_ONLY (n->symbol.decl))
+	{
+	  error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
+	  error_found = true;
+	}
+      if (n->symbol.type != node->symbol.type)
+	{
+	  error ("mixing different types of symbol in same comdat groups is not supported");
+	  error_found = true;
+	}
+      if (n == node)
+	{
+	  error ("node is alone in a comdat group");
+	  error_found = true;
+	}
+      do
+	{
+	  if (!n->symbol.same_comdat_group)
+	    {
+	      error ("same_comdat_group is not a circular list");
+	      error_found = true;
+	      break;
+	    }
+	  n = n->symbol.same_comdat_group;
+	}
+      while (n != node);
+    }
+  return error_found;
+}
+
+/* Verify consistency of NODE.  */
+
+DEBUG_FUNCTION void
+verify_symtab_node (symtab_node node)
+{
+  if (seen_error ())
+    return;
+
+  timevar_push (TV_CGRAPH_VERIFY);
+  if (symtab_function_p (node))
+    verify_cgraph_node (cgraph (node));
+  else
+    if (verify_symtab_base (node))
+      {
+        dump_symtab_node (stderr, node);
+        internal_error ("verify_symtab_node failed");
+      }
+  timevar_pop (TV_CGRAPH_VERIFY);
+}
+
+/* Verify symbol table for internal consistency.  */
+
+DEBUG_FUNCTION void
+verify_symtab (void)
+{
+  symtab_node node;
+  FOR_EACH_SYMBOL (node)
+   verify_symtab_node (node);
+}
+
 #include "gt-symtab.h"