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]

(C++) patch to debug info optimization


In the past, we've tried to limit where we emitted debug info for classes,
since it can get pretty big.  It had problems with the info never being
emitted for some classes, and was largely disabled.  This patch updates the
optimization so that polymorphic classes have their info emitted with the
vtable.

This is not very interesting on stabs targets that support the BINCL
optimization (such as Linux), but it's a slight win there, too.

1999-11-15  Jason Merrill  <jason@casey.cygnus.com>

	* search.c (maybe_suppress_debug_info): New function...
	* class.c (finish_struct_1): ...split out from here.
	* cp-tree.h: Declare it.
	* decl2.c (finish_vtable_vardecl): Override TYPE_DECL_SUPPRESS_DEBUG
	if we're writing out the vtable.
	* decl.c, search.c (dfs_debug_mark, dfs_debug_unmarked_p, 
	note_debug_info_needed): #if 0 out.

Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.129
diff -c -p -r1.129 search.c
*** search.c	1999/10/06 19:01:43	1.129
--- search.c	1999/11/16 00:53:09
*************** static tree marked_new_vtablep PROTO((tr
*** 103,110 ****
--- 103,112 ----
  static tree unmarked_new_vtablep PROTO((tree, void *));
  static tree marked_pushdecls_p PROTO((tree, void *));
  static tree unmarked_pushdecls_p PROTO((tree, void *));
+ #if 0
  static tree dfs_debug_unmarkedp PROTO((tree, void *));
  static tree dfs_debug_mark PROTO((tree, void *));
+ #endif
  static tree dfs_find_vbases PROTO((tree, void *));
  static tree dfs_clear_vbase_slots PROTO((tree, void *));
  static tree dfs_init_vbase_pointers PROTO((tree, void *));
*************** unmarked_pushdecls_p (binfo, data) 
*** 2301,2307 ****
  #if 0
  static int dfs_search_slot_nonempty_p (binfo) tree binfo;
  { return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
- #endif
  
  static tree 
  dfs_debug_unmarkedp (binfo, data) 
--- 2303,2308 ----
*************** dfs_debug_unmarkedp (binfo, data) 
*** 2311,2316 ****
--- 2312,2318 ----
    return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
  	  ? binfo : NULL_TREE);
  }
+ #endif
  
  /* The worker functions for `dfs_walk'.  These do not need to
     test anything (vis a vis marking) if they are paired with
*************** dfs_unmark_new_vtable (binfo) tree binfo
*** 2351,2358 ****
  static void
  dfs_clear_search_slot (binfo) tree binfo;
  { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
- #endif
  
  static tree
  dfs_debug_mark (binfo, data)
       tree binfo;
--- 2353,2362 ----
  static void
  dfs_clear_search_slot (binfo) tree binfo;
  { CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
  
+ /* Keep this code around in case we later want to control debug info
+    based on whether a type is "used".  Currently, we only suppress debug
+    info if we can emit it with the vtable.  jason 1999-11-11) */
  static tree
  dfs_debug_mark (binfo, data)
       tree binfo;
*************** dfs_debug_mark (binfo, data)
*** 2360,2406 ****
  {
    tree t = BINFO_TYPE (binfo);
  
-   /* Use heuristic that if there are virtual functions,
-      ignore until we see a non-inline virtual function.  */
-   tree methods = CLASSTYPE_METHOD_VEC (t);
- 
    CLASSTYPE_DEBUG_REQUESTED (t) = 1;
  
-   if (methods == 0)
-     return NULL_TREE;
- 
    /* If interface info is known, either we've already emitted the debug
       info or we don't need to.  */
    if (CLASSTYPE_INTERFACE_KNOWN (t))
      return NULL_TREE;
  
!   /* If debug info is requested from this context for this type, supply it.
!      If debug info is requested from another context for this type,
!      see if some third context can supply it.  */
!   if (current_function_decl == NULL_TREE
!       || DECL_CLASS_CONTEXT (current_function_decl) != t)
!     {
!       if (TREE_VEC_ELT (methods, 1))
! 	methods = TREE_VEC_ELT (methods, 1);
!       else if (TREE_VEC_ELT (methods, 0))
! 	methods = TREE_VEC_ELT (methods, 0);
!       else
! 	methods = TREE_VEC_ELT (methods, 2);
!       methods = OVL_CURRENT (methods);
!       while (methods)
! 	{
! 	  if (DECL_VINDEX (methods)
! 	      && DECL_THIS_INLINE (methods) == 0
! 	      && DECL_ABSTRACT_VIRTUAL_P (methods) == 0)
! 	    {
! 	      /* Somebody, somewhere is going to have to define this
! 		 virtual function.  When they do, they will provide
! 		 the debugging info.  */
! 	      return NULL_TREE;
! 	    }
! 	  methods = TREE_CHAIN (methods);
! 	}
!     }
    /* We cannot rely on some alien method to solve our problems,
       so we must write out the debug info ourselves.  */
    TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
--- 2364,2381 ----
  {
    tree t = BINFO_TYPE (binfo);
  
    CLASSTYPE_DEBUG_REQUESTED (t) = 1;
  
    /* If interface info is known, either we've already emitted the debug
       info or we don't need to.  */
    if (CLASSTYPE_INTERFACE_KNOWN (t))
      return NULL_TREE;
  
!   /* If the class has virtual functions, we'll emit the debug info
!      with the vtable.  */
!   if (TYPE_VIRTUAL_P (t))
!     return NULL_TREE;
! 
    /* We cannot rely on some alien method to solve our problems,
       so we must write out the debug info ourselves.  */
    TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
*************** dfs_debug_mark (binfo, data)
*** 2408,2413 ****
--- 2383,2389 ----
  
    return NULL_TREE;
  }
+ #endif
  
  struct vbase_info 
  {
*************** get_vbase_types (type)
*** 2933,2938 ****
--- 2909,2949 ----
    return vbase_types;
  }
  
+ /* Debug info for C++ classes can get very large; try to avoid
+    emitting it everywhere.
+ 
+    As it happens, this optimization wins even when the target supports
+    BINCL (though only slightly), so we always do it. */
+ 
+ void
+ maybe_suppress_debug_info (t)
+      tree t;
+ {
+   /* We don't bother with this for dwarf1, which shouldn't be used for C++
+      anyway.  */
+   if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
+       || write_symbols == NO_DEBUG)
+     return;
+ 
+   /* If we already know how we're handling this class, handle debug info
+      the same way.  */
+   if (CLASSTYPE_INTERFACE_ONLY (t))
+     TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+   else if (CLASSTYPE_INTERFACE_KNOWN (t))
+     /* Don't set it.  */;
+   /* If the class has virtual functions, write out the debug info
+      along with the vtable.  */
+   else if (TYPE_VIRTUAL_P (t))
+     TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
+ 
+   /* Otherwise, just emit the debug info normally.  */
+ }
+ 
+ #if 0
+ /* Keep this code around in case we later want to control debug info
+    based on whether a type is "used".  Currently, we only suppress debug
+    info if we can emit it with the vtable.  jason 1999-11-11) */
+ 
  /* If we want debug info for a type TYPE, make sure all its base types
     are also marked as being potentially interesting.  This avoids
     the problem of not writing any debug info for intermediate basetypes
*************** note_debug_info_needed (type)
*** 2952,2961 ****
      return;
  
    /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
!      does not support name references between translation units.  Well, we
!      could, but that would mean putting global labels in the debug output
!      before each exported type and each of its functions and static data
!      members.  */
    if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
        || write_symbols == NO_DEBUG)
      return;
--- 2963,2971 ----
      return;
  
    /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
!      does not support name references between translation units.  It supports
!      symbolic references between translation units, but only within a single
!      executable or shared library.  */
    if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG
        || write_symbols == NO_DEBUG)
      return;
*************** note_debug_info_needed (type)
*** 2970,2975 ****
--- 2980,2986 ----
  	note_debug_info_needed (ttype);
      }
  }
+ #endif
  
  /* Subroutines of push_class_decls ().  */
  
*************** types_overlap_p (empty_type, next_type)
*** 3332,3339 ****
  	    dfs_no_overlap_yet, &oi);
    return oi.found_overlap;
  }
  
! /* Given a vtable VAR, determine which binfo it comes from.  */
  
  tree
  binfo_for_vtable (var)
--- 3343,3352 ----
  	    dfs_no_overlap_yet, &oi);
    return oi.found_overlap;
  }
+ 
+ /* Given a vtable VAR, determine which binfo it comes from.
  
!    FIXME What about secondary vtables?  */
  
  tree
  binfo_for_vtable (var)
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.198
diff -c -p -r1.198 class.c
*** class.c	1999/11/07 22:21:28	1.198
--- class.c	1999/11/16 00:53:19
*************** finish_struct_1 (t)
*** 4183,4228 ****
    if (warn_overloaded_virtual)
      warn_hidden (t);
  
! #if 0
!   /* This has to be done after we have sorted out what to do with
!      the enclosing type.  */
!   if (write_symbols != DWARF_DEBUG)
!     {
!       /* Be smarter about nested classes here.  If a type is nested,
! 	 only output it if we would output the enclosing type.  */
!       if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (t)))
! 	DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = TREE_ASM_WRITTEN (TYPE_MAIN_DECL (t));
!     }
! #endif
! 
!   if (write_symbols != DWARF_DEBUG && write_symbols != DWARF2_DEBUG)
!     {
!       /* If the type has methods, we want to think about cutting down
! 	 the amount of symbol table stuff we output.  The value stored in
! 	 the TYPE_DECL's DECL_IGNORED_P slot is a first approximation.
! 	 For example, if a member function is seen and we decide to
! 	 write out that member function, then we can change the value
! 	 of the DECL_IGNORED_P slot, and the type will be output when
! 	 that member function's debug info is written out.
! 
! 	 We can't do this with DWARF, which does not support name
! 	 references between translation units.  */
!       if (CLASSTYPE_METHOD_VEC (t))
! 	{
! 	  /* Don't output full info about any type
! 	     which does not have its implementation defined here.  */
! 	  if (CLASSTYPE_INTERFACE_ONLY (t))
! 	    TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
! #if 0
! 	  /* XXX do something about this.  */
! 	  else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
! 	    /* Only a first approximation!  */
! 	    TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
! #endif
! 	}
!       else if (CLASSTYPE_INTERFACE_ONLY (t))
! 	TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
!     }
  
    /* Finish debugging output for this type.  */
    rest_of_type_compilation (t, toplevel_bindings_p ());
--- 4183,4189 ----
    if (warn_overloaded_virtual)
      warn_hidden (t);
  
!   maybe_suppress_debug_info (t);
  
    /* Finish debugging output for this type.  */
    rest_of_type_compilation (t, toplevel_bindings_p ());
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.343
diff -c -p -r1.343 cp-tree.h
*** cp-tree.h	1999/11/09 08:15:07	1.343
--- cp-tree.h	1999/11/16 00:53:25
*************** cp-tree.h			PROTO(
*** 3815,3820 ****
--- 3815,3821 ----
  extern void expand_indirect_vtbls_init		PROTO((tree, tree, tree));
  extern void clear_search_slots			PROTO((tree));
  extern tree get_vbase_types			PROTO((tree));
+ extern void maybe_suppress_debug_info		PROTO((tree));
  extern void note_debug_info_needed		PROTO((tree));
  extern void push_class_decls			PROTO((tree));
  extern void pop_class_decls			PROTO((void));
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.277
diff -c -p -r1.277 decl2.c
*** decl2.c	1999/11/05 23:11:57	1.277
--- decl2.c	1999/11/16 00:53:35
*************** finish_vtable_vardecl (t, data)
*** 2602,2607 ****
--- 2602,2615 ----
        if (flag_syntax_only)
  	TREE_ASM_WRITTEN (vars) = 1;
  
+       /* Since we're writing out the vtable here, also write the debug 
+ 	 info.  */
+       if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (ctype)))
+ 	{
+ 	  TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (ctype)) = 0;
+ 	  rest_of_type_compilation (ctype, toplevel_bindings_p ());
+ 	}
+ 
        return 1;
      }
    else if (!DECL_NEEDED_P (vars))
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.497
diff -c -p -r1.497 decl.c
*** decl.c	1999/11/09 08:15:07	1.497
--- decl.c	1999/11/16 00:53:53
*************** layout_var_decl (decl)
*** 7094,7105 ****
--- 7094,7110 ----
        cp_error ("storage size of `%D' isn't known", decl);
        TREE_TYPE (decl) = error_mark_node;
      }
+ #if 0
+   /* Keep this code around in case we later want to control debug info
+      based on whether a type is "used".  (jason 1999-11-11) */
+ 
    else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
      /* Let debugger know it should output info for this type.  */
      note_debug_info_needed (ttype);
  
    if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
      note_debug_info_needed (DECL_CONTEXT (decl));
+ #endif
  
    if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
        && DECL_SIZE (decl) != NULL_TREE
*************** finish_function (lineno, flags)
*** 13511,13516 ****
--- 13516,13525 ----
  	  tree ttype = target_type (fntype);
  	  tree parmdecl;
  
+ #if 0
+ 	  /* Keep this code around in case we later want to control debug info
+ 	     based on whether a type is "used".  (jason 1999-11-11) */
+ 
  	  if (IS_AGGR_TYPE (ttype))
  	    /* Let debugger know it should output info for this type.  */
  	    note_debug_info_needed (ttype);
*************** finish_function (lineno, flags)
*** 13522,13527 ****
--- 13531,13537 ----
  		/* Let debugger know it should output info for this type.  */
  		note_debug_info_needed (ttype);
  	    }
+ #endif
  	}
  
        /* Clean house because we will need to reorder insns here.  */
*************** finish_function (lineno, flags)
*** 13711,13718 ****
--- 13721,13733 ----
  	  mark_inline_for_output (fndecl);
  	}
  
+ #if 0
+       /* Keep this code around in case we later want to control debug info
+ 	 based on whether a type is "used".  (jason 1999-11-11) */
+ 
        if (ctype && TREE_ASM_WRITTEN (fndecl))
  	note_debug_info_needed (ctype);
+ #endif
  
        returns_null |= can_reach_end;
  


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