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]

[DWARF] mark partial fn versions and OMP frags as partial in dwarf2+ debug info


debug info: partial noentry functions: infra

This is the first patch of a set that addresses two different but
somewhat related issues.

On the one hand, after partial inlining, the non-inlined function
fragment is output in a way that debug info consumers can't distinguish
from the entire function: debug info lists the entire function as
abstract origin for the fragment, but nothing that indicates the
fragment does not stand for the entire function.  So, if a debugger is
asked to set a breakpoint at the entry point of the function, it might
very well set one at the entry point of the fragment, which is likely
not where users expect to stop.

On the other hand, OpenMP blocks are split out into artificial functions
that do not indicate their executable code is part of another function.
The artificial functions are nested within the original function, but
that's hardly enough: ideally, debug info consumers should be able to
tell that, if they stop within one of these functions, they're
abstractly within the original function.

This patch introduces a new DWARF attribute to indicate that a function
is a partial copy of its abstract origin, specifically, that its entry
point does not correspond to the entry point of the abstract origin.
This attribute can then be used to mark the out-of-line portion of
partial inlines, and OpenMP blocks split out into artificial functions.


This patchset was regstrapped on x86_64-linux-gnu and i686-linux-gnu.

Ok to install the first patch? (infrastructure)

Ok to install the second patch? (function versioning)

Ok to install the third patch? (OpenMP fragments)


for  include/ChangeLog

	* dwarf2.def (DW_AT_GNU_partial_noentry): New.

for  gcc/ChangeLog

	* tree-core.h (tree_function_decl): Drop unused
	tm_clone_flag.  Add partial_copy_flag.
	* tree.h (DECL_FUNCTION_PARTIAL_COPY): New.
	* dwarf2out.c (checksum_attributes): Add at_partial_noentry.
	(collect_checksum_attributes): Set it.
	(die_checksum_ordered): Checksum it.
	(gen_subprogam_die): Keep the old die if it the partial copy
	flag matches the partial noentry attribute.  Set the attribute
	as needed.
---
 gcc/dwarf2out.c    |   11 ++++++++++-
 gcc/tree-core.h    |    2 +-
 gcc/tree.h         |   10 ++++++++++
 include/dwarf2.def |    3 +++
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 76a538f1ff97..db0bc12a1f46 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -6944,6 +6944,7 @@ struct checksum_attributes
   dw_attr_node *at_virtuality;
   dw_attr_node *at_visibility;
   dw_attr_node *at_vtable_elem_location;
+  dw_attr_node *at_partial_noentry;
 };
 
 /* Collect the attributes that we will want to use for the checksum.  */
@@ -7108,6 +7109,9 @@ collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
         case DW_AT_vtable_elem_location:
           attrs->at_vtable_elem_location = a;
           break;
+	case DW_AT_GNU_partial_noentry:
+	  attrs->at_partial_noentry = a;
+	  break;
         default:
           break;
         }
@@ -7183,6 +7187,7 @@ die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
   CHECKSUM_ATTR (attrs.at_type);
   CHECKSUM_ATTR (attrs.at_friend);
   CHECKSUM_ATTR (attrs.at_alignment);
+  CHECKSUM_ATTR (attrs.at_partial_noentry);
 
   /* Checksum the child DIEs.  */
   c = die->die_child;
@@ -21933,7 +21938,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (old_die && old_die->die_parent == NULL)
 	add_child_die (context_die, old_die);
 
-      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin)
+	  && (DECL_FUNCTION_PARTIAL_COPY (decl)
+	      == get_AT_flag (old_die, DW_AT_GNU_partial_noentry)))
 	{
 	  /* If we have a DW_AT_abstract_origin we have a working
 	     cached version.  */
@@ -21943,6 +21950,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 	{
 	  subr_die = new_die (DW_TAG_subprogram, context_die, decl);
 	  add_abstract_origin_attribute (subr_die, origin);
+	  if (DECL_FUNCTION_PARTIAL_COPY (decl))
+	    add_AT_flag (subr_die, DW_AT_GNU_partial_noentry, true);
 	  /*  This is where the actual code for a cloned function is.
 	      Let's emit linkage name attribute for it.  This helps
 	      debuggers to e.g, set breakpoints into
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index f74f1453de6d..507016db23e9 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1784,7 +1784,7 @@ struct GTY(()) tree_function_decl {
   unsigned pure_flag : 1;
   unsigned looping_const_or_pure_flag : 1;
   unsigned has_debug_args_flag : 1;
-  unsigned tm_clone_flag : 1;
+  unsigned partial_copy_flag : 1;
   unsigned versioned_function : 1;
   /* No bits left.  */
 };
diff --git a/gcc/tree.h b/gcc/tree.h
index 39acffe52662..12c0b3835d9f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3002,6 +3002,16 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
 #define DECL_FUNCTION_VERSIONED(NODE)\
    (FUNCTION_DECL_CHECK (NODE)->function_decl.versioned_function)
 
+/* In FUNCTION_DECL, this is set if this function is only a partial
+   clone/version/copy of its DECL_ABSTRACT_ORIGIN.  It should be used
+   for the non-inlined portion of a partial inline, for openmp blocks
+   turned into separate functions, and for any other cases in which we
+   clone only select parts of a function, presumably omitting its
+   entry point, that is presumed to remain in a separate, controlling
+   version of the function.  */
+#define DECL_FUNCTION_PARTIAL_COPY(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.partial_copy_flag)
+
 /* In FUNCTION_DECL, this is set if this function is a C++ constructor.
    Devirtualization machinery uses this knowledge for determing type of the
    object constructed.  Also we assume that constructor address is not
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 2a3b23fef873..f2dd9196b039 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -433,6 +433,9 @@ DW_AT (DW_AT_GNU_all_source_call_sites, 0x2118)
 DW_AT (DW_AT_GNU_macros, 0x2119)
 /* Attribute for C++ deleted special member functions (= delete;).  */
 DW_AT (DW_AT_GNU_deleted, 0x211a)
+/* This flag indicates a partial copy of a function, whose entry point
+   does not correspond to that of the abstract origin.  */
+DW_AT (DW_AT_GNU_partial_noentry, 0x211b)
 /* Extensions for Fission.  See http://gcc.gnu.org/wiki/DebugFission.  */
 DW_AT (DW_AT_GNU_dwo_name, 0x2130)
 DW_AT (DW_AT_GNU_dwo_id, 0x2131)


debug info: partial noentry functions: partial inlines

When we version a function without copying all of its blocks,
particularly when we omit or modify the entry point, mark the function
as a partial copy.  This should enable debug info consumers to avoid
setting a breakpoint in the partial copy when the user requests a
breakpoint at the function's entry point.

An alternate entry point is specified when versioning a function only
as we inline part of it; the non-inlined portion is what goes in the
new version.

Such partial copies used to refer back to the entire function as their
abstract origin.  Without the partial copy marker, debug info
consumers would set a breakpoint for the function at the inlined
entry point, and also at the partial copy's entry point, although the
latter is not the actual entry point for the function.


for  gcc/ChangeLog

	* tree-inline.c (tree_function_versioning): Mark a version as
        a partial copy when an alternate entry point is given, and
        when versioning a partial copy.
---
 gcc/tree-inline.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index d4aa5bed7398..df0f8cabccc1 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -5829,6 +5829,9 @@ tree_function_versioning (tree old_decl, tree new_decl,
     old_version_node->used_as_abstract_origin = true;
   DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl);
 
+  DECL_FUNCTION_PARTIAL_COPY (new_decl) = new_entry
+    || DECL_FUNCTION_PARTIAL_COPY (old_decl);
+
   /* Prepare the data structures for the tree copy.  */
   memset (&id, 0, sizeof (id));
 


debug info: partial noentry functions: omp split-out blocks

We emit some OMP blocks as separate functions that are nested in, but
not otherwise related with the function they were originally part of.

This patch makes such newly-created artificial functions refer back to
the original function as their abstract origin, but as partial copies,
so that they're not mistaken as the whole function.

This enables line numbers in the split-out block to still be
recognized as part of the original function.

It may, however, cause debug information consumers that do not support
the partial copy attribute to mistake the nested functions as the
whole function.


for  gcc/ChangeLog

	* omp-low.c (create_omp_child_function): Mark newly-created
        function as a partial copy of the original one.  Mark the
        original function's cgraph node as used as abstract origin.
---
 gcc/omp-low.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 33e633cd627b..40166f9bfb3a 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1633,6 +1633,10 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
     = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
   DECL_FUNCTION_VERSIONED (decl)
     = DECL_FUNCTION_VERSIONED (current_function_decl);
+  DECL_FUNCTION_PARTIAL_COPY (decl) = 1;
+  DECL_ABSTRACT_ORIGIN (decl) = DECL_ORIGIN (current_function_decl);
+  if (DECL_ORIGIN (current_function_decl) == current_function_decl)
+    cgraph_node::get_create (current_function_decl)->used_as_abstract_origin = true;
 
   if (omp_maybe_offloaded_ctx (ctx))
     {


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


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