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]

PATCH: Debugging of clones


This patch changes the implementation of cloned [cd]tors so that the
original function (which is never emitted) is treated as an inline
function, and the clones are treated as out-of-line instances of it, which
logically they are.

This means a few changes to accommodate functions which always have
DECL_ABSTRACT set; previously it was set and then cleared as part of the
process of handling inlines with dwarf.

stabs output will now just ignore DECL_ABSTRACT methods in a class, since
it doesn't play the abstract/concrete game with inlines.  dwarf[12] output
will ignore methods with DECL_ABSTRACT_ORIGIN set, as they will later refer
back to the DECL_ABSTRACT version.

2001-02-21  Jason Merrill  <jason@redhat.com>

	* class.c (clone_function_decl): Set DECL_ABSTRACT on original fn.
	* decl.c (duplicate_decls): Preserve DECL_ABSTRACT.
	* class.c (build_clone): Set DECL_ABSTRACT_ORIGIN for the clone.
	* optimize.c (maybe_clone_body): Set DECL_ABSTRACT_ORIGIN for the
	parms and outer BLOCK.  note_deferral_of_defined_inline_function.

2001-02-21  Jason Merrill  <jason@redhat.com>

	* dwarf2out.c (add_name_and_src_coords_attributes): Don't add 
	DW_AT_MIPS_linkage_name to abstract methods.
	(dwarf2out_abstract_function): Emit class context before calling
	set_decl_abstract_flags.  Don't clear DECL_ABSTRACT.
	(gen_subprogram_die): Remove obsolete code.
	(gen_member_die): Don't include clones in the member list.
	(gen_decl_die): Emit abstract info for clone origin.
	* dwarfout.c (output_type): Don't include clones in the member list.
	* dbxout.c (dbxout_type_methods): Ignore abstract methods.
	* toplev.c (note_deferral_of_defined_inline_function): Don't clear
	DECL_ABSTRACT on a function that already has it set.

Index: dbxout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dbxout.c,v
retrieving revision 1.72
diff -c -p -r1.72 dbxout.c
*** dbxout.c	2001/01/28 01:50:05	1.72
--- dbxout.c	2001/02/21 12:23:52
*************** dbxout_type_methods (type)
*** 841,847 ****
  
  	  last = fndecl;
  
! 	  if (DECL_IGNORED_P (fndecl))
  	    continue;
  
  	  if (flag_minimal_debug)
--- 841,849 ----
  
  	  last = fndecl;
  
! 	  /* Also ignore abstract methods; those are only interesting to
! 	     the DWARF backends.  */
! 	  if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
  	    continue;
  
  	  if (flag_minimal_debug)
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.243
diff -c -p -r1.243 dwarf2out.c
*** dwarf2out.c	2001/02/16 13:03:10	1.243
--- dwarf2out.c	2001/02/21 12:23:58
*************** add_name_and_src_coords_attributes (die,
*** 9390,9396 ****
  
        if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
  	  && TREE_PUBLIC (decl)
! 	  && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
  	add_AT_string (die, DW_AT_MIPS_linkage_name,
  		       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
      }
--- 9390,9397 ----
  
        if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
  	  && TREE_PUBLIC (decl)
! 	  && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
! 	  && !DECL_ABSTRACT (decl))
  	add_AT_string (die, DW_AT_MIPS_linkage_name,
  		       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
      }
*************** void
*** 10025,10043 ****
  dwarf2out_abstract_function (decl)
       tree decl;
  {
!   register dw_die_ref old_die = lookup_decl_die (decl);
    tree save_fn;
  
    if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
      /* We've already generated the abstract instance.  */
      return;
  
    save_fn = current_function_decl;
    current_function_decl = decl;
  
    set_decl_abstract_flags (decl, 1);
    dwarf2out_decl (decl);
!   set_decl_abstract_flags (decl, 0);
  
    current_function_decl = save_fn;
  }
--- 10029,10062 ----
  dwarf2out_abstract_function (decl)
       tree decl;
  {
!   register dw_die_ref old_die;
    tree save_fn;
+   tree context;
+   int was_abstract = DECL_ABSTRACT (decl);
  
+   /* Make sure we have the actual abstract inline, not a clone.  */
+   decl = DECL_ORIGIN (decl);
+ 
+   old_die = lookup_decl_die (decl);  
    if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
      /* We've already generated the abstract instance.  */
      return;
  
+   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
+      we don't get confused by DECL_ABSTRACT.  */
+   context = decl_class_context (decl);
+   if (context)
+     gen_type_die_for_member
+       (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+  
+   /* Pretend we've just finished compiling this function.  */
    save_fn = current_function_decl;
    current_function_decl = decl;
  
    set_decl_abstract_flags (decl, 1);
    dwarf2out_decl (decl);
!   if (! was_abstract)
!     set_decl_abstract_flags (decl, 0);
  
    current_function_decl = save_fn;
  }
*************** gen_subprogram_die (decl, context_die)
*** 10088,10104 ****
        subr_die = new_die (DW_TAG_subprogram, context_die);
        add_abstract_origin_attribute (subr_die, origin);
      }
-   else if (old_die && DECL_ABSTRACT (decl)
- 	   && get_AT_unsigned (old_die, DW_AT_inline))
-     {
-       /* This must be a redefinition of an extern inline function.
- 	 We can just reuse the old die here.  */
-       subr_die = old_die;
- 
-       /* Clear out the inlined attribute and parm types.  */
-       remove_AT (subr_die, DW_AT_inline);
-       remove_children (subr_die);
-     }
    else if (old_die)
      {
        register unsigned file_index
--- 10107,10112 ----
*************** gen_member_die (type, context_die)
*** 10738,10743 ****
--- 10746,10755 ----
    /* Now output info about the function members (if any).  */
    for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member))
      {
+       /* Don't include clones in the member list.  */
+       if (DECL_ABSTRACT_ORIGIN (member))
+ 	continue;
+ 
        child = lookup_decl_die (member);
        if (child)
  	splice_child_die (context_die, child);
*************** gen_decl_die (decl, context_die)
*** 11266,11285 ****
  	  && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl)))
  	break;
  
        /* If we're emitting an out-of-line copy of an inline function,
  	 emit info for the abstract instance and set up to refer to it.  */
!       if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl)
! 	  && ! class_scope_p (context_die)
! 	  /* dwarf2out_abstract_function won't emit a die if this is just a
! 	     declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
! 	     that case, because that works only if we have a die.  */
! 	  && DECL_INITIAL (decl) != NULL_TREE)
  	{
  	  dwarf2out_abstract_function (decl);
  	  set_decl_origin_self (decl);
  	}
! 
!       if (debug_info_level > DINFO_LEVEL_TERSE)
  	{
  	  /* Before we describe the FUNCTION_DECL itself, make sure that we
  	     have described its return type.  */
--- 11278,11300 ----
  	  && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl)))
  	break;
  
+       /* If we're emitting a clone, emit info for the abstract instance.  */
+       if (DECL_ORIGIN (decl) != decl)
+ 	dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl));
        /* If we're emitting an out-of-line copy of an inline function,
  	 emit info for the abstract instance and set up to refer to it.  */
!       else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl)
! 	       && ! class_scope_p (context_die)
! 	       /* dwarf2out_abstract_function won't emit a die if this is just
! 		  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
! 		  that case, because that works only if we have a die.  */
! 	       && DECL_INITIAL (decl) != NULL_TREE)
  	{
  	  dwarf2out_abstract_function (decl);
  	  set_decl_origin_self (decl);
  	}
!       /* Otherwise we're emitting the primary DIE for this decl.  */
!       else if (debug_info_level > DINFO_LEVEL_TERSE)
  	{
  	  /* Before we describe the FUNCTION_DECL itself, make sure that we
  	     have described its return type.  */
Index: dwarfout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarfout.c,v
retrieving revision 1.79
diff -c -p -r1.79 dwarfout.c
*** dwarfout.c	2001/02/04 22:43:58	1.79
--- dwarfout.c	2001/02/21 12:24:03
*************** output_type (type, containing_scope)
*** 4444,4450 ****
  	      for (func_member = TYPE_METHODS (type);
  		   func_member;
  		   func_member = TREE_CHAIN (func_member))
! 		output_decl (func_member, type);
  	    }
  
  	    --in_class;
--- 4444,4456 ----
  	      for (func_member = TYPE_METHODS (type);
  		   func_member;
  		   func_member = TREE_CHAIN (func_member))
! 		{
! 		  /* Don't include clones in the member list.  */
! 		  if (DECL_ABSTRACT_ORIGIN (func_member))
! 		    continue;
! 
! 		  output_decl (func_member, type);
! 		}
  	    }
  
  	    --in_class;
Index: integrate.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/integrate.c,v
retrieving revision 1.128
diff -c -p -r1.128 integrate.c
*** integrate.c	2001/02/16 13:03:10	1.128
--- integrate.c	2001/02/21 12:24:06
*************** function_cannot_inline_p (fndecl)
*** 139,144 ****
--- 139,147 ----
    register tree parms;
    rtx result;
  
+   if (DECL_UNINLINABLE (fndecl))
+     return N_("function cannot be inline");
+ 
    /* No inlines with varargs.  */
    if ((last && TREE_VALUE (last) != void_type_node)
        || current_function_varargs)
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.425
diff -c -p -r1.425 toplev.c
*** toplev.c	2001/02/19 00:09:28	1.425
--- toplev.c	2001/02/21 12:24:11
*************** note_deferral_of_defined_inline_function
*** 2661,2679 ****
    /* Generate the DWARF info for the "abstract" instance of a function
       which we may later generate inlined and/or out-of-line instances
       of.  */
!   if (write_symbols == DWARF_DEBUG && DECL_INLINE (decl))
      {
        /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
  	 DWARF code expects it to be set in this case.  Intuitively,
  	 DECL is the function we just finished defining, so setting
  	 CURRENT_FUNCTION_DECL is sensible.  */
        tree saved_cfd = current_function_decl;
        current_function_decl = decl;
  
        /* Let the DWARF code do its work.  */
        set_decl_abstract_flags (decl, 1);
        dwarfout_file_scope_decl (decl, 0);
!       set_decl_abstract_flags (decl, 0);
  
        /* Reset CURRENT_FUNCTION_DECL.  */
        current_function_decl = saved_cfd;
--- 2661,2683 ----
    /* Generate the DWARF info for the "abstract" instance of a function
       which we may later generate inlined and/or out-of-line instances
       of.  */
!   if (write_symbols == DWARF_DEBUG
!       && (DECL_INLINE (decl) || DECL_ABSTRACT (decl))
!       && ! DECL_ABSTRACT_ORIGIN (decl))
      {
        /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
  	 DWARF code expects it to be set in this case.  Intuitively,
  	 DECL is the function we just finished defining, so setting
  	 CURRENT_FUNCTION_DECL is sensible.  */
        tree saved_cfd = current_function_decl;
+       int was_abstract = DECL_ABSTRACT (decl);
        current_function_decl = decl;
  
        /* Let the DWARF code do its work.  */
        set_decl_abstract_flags (decl, 1);
        dwarfout_file_scope_decl (decl, 0);
!       if (! was_abstract)
! 	set_decl_abstract_flags (decl, 0);
  
        /* Reset CURRENT_FUNCTION_DECL.  */
        current_function_decl = saved_cfd;
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.363
diff -c -p -r1.363 class.c
*** cp/class.c	2001/02/18 20:41:10	1.363
--- cp/class.c	2001/02/21 12:24:24
*************** build_clone (fn, name)
*** 4179,4184 ****
--- 4179,4185 ----
    clone = copy_decl (fn);
    /* Remember where this function came from.  */
    DECL_CLONED_FUNCTION (clone) = fn;
+   DECL_ABSTRACT_ORIGIN (clone) = fn;
    /* Reset the function name.  */
    DECL_NAME (clone) = name;
    DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
*************** clone_function_decl (fn, update_method_v
*** 4339,4344 ****
--- 4340,4348 ----
        if (update_method_vec_p)
  	add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
      }
+ 
+   /* Note that this is an abstract function that is never emitted.  */
+   DECL_ABSTRACT (fn) = 1;
  }
  
  /* For each of the constructors and destructors in T, create an
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.752
diff -c -p -r1.752 decl.c
*** cp/decl.c	2001/02/18 20:31:42	1.752
--- cp/decl.c	2001/02/21 12:24:35
*************** duplicate_decls (newdecl, olddecl)
*** 3626,3631 ****
--- 3626,3634 ----
  	DECL_INLINE (olddecl) = 1;
        DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
  
+       /* Preserve abstractness on cloned [cd]tors.  */
+       DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+ 
        if (! types_match)
  	{
  	  DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.55
diff -c -p -r1.55 optimize.c
*** cp/optimize.c	2001/02/19 04:06:48	1.55
--- cp/optimize.c	2001/02/21 12:24:37
*************** maybe_clone_body (fn)
*** 932,937 ****
--- 932,940 ----
        && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
      return 0;
  
+   /* Emit the DWARF1 abstract instance.  */
+   note_deferral_of_defined_inline_function (fn);
+ 
    /* We know that any clones immediately follow FN in the TYPE_METHODS
       list.  */
    for (clone = TREE_CHAIN (fn);
*************** maybe_clone_body (fn)
*** 996,1001 ****
--- 999,1005 ----
  		 from the CLONE to this parameter.  */
  	      if (DECL_HAS_VTT_PARM_P (clone))
  		{
+ 		  DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
  		  splay_tree_insert (id.decl_map,
  				     (splay_tree_key) parm,
  				     (splay_tree_value) clone_parm);
*************** maybe_clone_body (fn)
*** 1013,1018 ****
--- 1017,1023 ----
  	     function.  */
  	  else
  	    {
+ 	      DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
  	      splay_tree_insert (id.decl_map,
  				 (splay_tree_key) parm,
  				 (splay_tree_value) clone_parm);
*************** maybe_clone_body (fn)
*** 1029,1035 ****
  
        /* Now, expand this function into RTL, if appropriate.  */
        function_name_declared_p = 1;
!       expand_body (finish_function (0));
        pop_from_top_level ();
      }
    
--- 1034,1042 ----
  
        /* Now, expand this function into RTL, if appropriate.  */
        function_name_declared_p = 1;
!       finish_function (0);
!       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
!       expand_body (clone);
        pop_from_top_level ();
      }
    

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