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]

dwarf2out patch: support TYPE_DECL_SUPPRESS_DEBUG


As with stabs, we can handle TYPE_DECL_SUPPRESS_DEBUG in dwarf by
pretending that the type was never defined in the current translation
unit.  This is somewhat more complex in dwarf because the info for members
needs to be nested within the info for the class; this patch causes us to
handle that by only including the info for members that are directly
referenced by other DIEs, as the DIE for the definition of a member
function refers to the declaration DIE within the class info.

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

	Generate minimal debug info for types with TYPE_DECL_SUPPRESS_INFO set.
	* dwarf2out.c (gen_struct_or_union_type_die): TYPE_DECL_SUPPRESS_INFO
	means pretend the type isn't defined.
	Don't defer emitting types.
	(gen_type_die_for_member): New fn.
	(gen_decl_die): Call it.
	(splice_child_die): New fn.
	(gen_member_die): Call it rather than generate duplicate dies.

*** dwarf2out.c	Mon Nov 15 12:06:13 1999
--- dwarf2out.c.~6~	Fri Nov 12 07:57:03 1999
*************** static void gen_decl_die		PROTO((tree, d
*** 2552,2557 ****
--- 2552,2558 ----
  static unsigned lookup_filename		PROTO((const char *));
  static void add_incomplete_type		PROTO((tree));
  static void retry_incomplete_types	PROTO((void));
+ static void gen_type_die_for_member	PROTO((tree, tree, dw_die_ref));
  static void gen_abstract_function	PROTO((tree));
  
  /* Section names used to hold DWARF debugging information.  */
*************** add_child_die (die, child_die)
*** 4122,4127 ****
--- 4153,4186 ----
      }
  }
  
+ /* Move CHILD, which must be a child of PARENT, to the front of
+    PARENT's list of children.  */
+ 
+ static void
+ splice_child_die (parent, child)
+      dw_die_ref parent, child;
+ {
+   dw_die_ref *p;
+ 
+   /* We want the declaration DIE from inside the class, not the
+      specification DIE at toplevel.  */
+   if (child->die_parent != parent)
+     child = get_AT_ref (child, DW_AT_specification);
+ 
+   if (parent == NULL || child == NULL || child->die_parent != parent)
+     abort ();
+ 
+   for (p = &(parent->die_child); *p; p = &((*p)->die_sib))
+     if (*p == child)
+       {
+ 	*p = child->die_sib;
+ 	break;
+       }
+ 
+   child->die_sib = parent->die_child;
+   parent->die_child = child;
+ }
+ 
  /* Return a pointer to a newly created DIE node.  */
  
  static inline dw_die_ref
*************** gen_formal_types_die (function_or_method
*** 8202,8207 ****
--- 8203,8238 ----
      }
  }
  
+ /* We want to generate the DIE for TYPE so that we can generate the
+    die for MEMBER, which has been defined; we will need to refer back
+    to the member declaration nested within TYPE.  If we're trying to
+    generate minimal debug info for TYPE, processing TYPE won't do the
+    trick; we need to attach the member declaration by hand.  */
+ 
+ static void
+ gen_type_die_for_member (type, member, context_die)
+      tree type, member;
+      dw_die_ref context_die;
+ {
+   gen_type_die (type, context_die);
+ 
+   /* If we're trying to avoid duplicate debug info, we may not have
+      emitted the member decl for this function.  Emit it now.  */
+   if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))
+       && ! lookup_decl_die (member))
+     {
+       if (decl_ultimate_origin (member))
+ 	abort ();
+ 
+       push_decl_scope (type);
+       if (TREE_CODE (member) == FUNCTION_DECL)
+ 	gen_subprogram_die (member, lookup_type_die (type));
+       else
+ 	gen_variable_die (member, lookup_type_die (type));
+       pop_decl_scope ();
+     }
+ }
+ 
  /* Generate the DWARF2 info for the "abstract" instance
     of a function which we may later generate inlined and/or
     out-of-line instances of.  */
*************** gen_member_die (type, context_die)
*** 8833,8838 ****
--- 8958,8964 ----
       register dw_die_ref context_die;
  {
    register tree member;
+   dw_die_ref child;
  
    /* If this is not an incomplete type, output descriptions of each of its
       members. Note that as we output the DIEs necessary to represent the
*************** gen_member_die (type, context_die)
*** 8860,8873 ****
  
    /* Now output info about the data members and type members.  */
    for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
!     gen_decl_die (member, context_die);
  
    /* Now output info about the function members (if any).  */
    for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member))
!     gen_decl_die (member, context_die);
  }
  
! /* Generate a DIE for a structure or union type.  */
  
  static void
  gen_struct_or_union_type_die (type, context_die)
--- 8986,9018 ----
  
    /* Now output info about the data members and type members.  */
    for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
!     {
!       /* If we thought we were generating minimal debug info for TYPE
! 	 and then changed our minds, some of the member declarations
! 	 may have already been defined.  Don't define them again, but
! 	 do put them in the right order.  */
! 
!       child = lookup_decl_die (member);
!       if (child)
! 	splice_child_die (context_die, child);
!       else
! 	gen_decl_die (member, context_die);
!     }
  
    /* Now output info about the function members (if any).  */
    for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member))
!     {
!       child = lookup_decl_die (member);
!       if (child)
! 	splice_child_die (context_die, child);
!       else
! 	gen_decl_die (member, context_die);
!     }
  }
  
! /* Generate a DIE for a structure or union type.  If TYPE_DECL_SUPPRESS_DEBUG
!    is set, we pretend that the type was never defined, so we only get the
!    member DIEs needed by later specification DIEs.  */
  
  static void
  gen_struct_or_union_type_die (type, context_die)
*************** gen_struct_or_union_type_die (type, cont
*** 8877,8884 ****
    register dw_die_ref type_die = lookup_type_die (type);
    register dw_die_ref scope_die = 0;
    register int nested = 0;
  
!   if (type_die && ! TYPE_SIZE (type))
      return;
  
    if (TYPE_CONTEXT (type) != NULL_TREE
--- 9022,9031 ----
    register dw_die_ref type_die = lookup_type_die (type);
    register dw_die_ref scope_die = 0;
    register int nested = 0;
+   int complete = (TYPE_SIZE (type)
+ 		  && ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)));
  
!   if (type_die && ! complete)
      return;
  
    if (TYPE_CONTEXT (type) != NULL_TREE
*************** gen_struct_or_union_type_die (type, cont
*** 8912,8918 ****
      }
    /* If this type has been completed, then give it a byte_size attribute and
       then give a list of members.  */
!   else if (TYPE_SIZE (type))
      {
        /* Prevent infinite recursion in cases where the type of some member of 
           this type is expressed in terms of this type itself.  */
--- 9059,9065 ----
      }
    /* If this type has been completed, then give it a byte_size attribute and
       then give a list of members.  */
!   else if (complete)
      {
        /* Prevent infinite recursion in cases where the type of some member of 
           this type is expressed in terms of this type itself.  */
*************** gen_decl_die (decl, context_die)
*** 9395,9401 ****
  	  /* And its containing type.  */
  	  origin = decl_class_context (decl);
  	  if (origin != NULL_TREE)
! 	    gen_type_die (origin, context_die);
  
  	  /* And its virtual context.  */
  	  if (DECL_VINDEX (decl) != NULL_TREE)
--- 9547,9553 ----
  	  /* And its containing type.  */
  	  origin = decl_class_context (decl);
  	  if (origin != NULL_TREE)
! 	    gen_type_die_for_member (origin, decl, context_die);
  
  	  /* And its virtual context.  */
  	  if (DECL_VINDEX (decl) != NULL_TREE)
*************** gen_decl_die (decl, context_die)
*** 9450,9456 ****
        /* And its containing type.  */
        origin = decl_class_context (decl);
        if (origin != NULL_TREE)
! 	gen_type_die (origin, context_die);
  
        /* Now output the DIE to represent the data object itself.  This gets
           complicated because of the possibility that the VAR_DECL really
--- 9602,9608 ----
        /* And its containing type.  */
        origin = decl_class_context (decl);
        if (origin != NULL_TREE)
! 	gen_type_die_for_member (origin, decl, context_die);
  
        /* Now output the DIE to represent the data object itself.  This gets
           complicated because of the possibility that the VAR_DECL really


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