public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [debug-early] reuse variable DIEs and fix their context
@ 2014-08-27  2:43 Aldy Hernandez
  2014-08-28 13:58 ` Richard Biener
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-08-27  2:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 646 bytes --]

This patch fixes a bunch of guality failures.  With it I get 144 
guality.exp failures vs. 163 for "make check-gcc 
RUNTESTFLAGS=guality.exp".  A lot better than 100% fail rate ;-).

Variable DIEs were not being reused.  Instead, variable DIEs even had 
the wrong context (unilaterally the compilation unit).  The attached 
patch reuses variable DIEs that have been outputted earlier.  It also 
fixes the context by correcting the context on the second round.

I have also added a bit field to the DIE structure to record if a DIE 
has been generated early.

Again, this is all a rough draft, but feel free to comment.

Committed to branch.
Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 9548 bytes --]

commit 71d99991672200b6bcfe258ae0bfe92ea59af3ea
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Tue Aug 26 19:12:17 2014 -0700

    	* dwarf2out.c (struct die_struct): Add dumped_early field.
    	(reparent_child): New.
    	(splice_child_die): Use reparent_child.
    	(gen_subprogram_die): Do not regenerate parameters if previously
    	dumped.
    	(gen_variable_die): Fix parent of decls that have been dumped
    	early to reflect correct context.
    	Do not regenerate decls if previously dumped.
    	(dwarf2out_decl): Add return value.
    	(dwarf2out_early_decl): Set dumped_early bit.

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0aa4456..32c17ce 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -102,7 +102,7 @@ along with GCC; see the file COPYING3.  If not see
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
 static rtx_insn *last_var_location_insn;
 static rtx_insn *cached_next_real_insn;
-static void dwarf2out_decl (tree);
+static dw_die_ref dwarf2out_decl (tree);
 
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
@@ -2608,6 +2608,8 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
   /* Die is used and must not be pruned as unused.  */
   BOOL_BITFIELD die_perennial_p : 1;
   BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
+  /* Die was generated early via dwarf2out_early_decl.  */
+  BOOL_BITFIELD dumped_early : 1;
   /* Lots of spare bits.  */
 }
 die_node;
@@ -4808,6 +4810,21 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
   die->die_child = child_die;
 }
 
+/* Unassociate CHILD from its parent, and make its parent be
+   NEW_PARENT.  */
+
+static void
+reparent_child (dw_die_ref child, dw_die_ref new_parent)
+{
+  for (dw_die_ref p = child->die_parent->die_child; ; p = p->die_sib)
+    if (p->die_sib == child)
+      {
+	remove_child_with_prev (child, p);
+	break;
+      }
+  add_child_die (new_parent, child);
+}
+
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
    is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
@@ -4815,8 +4832,6 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 static void
 splice_child_die (dw_die_ref parent, dw_die_ref 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)
@@ -4831,14 +4846,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
 	      || (child->die_parent
 		  == get_AT_ref (parent, DW_AT_specification)));
 
-  for (p = child->die_parent->die_child; ; p = p->die_sib)
-    if (p->die_sib == child)
-      {
-	remove_child_with_prev (child, p);
-	break;
-      }
-
-  add_child_die (parent, child);
+  reparent_child (child, parent);
 }
 
 /* Return a pointer to a newly created DIE node.  */
@@ -18288,16 +18296,17 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 	  /* ??? Hmmm, early dwarf generation happened earlier, so no
 	     sense in removing the parameters.  Let's keep them and
 	     augment them with location information later.  */
-#if 0
-	  /* Clear out the declaration attribute and the formal parameters.
-	     Do not remove all children, because it is possible that this
-	     declaration die was forced using force_decl_die(). In such
-	     cases die that forced declaration die (e.g. TAG_imported_module)
-	     is one of the children that we do not want to remove.  */
-	  remove_AT (subr_die, DW_AT_declaration);
-	  remove_AT (subr_die, DW_AT_object_pointer);
-	  remove_child_TAG (subr_die, DW_TAG_formal_parameter);
-#endif
+	  if (!old_die->dumped_early)
+	    {
+	      /* Clear out the declaration attribute and the formal parameters.
+		 Do not remove all children, because it is possible that this
+		 declaration die was forced using force_decl_die(). In such
+		 cases die that forced declaration die (e.g. TAG_imported_module)
+		 is one of the children that we do not want to remove.  */
+	      remove_AT (subr_die, DW_AT_declaration);
+	      remove_AT (subr_die, DW_AT_object_pointer);
+	      remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+	    }
 	}
       else
 	{
@@ -18998,6 +19007,18 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (old_die && !declaration && !local_scope_p (context_die))
     return;
 
+  /* When DIEs are created early, the context is the compilation unit.
+     Adjust the context when we know what it is the second time
+     around.  */
+  if (old_die && old_die->dumped_early)
+    {
+      if (old_die->die_parent != context_die)
+	reparent_child (old_die, context_die);
+      var_die = old_die;
+      old_die = NULL;
+      goto gen_variable_die_location;
+    }
+
   /* For static data members, the declaration in the class is supposed
      to have DW_TAG_member tag; the specification should still be
      DW_TAG_variable referencing the DW_TAG_member DIE.  */
@@ -19081,6 +19102,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (decl && (DECL_ABSTRACT (decl) || declaration || old_die == NULL))
     equate_decl_number_to_die (decl, var_die);
 
+ gen_variable_die_location:
   if (! declaration
       && (! DECL_ABSTRACT (decl_or_origin)
 	  /* Local static vars are shared between all clones/inlines,
@@ -20988,9 +21010,9 @@ gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls)
 }
 
 
-/* Write the debugging output for DECL.  */
+/* Write the debugging output for DECL and return the DIE.  */
 
-static void
+static dw_die_ref
 dwarf2out_decl (tree decl)
 {
   dw_die_ref context_die = comp_unit_die ();
@@ -20998,7 +21020,7 @@ dwarf2out_decl (tree decl)
   switch (TREE_CODE (decl))
     {
     case ERROR_MARK:
-      return;
+      return NULL;
 
     case FUNCTION_DECL:
       /* What we would really like to do here is to filter out all mere
@@ -21035,7 +21057,7 @@ dwarf2out_decl (tree decl)
 	 or not at all.  */
       if (DECL_INITIAL (decl) == NULL_TREE
 	  && ! DECL_ABSTRACT (decl))
-	return;
+	return NULL;
 
       /* If we're a nested function, initially use a parent of NULL; if we're
 	 a plain function, this will be fixed up in decls_for_scope.  If
@@ -21056,7 +21078,7 @@ dwarf2out_decl (tree decl)
 	 would screw-up the debugger's name lookup mechanism and cause it to
 	 miss things which really ought to be in scope at a given point.  */
       if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
-	return;
+	return NULL;
 
       /* For local statics lookup proper context die.  */
       if (TREE_STATIC (decl)
@@ -21067,14 +21089,14 @@ dwarf2out_decl (tree decl)
       /* If we are in terse mode, don't generate any DIEs to represent any
 	 variable declarations or definitions.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-	return;
+	return NULL;
       break;
 
     case CONST_DECL:
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-	return;
+	return NULL;
       if (!is_fortran () && !is_ada ())
-	return;
+	return NULL;
       if (TREE_STATIC (decl) && decl_function_context (decl))
 	context_die = lookup_decl_die (DECL_CONTEXT (decl));
       break;
@@ -21082,24 +21104,24 @@ dwarf2out_decl (tree decl)
     case NAMESPACE_DECL:
     case IMPORTED_DECL:
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-	return;
+	return NULL;
       if (lookup_decl_die (decl) != NULL)
-	return;
+	return NULL;
       break;
 
     case TYPE_DECL:
       /* Don't emit stubs for types unless they are needed by other DIEs.  */
       if (TYPE_DECL_SUPPRESS_DEBUG (decl))
-	return;
+	return NULL;
 
       /* Don't bother trying to generate any DIEs to represent any of the
 	 normal built-in types for the language we are compiling.  */
       if (DECL_IS_BUILTIN (decl))
-	return;
+	return NULL;
 
       /* If we are in terse mode, don't generate any DIEs for types.  */
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-	return;
+	return NULL;
 
       /* If we're a function-scope tag, initially use a parent of NULL;
 	 this will be fixed up in decls_for_scope.  */
@@ -21112,7 +21134,7 @@ dwarf2out_decl (tree decl)
       break;
 
     default:
-      return;
+      return NULL;
     }
 
   gen_decl_die (decl, NULL, context_die);
@@ -21120,6 +21142,7 @@ dwarf2out_decl (tree decl)
   dw_die_ref die = lookup_decl_die (decl);
   if (die)
     check_die (die, 0);
+  return die;
 }
 
 /* Early dumping of DECLs before we lose language data.  */
@@ -21135,8 +21158,8 @@ dwarf2out_early_decl (tree decl)
      cgraph information, causing cgraph_function_possibly_inlined_p()
      to return true.  Trick cgraph_function_possibly_inlined_p()
      while we generate dwarf early.  */
-  bool save = cgraph_global_info_ready;
-  cgraph_global_info_ready = true;
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
 
   /* We don't handle TYPE_DECLs.  If required, they'll be reached via
      other DECLs and they can point to template types or other things
@@ -21154,7 +21177,9 @@ dwarf2out_early_decl (tree decl)
 	  push_cfun (DECL_STRUCT_FUNCTION (decl));
 	  current_function_decl = decl;
 	}
-      dwarf2out_decl (decl);
+      dw_die_ref die = dwarf2out_decl (decl);
+      if (die)
+	die->dumped_early = true;
       if (TREE_CODE (decl) == FUNCTION_DECL)
 	{
 	  pop_cfun ();
@@ -21162,7 +21187,7 @@ dwarf2out_early_decl (tree decl)
 	}
     }
  early_decl_exit:
-  cgraph_global_info_ready = save;
+  symtab->global_info_ready = save;
   return;
 }
 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-27  2:43 [debug-early] reuse variable DIEs and fix their context Aldy Hernandez
@ 2014-08-28 13:58 ` Richard Biener
  2014-08-28 17:35   ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-08-28 13:58 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches

On Wed, Aug 27, 2014 at 4:42 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> This patch fixes a bunch of guality failures.  With it I get 144 guality.exp
> failures vs. 163 for "make check-gcc RUNTESTFLAGS=guality.exp".  A lot
> better than 100% fail rate ;-).
>
> Variable DIEs were not being reused.  Instead, variable DIEs even had the
> wrong context (unilaterally the compilation unit).  The attached patch
> reuses variable DIEs that have been outputted earlier.  It also fixes the
> context by correcting the context on the second round.
>
> I have also added a bit field to the DIE structure to record if a DIE has
> been generated early.
>
> Again, this is all a rough draft, but feel free to comment.

I wonder if we can't not force a proper context die (ISTR dwarf2out.c
lazily handles some contexts in some circumstances).  All parent
"trees" should be readily available and we should be able to create
DIEs for them.

Richard.

> Committed to branch.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 13:58 ` Richard Biener
@ 2014-08-28 17:35   ` Aldy Hernandez
  2014-08-28 18:01     ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-08-28 17:35 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, jason merrill

On 08/28/14 06:58, Richard Biener wrote:
> On Wed, Aug 27, 2014 at 4:42 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>> This patch fixes a bunch of guality failures.  With it I get 144 guality.exp
>> failures vs. 163 for "make check-gcc RUNTESTFLAGS=guality.exp".  A lot
>> better than 100% fail rate ;-).
>>
>> Variable DIEs were not being reused.  Instead, variable DIEs even had the
>> wrong context (unilaterally the compilation unit).  The attached patch
>> reuses variable DIEs that have been outputted earlier.  It also fixes the
>> context by correcting the context on the second round.
>>
>> I have also added a bit field to the DIE structure to record if a DIE has
>> been generated early.
>>
>> Again, this is all a rough draft, but feel free to comment.
>
> I wonder if we can't not force a proper context die (ISTR dwarf2out.c
> lazily handles some contexts in some circumstances).  All parent

Hmmm, I don't see any of this lazy context setting you speak of, but...

> "trees" should be readily available and we should be able to create
> DIEs for them.

I wonder if instead of early dumping of all the DECLs, we could only 
dump the toplevel scoped DECLs, and let inheritance set the proper contexts.

We could start with calling dwarf2out_early_decl() for each function 
decl, and then for every global.  This is analogous to what we currently 
do for late dwarf2out.

see final.c for the functions:
       if (!DECL_IGNORED_P (current_function_decl))
         debug_hooks->function_decl (current_function_decl);

see c/c-decl.c for the globals:
       FOR_EACH_VEC_ELT (*all_translation_units, i, t)
	c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
       c_write_global_declarations_2 (BLOCK_VARS (ext_block));

The problem being that to calculate `ext_block' above, we need intimate 
knowledge of scopes and such, only available in the FE.  Is there a 
generic way of determining if a DECL is in global scope?  If, so we 
could do:

	foreach decl in fld.decls
		if (is_global_scope(decl))
			dwarf2out_decl (decl)

...and contexts will magically be set.

Is there such a way, or am I going about this the wrong way?

Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 17:35   ` Aldy Hernandez
@ 2014-08-28 18:01     ` Jason Merrill
  2014-08-28 19:13       ` Richard Biener
  2014-09-03 17:55       ` Aldy Hernandez
  0 siblings, 2 replies; 40+ messages in thread
From: Jason Merrill @ 2014-08-28 18:01 UTC (permalink / raw)
  To: Aldy Hernandez, Richard Biener; +Cc: gcc-patches

On 08/28/2014 01:34 PM, Aldy Hernandez wrote:
> I wonder if instead of early dumping of all the DECLs, we could only
> dump the toplevel scoped DECLs, and let inheritance set the proper
> contexts.

Yes, I think this makes a lot more sense; do it at a well-defined point 
in compilation rather than as part of free_lang_data.

> We could start with calling dwarf2out_early_decl() for each function
> decl, and then for every global.  This is analogous to what we currently
> do for late dwarf2out.
>
> see final.c for the functions:
>        if (!DECL_IGNORED_P (current_function_decl))
>          debug_hooks->function_decl (current_function_decl);
>
> see c/c-decl.c for the globals:
>        FOR_EACH_VEC_ELT (*all_translation_units, i, t)
>      c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
>        c_write_global_declarations_2 (BLOCK_VARS (ext_block));

> The problem being that to calculate `ext_block' above, we need intimate
> knowledge of scopes and such, only available in the FE.  Is there a
> generic way of determining if a DECL is in global scope?

Why not do it in the FE, i.e. *_write_global_declarations?

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 18:01     ` Jason Merrill
@ 2014-08-28 19:13       ` Richard Biener
  2014-08-28 20:14         ` Jason Merrill
  2014-09-03 17:55       ` Aldy Hernandez
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-08-28 19:13 UTC (permalink / raw)
  To: Jason Merrill, Aldy Hernandez; +Cc: gcc-patches

On August 28, 2014 8:01:05 PM CEST, Jason Merrill <jason@redhat.com> wrote:
>On 08/28/2014 01:34 PM, Aldy Hernandez wrote:
>> I wonder if instead of early dumping of all the DECLs, we could only
>> dump the toplevel scoped DECLs, and let inheritance set the proper
>> contexts.
>
>Yes, I think this makes a lot more sense; do it at a well-defined point
>
>in compilation rather than as part of free_lang_data.
>
>> We could start with calling dwarf2out_early_decl() for each function
>> decl, and then for every global.  This is analogous to what we
>currently
>> do for late dwarf2out.
>>
>> see final.c for the functions:
>>        if (!DECL_IGNORED_P (current_function_decl))
>>          debug_hooks->function_decl (current_function_decl);
>>
>> see c/c-decl.c for the globals:
>>        FOR_EACH_VEC_ELT (*all_translation_units, i, t)
>>      c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
>>        c_write_global_declarations_2 (BLOCK_VARS (ext_block));
>
>> The problem being that to calculate `ext_block' above, we need
>intimate
>> knowledge of scopes and such, only available in the FE.  Is there a
>> generic way of determining if a DECL is in global scope?

Via DECL_CONTEXT and the global scope macro predicate.  Eventually not enough to detect class scope statics.

>Why not do it in the FE, i.e. *_write_global_declarations?

Yeah, ultimatively I'd like the front ends to do all required dwarf2out calls but free lang data seemed a convenient place to do things.

There is no reason we can't walk its array in a more sensible order.

Richard.
>
>Jason


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 19:13       ` Richard Biener
@ 2014-08-28 20:14         ` Jason Merrill
  2014-08-29  9:09           ` Richard Biener
  0 siblings, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2014-08-28 20:14 UTC (permalink / raw)
  To: Richard Biener, Aldy Hernandez; +Cc: gcc-patches

On 08/28/2014 03:13 PM, Richard Biener wrote:
>>> knowledge of scopes and such, only available in the FE.  Is there a
>>> generic way of determining if a DECL is in global scope?
>
> Via DECL_CONTEXT and the global scope macro predicate.  Eventually not enough to detect class scope statics.

!decl_function_context should do the trick.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 20:14         ` Jason Merrill
@ 2014-08-29  9:09           ` Richard Biener
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Biener @ 2014-08-29  9:09 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Aldy Hernandez, gcc-patches

On Thu, Aug 28, 2014 at 10:14 PM, Jason Merrill <jason@redhat.com> wrote:
> On 08/28/2014 03:13 PM, Richard Biener wrote:
>>>>
>>>> knowledge of scopes and such, only available in the FE.  Is there a
>>>> generic way of determining if a DECL is in global scope?
>>
>>
>> Via DECL_CONTEXT and the global scope macro predicate.  Eventually not
>> enough to detect class scope statics.
>
>
> !decl_function_context should do the trick.

Yeah, that might work.  But I suppose we want proper ordering even
for a namespace hierarchy, that is, output dwarf for the namespace
which will output its siblings.

That is, dwarf2out.c currently kind-of supports both, first create
DIEs for the context which will usually create DIEs for its siblings
or first create siblings which will either end up in the limbo-list
or get a context DIE via force_decl/type_die (see get_context_die).

IMHO the best would be to create DIEs top-down controlled
by frontends and also populate context DIEs from the frontends
and not by walking some sibling list from dwarf2out.c.

Frontends already "announce" some types/decls to dwarf2out.c
by means of calling rest_of_decl_compilation or rest_of_type_compilation
(only for TYPE_DECLs).  So it's mostly a matter of adding similar calls
for scopes and global decls.  The calls should be debug_hook calls
of course, not these weird rest_of_*_compilation stuff.

Richard.

> Jason
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-08-28 18:01     ` Jason Merrill
  2014-08-28 19:13       ` Richard Biener
@ 2014-09-03 17:55       ` Aldy Hernandez
  2014-09-04 10:42         ` Richard Biener
  2014-09-04 17:53         ` H.J. Lu
  1 sibling, 2 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-03 17:55 UTC (permalink / raw)
  To: Jason Merrill, Richard Biener; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1946 bytes --]

[Jason, Richard]: Is it useful for my patches to contain ChangeLog 
entries?  I find them mildly annoying for something that will inevitably 
be rewritten multiple times, but if it aids in reviewing my WIP, I am 
more than happy to continue including them.

On 08/28/14 11:01, Jason Merrill wrote:
> On 08/28/2014 01:34 PM, Aldy Hernandez wrote:
>> I wonder if instead of early dumping of all the DECLs, we could only
>> dump the toplevel scoped DECLs, and let inheritance set the proper
>> contexts.
>
> Yes, I think this makes a lot more sense; do it at a well-defined point
> in compilation rather than as part of free_lang_data.

Great.  It turned out, this was a cleaner approach as well.

>> The problem being that to calculate `ext_block' above, we need intimate
>> knowledge of scopes and such, only available in the FE.  Is there a
>> generic way of determining if a DECL is in global scope?
>
> Why not do it in the FE, i.e. *_write_global_declarations?

This is what I've done in this patch.

I'm no longer generating dwarf early from free_lang_data, instead I'm 
using the global_decl debug hook and adding an EARLY argument.  Then I 
call it twice, once after the FE is done, and once after the full 
compilation has finished (cgraph has been generated, etc).  The goal is 
to have the first pass generate the DIEs and the 2nd pass fill in 
location information and such.

Generating the globals first solves the context issue.  The recursive 
nature of generating DIEs gets everything right.  For that matter,
with the attached patch, I actually get *LESS* guality failures than 
before.  Unexpected, but I'm not going to complain ;-).

I have added a few (temporary) checks to make sure we're not 
regenerating DIEs when we already have one (at least for DECLs).  These 
should go away after this work is incorporated into mainline.

FYI, I am only handling C for now while we iron out the general idea.

How does this look?

Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 14177 bytes --]

diff --git a/gcc/ChangeLog.debug-early b/gcc/ChangeLog.debug-early
index df571a4..980b655 100644
--- a/gcc/ChangeLog.debug-early
+++ b/gcc/ChangeLog.debug-early
@@ -1,3 +1,31 @@
+2014-09-03  Aldy Hernandez  <aldyh@redhat.com>
+
+	* c/c-decl.c (write_global_declarations_1): Call global_decl()
+	with early=true.
+	(write_global_declarations_2): Call global_decl() with
+	early=false.
+	* dbxout.c (dbxout_global_decl): New argument.
+	* debug.c (do_nothing_debug_hooks): Use debug_nothing_tree_bool
+	for global_decl hook.
+	(debug_nothing_tree_bool): New.
+	(struct gcc_debug_hooks): New argument to global_decl.
+	* dwarf2out.c (output_die): Add misc debugging information.
+	(gen_variable_die): Do not reparent children.
+	(dwarf2out_global_decl): Add new documentation.  Add EARLY
+	argument.
+	(dwarf2out_decl): Make sure we don't generate new DIEs if we
+	already have a DIE.
+	* cp/name-lookup.c (do_namespace_alias): New argument to
+	global_decl debug hook.
+	* fortran/trans-decl.c (gfc_emit_parameter_debug_info): Same.
+	* godump.c (go_global_decl): Same.
+	* lto/lto-lang.c (lto_write_globals): Same.
+	* sdbout.c (sdbout_global_decl): Same.
+	* toplev.c (emit_debug_global_declarations): Same.
+	* vmsdbgout.c (vmsdbgout_global_decl): Same.
+	* tree.c (free_lang_data_in_decl): Do not call
+	dwarf2out_early_decl from here.
+
 2014-08-26  Aldy Hernandez  <aldyh@redhat.com>
 
 	* dwarf2out.c (struct die_struct): Add dumped_early field.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index b4995a6..1e09404 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10308,7 +10308,10 @@ c_write_global_declarations_1 (tree globals)
   while (reconsider);
 
   for (decl = globals; decl; decl = DECL_CHAIN (decl))
-    check_global_declaration_1 (decl);
+    {
+      check_global_declaration_1 (decl);
+      debug_hooks->global_decl (decl, /*early=*/true);
+    }
 }
 
 /* A subroutine of c_write_global_declarations Emit debug information for each
@@ -10320,7 +10323,7 @@ c_write_global_declarations_2 (tree globals)
   tree decl;
 
   for (decl = globals; decl ; decl = DECL_CHAIN (decl))
-    debug_hooks->global_decl (decl);
+    debug_hooks->global_decl (decl, /*early=*/false);
 }
 
 /* Callback to collect a source_ref from a DECL.  */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ebcbb5c..45b3b99 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3859,7 +3859,7 @@ do_namespace_alias (tree alias, tree name_space)
 
   /* Emit debug info for namespace alias.  */
   if (!building_stmt_list_p ())
-    (*debug_hooks->global_decl) (alias);
+    (*debug_hooks->global_decl) (alias, /*early=*/false);
 }
 
 /* Like pushdecl, only it places X in the current namespace,
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index d856bdd..208cec9 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -325,7 +325,7 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
 static void dbxout_common_name (tree, const char *, stab_code_type);
 static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree);
+static void dbxout_global_decl (tree, bool);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void debug_free_queue (void);
@@ -1320,7 +1320,7 @@ dbxout_function_decl (tree decl)
 /* Debug information for a global DECL.  Called from toplev.c after
    compilation proper has finished.  */
 static void
-dbxout_global_decl (tree decl)
+dbxout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
diff --git a/gcc/debug.c b/gcc/debug.c
index dba068c..b5818de 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -43,7 +43,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_tree,		         /* begin_function */
   debug_nothing_int,		         /* end_function */
   debug_nothing_tree,		         /* function_decl */
-  debug_nothing_tree,		         /* global_decl */
+  debug_nothing_tree_bool,	         /* global_decl */
   debug_nothing_tree_int,		 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -71,6 +71,12 @@ debug_nothing_tree (tree decl ATTRIBUTE_UNUSED)
 }
 
 void
+debug_nothing_tree_bool (tree decl ATTRIBUTE_UNUSED,
+			 bool early ATTRIBUTE_UNUSED)
+{
+}
+
+void
 debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED,
 			 tree t2 ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/debug.h b/gcc/debug.h
index 28bc210..e89a9e8 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -93,8 +93,11 @@ struct gcc_debug_hooks
   void (* function_decl) (tree decl);
 
   /* Debug information for a global DECL.  Called from toplev.c after
-     compilation proper has finished.  */
-  void (* global_decl) (tree decl);
+     compilation proper has finished.  EARLY is true if global_decl()
+     is being called early on in the compilation process (i.e., before
+     cgraph information is available and before full location
+     information is available).  */
+  void (* global_decl) (tree decl, bool early);
 
   /* Debug information for a type DECL.  Called from toplev.c after
      compilation proper, also from various language front ends to
@@ -156,6 +159,7 @@ extern void debug_nothing_int_charstar_int_bool (unsigned int, const char *,
 extern void debug_nothing_int (unsigned int);
 extern void debug_nothing_int_int (unsigned int, unsigned int);
 extern void debug_nothing_tree (tree);
+extern void debug_nothing_tree_bool (tree, bool);
 extern void debug_nothing_tree_tree (tree, tree);
 extern void debug_nothing_tree_int (tree, int);
 extern void debug_nothing_tree_tree_tree_bool (tree, tree, tree, bool);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5859228..b577757 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2430,7 +2430,7 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree);
+static void dwarf2out_global_decl (tree, bool);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
@@ -8711,10 +8711,11 @@ output_die (dw_die_ref die)
   if (! die->comdat_type_p && die->die_id.die_symbol)
     output_die_symbol (die);
 
-  dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s (parent DIE=%#lx))",
+  dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s (parent DIE=%#lx) early=%d)",
 			       (unsigned long)die->die_offset,
 			       dwarf_tag_name (die->die_tag),
-			       die->die_parent ? die->die_parent->die_offset : 0);
+			       die->die_parent ? die->die_parent->die_offset : 0,
+			       die->dumped_early);
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     {
@@ -19009,13 +19010,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (old_die && !declaration && !local_scope_p (context_die))
     return;
 
-  /* When DIEs are created early, the context is the compilation unit.
-     Adjust the context when we know what it is the second time
-     around.  */
+  /* If a DIE was dumped early, it still needs location info.  Skip to
+     the part where we fill the location bits.  */
   if (old_die && old_die->dumped_early)
     {
-      if (old_die->die_parent != context_die)
-	reparent_child (old_die, context_die);
+      gcc_assert (old_die->die_parent == context_die);
       var_die = old_die;
       old_die = NULL;
       goto gen_variable_die_location;
@@ -20818,12 +20817,29 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from toplev.c after
-   compilation proper has finished.  */
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.
+
+   dwarf2out_decl() will be called twice on each global symbol: once
+   immediately after parsing (EARLY=true), and once after the full
+   compilation has finished (EARLY=false).  There are checks in
+   dwarf2out_decl() to make sure that if we have a DECL DIE upon
+   entry, that the previously created DIE is reused.  No new DECL DIEs
+   should be created when EARLY=false.
+
+   The second time dwarf2out_decl() is called (or for that matter, the
+   second time any DECL DIE is seen throughout dwarf2out), only
+   information not previously available (e.g. location) is tacked onto
+   the early dumped DIE.  That's the plan anyhow ;-).  */
 
 static void
-dwarf2out_global_decl (tree decl)
+dwarf2out_global_decl (tree decl, bool early)
 {
+  if (early)
+    {
+      dwarf2out_early_decl (decl);
+      return;
+    }
   /* Output DWARF2 information for file-scope tentative data object
      declarations, file-scope (extern) function declarations (which
      had no corresponding body) and file-scope tagged type declarations
@@ -21019,6 +21035,19 @@ dwarf2out_decl (tree decl)
 {
   dw_die_ref context_die = comp_unit_die ();
 
+#ifdef ENABLE_CHECKING
+  /* Save some info so we can later determine if we erroneously
+     created a DIE for something we had already created a DIE for.
+     We should always be reusing DIEs created early.  */
+  dw_die_ref early_die = NULL;
+  if (decl_die_table)
+    {
+      early_die = lookup_decl_die (decl);
+      if (early_die && !early_die->dumped_early)
+	early_die = NULL;
+    }
+#endif
+
   switch (TREE_CODE (decl))
     {
     case ERROR_MARK:
@@ -21144,6 +21173,11 @@ dwarf2out_decl (tree decl)
   dw_die_ref die = lookup_decl_die (decl);
   if (die)
     check_die (die, 0);
+#ifdef ENABLE_CHECKING
+  /* If we early created a DIE, make sure it didn't get re-created by
+     mistake.  */
+  gcc_assert (!early_die || early_die == die);
+#endif
   return die;
 }
 
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 6afa6f3..38e6f99 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4693,7 +4693,7 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym)
 					      TREE_TYPE (decl),
 					      sym->attr.dimension,
 					      false, false);
-  debug_hooks->global_decl (decl);
+  debug_hooks->global_decl (decl, /*early=*/false);
 }
 
 
diff --git a/gcc/godump.c b/gcc/godump.c
index 7566f4d..01f8410 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -496,9 +496,9 @@ go_function_decl (tree decl)
 /* A global variable decl.  */
 
 static void
-go_global_decl (tree decl)
+go_global_decl (tree decl, bool early)
 {
-  real_debug_hooks->global_decl (decl);
+  real_debug_hooks->global_decl (decl, early);
   go_decl (decl);
 }
 
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 9e8524a..1f39949 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1093,7 +1093,7 @@ lto_write_globals (void)
   varpool_node *vnode;
   FOR_EACH_DEFINED_VARIABLE (vnode)
     if (!decl_function_context (vnode->decl))
-      debug_hooks->global_decl (vnode->decl);
+      debug_hooks->global_decl (vnode->decl, /*early=*/false);
 }
 
 static tree
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index 7b6f457..d81b184 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -119,7 +119,7 @@ static void sdbout_begin_block		(unsigned int, unsigned int);
 static void sdbout_end_block		(unsigned int, unsigned int);
 static void sdbout_source_line		(unsigned int, const char *, int, bool);
 static void sdbout_end_epilogue		(unsigned int, const char *);
-static void sdbout_global_decl		(tree);
+static void sdbout_global_decl		(tree, bool);
 static void sdbout_begin_prologue	(unsigned int, const char *);
 static void sdbout_end_prologue		(unsigned int, const char *);
 static void sdbout_begin_function	(tree);
@@ -142,7 +142,6 @@ static void sdbout_field_types		(tree);
 static void sdbout_one_type		(tree);
 static void sdbout_parms		(tree);
 static void sdbout_reg_parms		(tree);
-static void sdbout_global_decl		(tree);
 
 /* Random macros describing parts of SDB data.  */
 
@@ -1422,7 +1421,7 @@ sdbout_reg_parms (tree parms)
    after compilation proper has finished.  */
 
 static void
-sdbout_global_decl (tree decl)
+sdbout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (decl) == VAR_DECL
       && !DECL_EXTERNAL (decl)
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 492a7ef..ceefa1b 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -532,7 +532,7 @@ emit_debug_global_declarations (tree *vec, int len)
 
   timevar_push (TV_SYMOUT);
   for (i = 0; i < len; i++)
-    debug_hooks->global_decl (vec[i]);
+    debug_hooks->global_decl (vec[i], /*early=*/false);
   timevar_pop (TV_SYMOUT);
 }
 
diff --git a/gcc/tree.c b/gcc/tree.c
index afc8e3d..8e9876e 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5032,10 +5032,6 @@ free_lang_data_in_decl (tree decl)
 {
   gcc_assert (DECL_P (decl));
 
-  /* Early dumping of DECLs before we lose language data.  */
-  if (debug_info_level > DINFO_LEVEL_NONE)
-    dwarf2out_early_decl (decl);
-
   /* Give the FE a chance to remove its own data first.  */
   lang_hooks.free_lang_data (decl);
 
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 463a418..2ad9e9b 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -163,7 +163,7 @@ static void vmsdbgout_begin_epilogue (unsigned int, const char *);
 static void vmsdbgout_end_epilogue (unsigned int, const char *);
 static void vmsdbgout_begin_function (tree);
 static void vmsdbgout_decl (tree);
-static void vmsdbgout_global_decl (tree);
+static void vmsdbgout_global_decl (tree, bool);
 static void vmsdbgout_type_decl (tree, int);
 static void vmsdbgout_abstract_function (tree);
 
@@ -1510,10 +1510,10 @@ vmsdbgout_decl (tree decl)
 /* Not implemented in VMS Debug.  */
 
 static void
-vmsdbgout_global_decl (tree decl)
+vmsdbgout_global_decl (tree decl, bool early)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
-    (*dwarf2_debug_hooks.global_decl) (decl);
+    (*dwarf2_debug_hooks.global_decl) (decl, early);
 }
 
 /* Not implemented in VMS Debug.  */

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-03 17:55       ` Aldy Hernandez
@ 2014-09-04 10:42         ` Richard Biener
  2014-09-05  2:38           ` Aldy Hernandez
  2014-09-04 17:53         ` H.J. Lu
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-09-04 10:42 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches

On Wed, Sep 3, 2014 at 7:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> [Jason, Richard]: Is it useful for my patches to contain ChangeLog entries?
> I find them mildly annoying for something that will inevitably be rewritten
> multiple times, but if it aids in reviewing my WIP, I am more than happy to
> continue including them.

I think they are useful in the sense that they make you review your
patches youself ;)  That's how I treat it with match-and-simplify
where the final trunk commit will just say * foo.c: New. in most
cases ;)

>
> On 08/28/14 11:01, Jason Merrill wrote:
>>
>> On 08/28/2014 01:34 PM, Aldy Hernandez wrote:
>>>
>>> I wonder if instead of early dumping of all the DECLs, we could only
>>> dump the toplevel scoped DECLs, and let inheritance set the proper
>>> contexts.
>>
>>
>> Yes, I think this makes a lot more sense; do it at a well-defined point
>> in compilation rather than as part of free_lang_data.
>
>
> Great.  It turned out, this was a cleaner approach as well.
>
>
>>> The problem being that to calculate `ext_block' above, we need intimate
>>> knowledge of scopes and such, only available in the FE.  Is there a
>>> generic way of determining if a DECL is in global scope?
>>
>>
>> Why not do it in the FE, i.e. *_write_global_declarations?
>
>
> This is what I've done in this patch.

Fine.  Of course FEs may choose to emit debug info even earlier
before the whole unit is parsed.

Flow-wise I still want to move hand-off to the cgraph code to toplev.c,
out from the FEs final_write_gloabals hook:

  /* This must also call finalize_compilation_unit.  */
  lang_hooks.decls.final_write_globals ();

that would make clearer how control flows.

> I'm no longer generating dwarf early from free_lang_data, instead I'm using
> the global_decl debug hook and adding an EARLY argument.  Then I call it
> twice, once after the FE is done, and once after the full compilation has
> finished (cgraph has been generated, etc).  The goal is to have the first
> pass generate the DIEs and the 2nd pass fill in location information and
> such.

Sounds good (or split the hook into two).

> Generating the globals first solves the context issue.  The recursive nature
> of generating DIEs gets everything right.  For that matter,
> with the attached patch, I actually get *LESS* guality failures than before.
> Unexpected, but I'm not going to complain ;-).
>
> I have added a few (temporary) checks to make sure we're not regenerating
> DIEs when we already have one (at least for DECLs).  These should go away
> after this work is incorporated into mainline.
>
> FYI, I am only handling C for now while we iron out the general idea.
>
> How does this look?

   /* Debug information for a global DECL.  Called from toplev.c after
-     compilation proper has finished.  */
-  void (* global_decl) (tree decl);
+     compilation proper has finished.  EARLY is true if global_decl()
+     is being called early on in the compilation process (i.e., before
+     cgraph information is available and before full location
+     information is available).  */

I'd say "before code is generated" instead of "full location information is
available" (location info always sounds ambiguous to me)

+  void (* global_decl) (tree decl, bool early);

I'd also rather split the hook into two ... (and call the 2nd non-early
phase hook from where we output the code).  What does that phase
output for global decls anyway?

That is, the 2nd phase should use the cgraph/varpool iterators to
amend debug info and not need the FEs list of global vars.

Otherwise looks like a good incremental improvement to me.

Richard.

> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-03 17:55       ` Aldy Hernandez
  2014-09-04 10:42         ` Richard Biener
@ 2014-09-04 17:53         ` H.J. Lu
  2014-09-04 17:54           ` Aldy Hernandez
  1 sibling, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2014-09-04 17:53 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, Richard Biener, gcc-patches

On Wed, Sep 3, 2014 at 10:54 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> [Jason, Richard]: Is it useful for my patches to contain ChangeLog entries?
> I find them mildly annoying for something that will inevitably be rewritten
> multiple times, but if it aids in reviewing my WIP, I am more than happy to
> continue including them.
>
>
> On 08/28/14 11:01, Jason Merrill wrote:
>>
>> On 08/28/2014 01:34 PM, Aldy Hernandez wrote:
>>>
>>> I wonder if instead of early dumping of all the DECLs, we could only
>>> dump the toplevel scoped DECLs, and let inheritance set the proper
>>> contexts.
>>
>>
>> Yes, I think this makes a lot more sense; do it at a well-defined point
>> in compilation rather than as part of free_lang_data.
>
>
> Great.  It turned out, this was a cleaner approach as well.
>
>
>>> The problem being that to calculate `ext_block' above, we need intimate
>>> knowledge of scopes and such, only available in the FE.  Is there a
>>> generic way of determining if a DECL is in global scope?
>>
>>
>> Why not do it in the FE, i.e. *_write_global_declarations?
>
>
> This is what I've done in this patch.
>
> I'm no longer generating dwarf early from free_lang_data, instead I'm using
> the global_decl debug hook and adding an EARLY argument.  Then I call it
> twice, once after the FE is done, and once after the full compilation has
> finished (cgraph has been generated, etc).  The goal is to have the first
> pass generate the DIEs and the 2nd pass fill in location information and
> such.
>
> Generating the globals first solves the context issue.  The recursive nature
> of generating DIEs gets everything right.  For that matter,
> with the attached patch, I actually get *LESS* guality failures than before.
> Unexpected, but I'm not going to complain ;-).
>
> I have added a few (temporary) checks to make sure we're not regenerating
> DIEs when we already have one (at least for DECLs).  These should go away
> after this work is incorporated into mainline.
>
> FYI, I am only handling C for now while we iron out the general idea.
>
> How does this look?
>

I think this merge caused bootstrap failure on Linux/i686

https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html


-- 
H.J.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 17:53         ` H.J. Lu
@ 2014-09-04 17:54           ` Aldy Hernandez
  2014-09-04 18:23             ` Richard Biener
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-04 17:54 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Jason Merrill, Richard Biener, gcc-patches


> I think this merge caused bootstrap failure on Linux/i686
>
> https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html
>
>

I incorrectly pushed my branch onto trunk.  It's being reverted.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 17:54           ` Aldy Hernandez
@ 2014-09-04 18:23             ` Richard Biener
  2014-09-04 18:35               ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-09-04 18:23 UTC (permalink / raw)
  To: Aldy Hernandez, H.J. Lu; +Cc: Jason Merrill, gcc-patches

On September 4, 2014 7:54:14 PM CEST, Aldy Hernandez <aldyh@redhat.com> wrote:
>
>> I think this merge caused bootstrap failure on Linux/i686
>>
>> https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html
>>
>>
>
>I incorrectly pushed my branch onto trunk.  It's being reverted.

Too bad!

;)

Richard.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 18:23             ` Richard Biener
@ 2014-09-04 18:35               ` Aldy Hernandez
  2014-09-04 18:38                 ` Christophe Lyon
  2014-09-04 19:42                 ` Jan-Benedict Glaw
  0 siblings, 2 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-04 18:35 UTC (permalink / raw)
  To: Richard Biener, H.J. Lu; +Cc: Jason Merrill, gcc-patches

On 09/04/14 11:23, Richard Biener wrote:
> On September 4, 2014 7:54:14 PM CEST, Aldy Hernandez <aldyh@redhat.com> wrote:
>>
>>> I think this merge caused bootstrap failure on Linux/i686
>>>
>>> https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html
>>>
>>>
>>
>> I incorrectly pushed my branch onto trunk.  It's being reverted.
>
> Too bad!

Hey, I tried to sneak in all my changes onto trunk...but people noticed 
too fast.  It's those Ada people!  I should've added fixed the debugging 
hooks for their language :).

Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 18:35               ` Aldy Hernandez
@ 2014-09-04 18:38                 ` Christophe Lyon
  2014-09-04 19:42                 ` Jan-Benedict Glaw
  1 sibling, 0 replies; 40+ messages in thread
From: Christophe Lyon @ 2014-09-04 18:38 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Richard Biener, H.J. Lu, Jason Merrill, gcc-patches

Hi, FWIW I saw the same problem on arm* and aarch64 targets.



On 4 September 2014 20:34, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/04/14 11:23, Richard Biener wrote:
>>
>> On September 4, 2014 7:54:14 PM CEST, Aldy Hernandez <aldyh@redhat.com>
>> wrote:
>>>
>>>
>>>> I think this merge caused bootstrap failure on Linux/i686
>>>>
>>>> https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html
>>>>
>>>>
>>>
>>> I incorrectly pushed my branch onto trunk.  It's being reverted.
>>
>>
>> Too bad!
>
>
> Hey, I tried to sneak in all my changes onto trunk...but people noticed too
> fast.  It's those Ada people!  I should've added fixed the debugging hooks
> for their language :).
>
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 18:35               ` Aldy Hernandez
  2014-09-04 18:38                 ` Christophe Lyon
@ 2014-09-04 19:42                 ` Jan-Benedict Glaw
  1 sibling, 0 replies; 40+ messages in thread
From: Jan-Benedict Glaw @ 2014-09-04 19:42 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Richard Biener, H.J. Lu, Jason Merrill, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1385 bytes --]

On Thu, 2014-09-04 11:34:57 -0700, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/04/14 11:23, Richard Biener wrote:
> > On September 4, 2014 7:54:14 PM CEST, Aldy Hernandez <aldyh@redhat.com> wrote:
> > > > I think this merge caused bootstrap failure on Linux/i686
> > > > https://gcc.gnu.org/ml/gcc-regression/2014-09/msg00010.html
> > > I incorrectly pushed my branch onto trunk.  It's being reverted.
> >
> > Too bad!
> 
> Hey, I tried to sneak in all my changes onto trunk...but people
> noticed too fast.  It's those Ada people!  I should've added fixed
> the debugging hooks for their language :).

The sh4/sh64 folks would have noticed, too:

http://toolchain.lug-owl.de/buildbot/show_build_details.php?id=350741
http://toolchain.lug-owl.de/buildbot/show_build_details.php?id=350742

:)

MfG, JBG

-- 
      Jan-Benedict Glaw      jbglaw@lug-owl.de              +49-172-7608481
Signature of: 17:45 <@Eimann> Hrm, das E90 hat keinen Lebenszeit Call-Time Counter mehr
the second  : 17:46 <@jbglaw> Eimann: Wofür braucht man das?
              17:46 <@jbglaw> Eimann: Für mich ist an 'nem Handy wichtig, daß ich mein
                              Gegeüber hören kann. Und daß mein Gegenüber mich versteht...
              17:47 <@KrisK> jbglaw: was du meinst ist wodka.
              17:47 <@KrisK> jbglaw: es klingelt und man hört stimmen

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-04 10:42         ` Richard Biener
@ 2014-09-05  2:38           ` Aldy Hernandez
  2014-09-05  9:00             ` Richard Biener
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-05  2:38 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jason Merrill, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2307 bytes --]

On 09/04/14 03:42, Richard Biener wrote:
> On Wed, Sep 3, 2014 at 7:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:

> Flow-wise I still want to move hand-off to the cgraph code to toplev.c,
> out from the FEs final_write_gloabals hook:
>
>    /* This must also call finalize_compilation_unit.  */
>    lang_hooks.decls.final_write_globals ();
>
> that would make clearer how control flows.

Neat.  I like it.

> I'd also rather split the hook into two ... (and call the 2nd non-early
> phase hook from where we output the code).  What does that phase
> output for global decls anyway?

This is also a very good idea, and it makes the intent clearer.

> Otherwise looks like a good incremental improvement to me.

Since we're pretty much on the same page, I've committed this revision 
you just looked at, so we can talk about the changes you mention above 
separately, namely:

a) Divorcing final_write_globals and finalize_compilation.
b) Splitting the global_decl hook into two.

So this is what I have in mind (patch attached).  I'd like to split
LANG_HOOKS_WRITE_GLOBALS in favor of 
LANG_HOOKS_{EARLY,LATE}_WRITE_GLOBALS, as well as splitting the 
global_decl debug hook into {early,late}_global_decl.  I've commented 
things throughout to make it very clear what we're getting at.

I chose to dispense with the old names to make it very clear what the 
hook should do, and to make sure I didn't miss any places.

Toplev will now look much cleaner:

+  /* Emit early debugging information as well as globals.  */
+  timevar_start (TV_PHASE_DEFERRED);
+  lang_hooks.decls.early_write_globals ();
+  timevar_stop (TV_PHASE_DEFERRED);
+
+  /* We're done parsing; proceed to optimize and emit assembly.  */
+  timevar_start (TV_PHASE_OPT_GEN);
+  symtab->finalize_compilation_unit ();
+  timevar_stop (TV_PHASE_OPT_GEN);
+
+  /* Amend any debugging information generated previously.  */
+  timevar_start (TV_PHASE_DBGINFO);
+  lang_hooks.decls.late_write_globals ();
+  timevar_stop (TV_PHASE_DBGINFO);

Preeeeety... if I do say so myself.

The attached patch is untested, and will fail miserably on anything but 
C (lto, c++, etc).  But it shows how I'd like to approach this.

Would you bless this approach, so I can continue with the other 
languages and LTO?

As usual, thanks for your feedback.
Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 27346 bytes --]

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 240ca44..fd88e44 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -894,8 +894,9 @@ gnat_init_ts (void)
 #define LANG_HOOKS_GETDECLS		lhd_return_null_tree_v
 #undef  LANG_HOOKS_PUSHDECL
 #define LANG_HOOKS_PUSHDECL		gnat_return_tree
-#undef  LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS	gnat_write_global_declarations
+/* FIXME: Add Ada support.  */
+#undef  LANG_HOOKS_EARLY_WRITE_GLOBALS
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS	gnat_write_global_declarations
 #undef  LANG_HOOKS_GET_ALIAS_SET
 #define LANG_HOOKS_GET_ALIAS_SET	gnat_get_alias_set
 #undef  LANG_HOOKS_PRINT_DECL
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 1e09404..79ea89c 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10310,7 +10310,7 @@ c_write_global_declarations_1 (tree globals)
   for (decl = globals; decl; decl = DECL_CHAIN (decl))
     {
       check_global_declaration_1 (decl);
-      debug_hooks->global_decl (decl, /*early=*/true);
+      debug_hooks->early_global_decl (decl);
     }
 }
 
@@ -10322,8 +10322,10 @@ c_write_global_declarations_2 (tree globals)
 {
   tree decl;
 
+  /* FIXME: Rewrite to iterate through varpool/cgraph nodes, instead
+     of `globals'.  */
   for (decl = globals; decl ; decl = DECL_CHAIN (decl))
-    debug_hooks->global_decl (decl, /*early=*/false);
+    debug_hooks->late_global_decl (decl);
 }
 
 /* Callback to collect a source_ref from a DECL.  */
@@ -10374,17 +10376,12 @@ for_each_global_decl (void (*callback) (tree decl))
 }
 
 void
-c_write_global_declarations (void)
+c_early_write_global_declarations (void)
 {
-  tree t;
-  unsigned i;
-
   /* We don't want to do this if generating a PCH.  */
   if (pch_file)
     return;
 
-  timevar_start (TV_PHASE_DEFERRED);
-
   /* Do the Objective-C stuff.  This is where all the Objective-C
      module stuff gets generated (symtab, class/protocol/selector
      lists etc).  */
@@ -10422,24 +10419,24 @@ c_write_global_declarations (void)
 
   /* Process all file scopes in this compilation, and the external_scope,
      through wrapup_global_declarations and check_global_declarations.  */
+  tree t;
+  unsigned i;
   FOR_EACH_VEC_ELT (*all_translation_units, i, t)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+}
 
-  timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
-
-  /* We're done parsing; proceed to optimize and emit assembly.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  symtab->finalize_compilation_unit ();
-
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_DBGINFO);
-
+void
+c_late_write_global_declarations (void)
+{
   /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for globals.  */
+     be emitted, amend any debug information for globals with
+     appropriate location information.  */
   if (!seen_error ())
     {
+      unsigned int i;
+      tree t;
+
       timevar_push (TV_SYMOUT);
       FOR_EACH_VEC_ELT (*all_translation_units, i, t)
 	c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
@@ -10448,7 +10445,6 @@ c_write_global_declarations (void)
     }
 
   ext_block = NULL;
-  timevar_stop (TV_PHASE_DBGINFO);
 }
 
 /* Register reserved keyword WORD as qualifier for address space AS.  */
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 92cf60f..acabeec 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -92,8 +92,10 @@ along with GCC; see the file COPYING3.  If not see
 
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS c_early_write_global_declarations
+#undef LANG_HOOKS_LATE_WRITE_GLOBALS
+#define LANG_HOOKS_LATE_WRITE_GLOBALS c_late_write_global_declarations
 
 /* Hooks for tree gimplification.  */
 #undef LANG_HOOKS_GIMPLIFY_EXPR
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 6004d50..9dada9c 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -669,7 +669,8 @@ extern enum machine_mode c_default_pointer_mode;
 
 /* In c-decl.c */
 extern void c_finish_incomplete_decl (tree);
-extern void c_write_global_declarations (void);
+extern void c_early_write_global_declarations (void);
+extern void c_late_write_global_declarations (void);
 extern tree c_omp_reduction_id (enum tree_code, tree);
 extern tree c_omp_reduction_decl (tree);
 extern tree c_omp_reduction_lookup (tree, tree);
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 246800e..2435e06 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -83,8 +83,9 @@ extern void cp_common_init_ts (void);
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION	cxx_print_error_function
 #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS cp_write_global_declarations
+/* FIXME: Add C++ support.  */
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS cp_write_global_declarations
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function
 #undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 208cec9..e517311 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -325,7 +325,7 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
 static void dbxout_common_name (tree, const char *, stab_code_type);
 static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree, bool);
+static void dbxout_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void debug_free_queue (void);
@@ -366,7 +366,8 @@ const struct gcc_debug_hooks dbx_debug_hooks =
 #endif
   debug_nothing_int,		         /* end_function */
   dbxout_function_decl,
-  dbxout_global_decl,		         /* global_decl */
+  debug_nothing_tree,		         /* early_global_decl */
+  dbxout_global_decl,		         /* late_global_decl */
   dbxout_type_decl,			 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -402,7 +403,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_tree,		         /* begin_function */
   xcoffout_end_function,
   debug_nothing_tree,		         /* function_decl */
-  dbxout_global_decl,		         /* global_decl */
+  debug_nothing_tree,		         /* early_global_decl */
+  dbxout_global_decl,		         /* late_global_decl */
   dbxout_type_decl,			 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -1320,7 +1322,7 @@ dbxout_function_decl (tree decl)
 /* Debug information for a global DECL.  Called from toplev.c after
    compilation proper has finished.  */
 static void
-dbxout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED)
+dbxout_global_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
diff --git a/gcc/debug.c b/gcc/debug.c
index b5818de..2beb10f 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -43,7 +43,8 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_tree,		         /* begin_function */
   debug_nothing_int,		         /* end_function */
   debug_nothing_tree,		         /* function_decl */
-  debug_nothing_tree_bool,	         /* global_decl */
+  debug_nothing_tree,			 /* early_global_decl */
+  debug_nothing_tree,	         	 /* late_global_decl */
   debug_nothing_tree_int,		 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
diff --git a/gcc/debug.h b/gcc/debug.h
index 9440515..227618d 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -92,12 +92,22 @@ struct gcc_debug_hooks
      function.  */
   void (* function_decl) (tree decl);
 
-  /* Debug information for a global DECL.  Called from toplev.c after
-     compilation proper has finished.  EARLY is true if global_decl()
-     is being called early on in the compilation process (i.e., before
-     cgraph information is available and before code is
-     generated).  */
-  void (* global_decl) (tree decl, bool early);
+  /* Debug information for a global DECL.  Called before the
+     compilation proper has run (i.e., before cgraph information is
+     available, usually after parsing has completed).
+
+     This hooks gets called to emit initial debugging information
+     after parsing has happened, but before we have complete location
+     information.  When the compilation proper has finished,
+     late_global_decl (below) is called and the debugging information
+     generated by this hook is amended accordingly.  */
+  void (* early_global_decl) (tree decl);
+
+  /* This hook is called after the compilation proper has finished and
+     is used to ammend debugging information which was initially
+     generated by early_global_decl above (with location information
+     and such).  */
+  void (* late_global_decl) (tree decl);
 
   /* Debug information for a type DECL.  Called from toplev.c after
      compilation proper, also from various language front ends to
@@ -191,8 +201,6 @@ extern void dwarf2out_switch_text_section (void);
 const char *remap_debug_filename (const char *);
 void add_debug_prefix_map (const char *);
 
-extern void dwarf2out_early_decl (tree);
-
 /* For -fdump-go-spec.  */
 
 extern const struct gcc_debug_hooks *
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 918f261..f3f8481 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2430,7 +2430,8 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree, bool);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
@@ -2468,7 +2469,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_begin_function,
   dwarf2out_end_function,	/* end_function */
   dwarf2out_function_decl,	/* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,	/* early_global_decl */
+  dwarf2out_late_global_decl,	/* late_global_decl */
   dwarf2out_type_decl,		/* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,		/* deferred_inline_function */
@@ -2609,7 +2611,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
   /* Die is used and must not be pruned as unused.  */
   BOOL_BITFIELD die_perennial_p : 1;
   BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
-  /* Die was generated early via dwarf2out_early_decl.  */
+  /* Die was generated early via dwarf2out_early_global_decl.  */
   BOOL_BITFIELD dumped_early : 1;
   /* Lots of spare bits.  */
 }
@@ -20817,29 +20819,65 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from
-   toplev.c after compilation proper has finished.
-
-   dwarf2out_decl() will be called twice on each global symbol: once
-   immediately after parsing (EARLY=true), and once after the full
-   compilation has finished (EARLY=false).  There are checks in
-   dwarf2out_decl() to make sure that if we have a DECL DIE upon
-   entry, that the previously created DIE is reused.  No new DECL DIEs
-   should be created when EARLY=false.
-
-   The second time dwarf2out_decl() is called (or for that matter, the
-   second time any DECL DIE is seen throughout dwarf2out), only
-   information not previously available (e.g. location) is tacked onto
-   the early dumped DIE.  That's the plan anyhow ;-).  */
+/* Output initial debug information for global decl DECL.  Called from
+   toplev.c after parsing has finished.  After the compilation proper
+   has finished, the debugging information generated here is amended
+   with location information and other things (see
+   dwarf2out_late_global_decl).  */
 
 static void
-dwarf2out_global_decl (tree decl, bool early)
+dwarf2out_early_global_decl (tree decl)
 {
-  if (early)
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
     {
-      dwarf2out_early_decl (decl);
-      return;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+	{
+	  /* A missing cfun means the symbol is unused and was removed
+	     from the callgraph.  */
+	  if (!DECL_STRUCT_FUNCTION (decl))
+	    goto early_decl_exit;
+
+	  push_cfun (DECL_STRUCT_FUNCTION (decl));
+	  current_function_decl = decl;
+	}
+      dw_die_ref die = dwarf2out_decl (decl);
+      if (die)
+	die->dumped_early = true;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+	{
+	  pop_cfun ();
+	  current_function_decl = NULL;
+	}
     }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+  return;
+}
+
+/* After the compilation proper has finished, augment any debugging
+   information generated in dwarf2out_early_global_decl().  No new
+   DECL DIEs should be generated at this point.  Instead, DIEs
+   generated in dwarf2out_early_global_decl should be reused and
+   amended.  */
+
+static void
+dwarf2out_late_global_decl (tree decl)
+{
   /* Output DWARF2 information for file-scope tentative data object
      declarations, file-scope (extern) function declarations (which
      had no corresponding body) and file-scope tagged type declarations
@@ -21181,52 +21219,6 @@ dwarf2out_decl (tree decl)
   return die;
 }
 
-/* Early dumping of DECLs before we lose language data.  */
-
-void
-dwarf2out_early_decl (tree decl)
-{
-  /* gen_decl_die() will set DECL_ABSTRACT because
-     cgraph_function_possibly_inlined_p() returns true.  This is in
-     turn will cause DW_AT_inline attributes to be set.
-
-     This happens because at early dwarf generation, there is no
-     cgraph information, causing cgraph_function_possibly_inlined_p()
-     to return true.  Trick cgraph_function_possibly_inlined_p()
-     while we generate dwarf early.  */
-  bool save = symtab->global_info_ready;
-  symtab->global_info_ready = true;
-
-  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
-     other DECLs and they can point to template types or other things
-     that dwarf2out can't handle when done via dwarf2out_decl.  */
-  if (TREE_CODE (decl) != TYPE_DECL
-      && TREE_CODE (decl) != PARM_DECL)
-    {
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	{
-	  /* A missing cfun means the symbol is unused and was removed
-	     from the callgraph.  */
-	  if (!DECL_STRUCT_FUNCTION (decl))
-	    goto early_decl_exit;
-
-	  push_cfun (DECL_STRUCT_FUNCTION (decl));
-	  current_function_decl = decl;
-	}
-      dw_die_ref die = dwarf2out_decl (decl);
-      if (die)
-	die->dumped_early = true;
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	{
-	  pop_cfun ();
-	  current_function_decl = NULL;
-	}
-    }
- early_decl_exit:
-  symtab->global_info_ready = save;
-  return;
-}
-
 /* Write the debugging output for DECL.  */
 
 static void
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index da3a0d0..d435c07 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -108,7 +108,8 @@ static const struct attribute_spec gfc_attribute_table[] =
 #undef LANG_HOOKS_NAME
 #undef LANG_HOOKS_INIT
 #undef LANG_HOOKS_FINISH
-#undef LANG_HOOKS_WRITE_GLOBALS
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#undef LANG_HOOKS_LATE_WRITE_GLOBALS
 #undef LANG_HOOKS_OPTION_LANG_MASK
 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
 #undef LANG_HOOKS_INIT_OPTIONS
@@ -142,7 +143,8 @@ static const struct attribute_spec gfc_attribute_table[] =
 #define LANG_HOOKS_NAME                 "GNU Fortran"
 #define LANG_HOOKS_INIT                 gfc_init
 #define LANG_HOOKS_FINISH               gfc_finish
-#define LANG_HOOKS_WRITE_GLOBALS	gfc_write_global_declarations
+/* FIXME: Add Fortran support.  */
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS	gfc_write_global_declarations
 #define LANG_HOOKS_OPTION_LANG_MASK	gfc_option_lang_mask
 #define LANG_HOOKS_INIT_OPTIONS_STRUCT  gfc_init_options_struct
 #define LANG_HOOKS_INIT_OPTIONS         gfc_init_options
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 24b6437..a2aec63 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -534,7 +534,8 @@ go_localize_identifier (const char *ident)
 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
 #undef LANG_HOOKS_PUSHDECL
 #undef LANG_HOOKS_GETDECLS
-#undef LANG_HOOKS_WRITE_GLOBALS
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#undef LANG_HOOKS_LATE_WRITE_GLOBALS
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #undef LANG_HOOKS_EH_PERSONALITY
 
@@ -551,7 +552,8 @@ go_localize_identifier (const char *ident)
 #define LANG_HOOKS_GLOBAL_BINDINGS_P	go_langhook_global_bindings_p
 #define LANG_HOOKS_PUSHDECL		go_langhook_pushdecl
 #define LANG_HOOKS_GETDECLS		go_langhook_getdecls
-#define LANG_HOOKS_WRITE_GLOBALS	go_langhook_write_globals
+/* FIXME: Add Go support.  */
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS	go_langhook_write_globals
 #define LANG_HOOKS_GIMPLIFY_EXPR	go_langhook_gimplify_expr
 #define LANG_HOOKS_EH_PERSONALITY	go_langhook_eh_personality
 
diff --git a/gcc/godump.c b/gcc/godump.c
index 01f8410..888dcb0 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -496,9 +496,9 @@ go_function_decl (tree decl)
 /* A global variable decl.  */
 
 static void
-go_global_decl (tree decl, bool early)
+go_global_decl (tree decl)
 {
-  real_debug_hooks->global_decl (decl, early);
+  real_debug_hooks->late_global_decl (decl);
   go_decl (decl);
 }
 
@@ -1240,7 +1240,7 @@ dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
   go_debug_hooks.define = go_define;
   go_debug_hooks.undef = go_undef;
   go_debug_hooks.function_decl = go_function_decl;
-  go_debug_hooks.global_decl = go_global_decl;
+  go_debug_hooks.late_global_decl = go_global_decl;
   go_debug_hooks.type_decl = go_type_decl;
 
   macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 8a68691..5cdaa15 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -142,8 +142,9 @@ struct GTY(()) language_function {
 #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name
 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION	java_print_error_function
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS java_write_globals
+/* FIXME: Add Java support.  */
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS java_write_globals
 
 #undef LANG_HOOKS_TYPE_FOR_MODE
 #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index e77d2d9..410690b 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -204,7 +204,8 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_GETDECLS	getdecls
 #define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
-#define LANG_HOOKS_WRITE_GLOBALS write_global_declarations
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS early_write_global_declarations
+#define LANG_HOOKS_LATE_WRITE_GLOBALS late_write_global_declarations
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL	lhd_decl_ok_for_sibcall
 #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
@@ -228,7 +229,8 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
   LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
   LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
-  LANG_HOOKS_WRITE_GLOBALS, \
+  LANG_HOOKS_EARLY_WRITE_GLOBALS, \
+  LANG_HOOKS_LATE_WRITE_GLOBALS, \
   LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
   LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
   LANG_HOOKS_OMP_PREDETERMINED_SHARING, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 8ff91ba..c0d7459 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -290,45 +290,48 @@ lhd_decl_ok_for_sibcall (const_tree decl ATTRIBUTE_UNUSED)
   return true;
 }
 
-/* lang_hooks.decls.final_write_globals: perform final processing on
+/* FIXME: Rewrite this to use <vec>.  Remove this eventually (see note
+   in late_write_global_declarations).  */
+static tree *globals_vec;
+static int globals_vec_len;
+
+/* lang_hooks.decls.early_write_globals: perform final processing on
    global variables.  */
 void
-write_global_declarations (void)
+early_write_global_declarations (void)
 {
-  tree globals, decl, *vec;
-  int len, i;
+  tree globals, decl;
 
-  timevar_start (TV_PHASE_DEFERRED);
   /* Really define vars that have had only a tentative definition.
      Really output inline functions that must actually be callable
      and have not been output so far.  */
 
   globals = lang_hooks.decls.getdecls ();
-  len = list_length (globals);
-  vec = XNEWVEC (tree, len);
+  globals_vec_len = list_length (globals);
+  globals_vec = XNEWVEC (tree, globals_vec_len);
 
   /* Process the decls in reverse order--earliest first.
      Put them into VEC from back to front, then take out from front.  */
+  int i;
+  for (i = 0, decl = globals; i < globals_vec_len;
+       i++, decl = DECL_CHAIN (decl))
+    globals_vec[globals_vec_len - i - 1] = decl;
 
-  for (i = 0, decl = globals; i < len; i++, decl = DECL_CHAIN (decl))
-    vec[len - i - 1] = decl;
-
-  wrapup_global_declarations (vec, len);
-  check_global_declarations (vec, len);
-  timevar_stop (TV_PHASE_DEFERRED);
-
-  timevar_start (TV_PHASE_OPT_GEN);
-  /* This lang hook is dual-purposed, and also finalizes the
-     compilation unit.  */
-  symtab->finalize_compilation_unit ();
-  timevar_stop (TV_PHASE_OPT_GEN);
+  wrapup_global_declarations (globals_vec, globals_vec_len);
+  check_global_declarations (globals_vec, globals_vec_len);
+}
 
-  timevar_start (TV_PHASE_DBGINFO);
-  emit_debug_global_declarations (vec, len);
-  timevar_stop (TV_PHASE_DBGINFO);
+/* lang_hooks.decls.late_write_globals: perform final processing on
+   global variables.  */
+void
+late_write_global_declarations (void)
+{
+  /* FIXME: Rewrite this to use the cgraph/varpool iterators instead
+     of globals_vec.  */
+  emit_debug_global_declarations (globals_vec, globals_vec_len);
 
   /* Clean up.  */
-  free (vec);
+  free (globals_vec);
 }
 
 /* Called to perform language-specific initialization of CTX.  */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 72fa85e..7e33f3a 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -181,9 +181,16 @@ struct lang_hooks_for_decls
      We will already have checked that it has static binding.  */
   bool (*warn_unused_global) (const_tree);
 
-  /* Obtain a list of globals and do final output on them at end
-     of compilation */
-  void (*final_write_globals) (void);
+  /* Obtain a list of globals and do final output on them after
+     parsing (before compilation).  This also involves outputting
+     initial debugging information after parsing.  */
+  void (*early_write_globals) (void);
+
+  /* Perform any final output of globals after compilation (cgraph
+     information is available).  This usually involves amending any
+     debugging information originally outputted by the
+     early_write_globals hook above.  */
+  void (*late_write_globals) (void);
 
   /* True if this decl may be called via a sibcall.  */
   bool (*ok_for_sibcall) (const_tree);
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 1f39949..de65854 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1093,7 +1093,7 @@ lto_write_globals (void)
   varpool_node *vnode;
   FOR_EACH_DEFINED_VARIABLE (vnode)
     if (!decl_function_context (vnode->decl))
-      debug_hooks->global_decl (vnode->decl, /*early=*/false);
+      debug_hooks->late_global_decl (vnode->decl);
 }
 
 static tree
@@ -1275,8 +1275,10 @@ static void lto_init_ts (void)
 #define LANG_HOOKS_PUSHDECL lto_pushdecl
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lto_getdecls
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS lto_write_globals
+#undef LANG_HOOKS_EARLY_WRITE_GLOBALS
+#define LANG_HOOKS_EARLY_WRITE_GLOBALS debug_nothing_void
+#undef LANG_HOOKS_LATE_WRITE_GLOBALS
+#define LANG_HOOKS_LATE_WRITE_GLOBALS lto_write_globals
 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lto_register_builtin_type
 #undef LANG_HOOKS_BUILTIN_FUNCTION
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ceefa1b..151bc04 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -532,7 +532,7 @@ emit_debug_global_declarations (tree *vec, int len)
 
   timevar_push (TV_SYMOUT);
   for (i = 0; i < len; i++)
-    debug_hooks->global_decl (vec[i], /*early=*/false);
+    debug_hooks->late_global_decl (vec[i]);
   timevar_pop (TV_SYMOUT);
 }
 
@@ -560,8 +560,20 @@ compile_file (void)
 
   ggc_protect_identifiers = false;
 
-  /* This must also call finalize_compilation_unit.  */
-  lang_hooks.decls.final_write_globals ();
+  /* Emit early debugging information as well as globals.  */
+  timevar_start (TV_PHASE_DEFERRED);
+  lang_hooks.decls.early_write_globals ();
+  timevar_stop (TV_PHASE_DEFERRED);
+
+  /* We're done parsing; proceed to optimize and emit assembly.  */
+  timevar_start (TV_PHASE_OPT_GEN);
+  symtab->finalize_compilation_unit ();
+  timevar_stop (TV_PHASE_OPT_GEN);
+
+  /* Amend any debugging information generated previously.  */
+  timevar_start (TV_PHASE_DBGINFO);
+  lang_hooks.decls.late_write_globals ();
+  timevar_stop (TV_PHASE_DBGINFO);
 
   if (seen_error ())
     return;
diff --git a/gcc/toplev.h b/gcc/toplev.h
index 1b54578..807b3f1 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -43,7 +43,6 @@ extern bool wrapup_global_declarations (tree *, int);
 extern void check_global_declaration_1 (tree);
 extern void check_global_declarations (tree *, int);
 extern void emit_debug_global_declarations (tree *, int);
-extern void write_global_declarations (void);
 
 extern void dump_memory_report (bool);
 extern void dump_profile_report (void);

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-05  2:38           ` Aldy Hernandez
@ 2014-09-05  9:00             ` Richard Biener
  2014-09-09  0:01               ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-09-05  9:00 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches

On Fri, Sep 5, 2014 at 4:38 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/04/14 03:42, Richard Biener wrote:
>>
>> On Wed, Sep 3, 2014 at 7:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
>
>
>> Flow-wise I still want to move hand-off to the cgraph code to toplev.c,
>> out from the FEs final_write_gloabals hook:
>>
>>    /* This must also call finalize_compilation_unit.  */
>>    lang_hooks.decls.final_write_globals ();
>>
>> that would make clearer how control flows.
>
>
> Neat.  I like it.
>
>> I'd also rather split the hook into two ... (and call the 2nd non-early
>> phase hook from where we output the code).  What does that phase
>> output for global decls anyway?
>
>
> This is also a very good idea, and it makes the intent clearer.
>
>> Otherwise looks like a good incremental improvement to me.
>
>
> Since we're pretty much on the same page, I've committed this revision you
> just looked at, so we can talk about the changes you mention above
> separately, namely:
>
> a) Divorcing final_write_globals and finalize_compilation.
> b) Splitting the global_decl hook into two.
>
> So this is what I have in mind (patch attached).  I'd like to split
> LANG_HOOKS_WRITE_GLOBALS in favor of LANG_HOOKS_{EARLY,LATE}_WRITE_GLOBALS,
> as well as splitting the global_decl debug hook into
> {early,late}_global_decl.  I've commented things throughout to make it very
> clear what we're getting at.

I meant that LATE_WRITE_GLOBALS shouldn't be a langhook
at all but instead the middle-end should be in control of that and
implement it in a language independent way.  After all this will be
called from LTO LTRANS phase.

> I chose to dispense with the old names to make it very clear what the hook
> should do, and to make sure I didn't miss any places.
>
> Toplev will now look much cleaner:
>
> +  /* Emit early debugging information as well as globals.  */
> +  timevar_start (TV_PHASE_DEFERRED);
> +  lang_hooks.decls.early_write_globals ();
> +  timevar_stop (TV_PHASE_DEFERRED);
> +
> +  /* We're done parsing; proceed to optimize and emit assembly.  */
> +  timevar_start (TV_PHASE_OPT_GEN);
> +  symtab->finalize_compilation_unit ();
> +  timevar_stop (TV_PHASE_OPT_GEN);
> +
> +  /* Amend any debugging information generated previously.  */
> +  timevar_start (TV_PHASE_DBGINFO);
> +  lang_hooks.decls.late_write_globals ();
> +  timevar_stop (TV_PHASE_DBGINFO);
>
> Preeeeety... if I do say so myself.

Yeah - apart from that langhook issue for late_write_globals ;)

> The attached patch is untested, and will fail miserably on anything but C
> (lto, c++, etc).  But it shows how I'd like to approach this.
>
> Would you bless this approach, so I can continue with the other languages
> and LTO?

Be prepared to meet some fun with Java and moving finalize_compilation_unit
out (I remember trying that at some point).

Otherwise it would be nice if you can implement late_write_globals by
simply walking the symbol table with sth like

  FOR_EACH_DEFINED_SYMBOL (node)
     debug_hooks->late_global_decl (node->decl);

well - of course it will likely not be _that_ simple.  And eventually it's
better to do this from where we have done the output (in varasm.c
for variables and somewhere in final.c for functions), but let's try
that FOR_EACH as it looks so simple ;)

Richard.

> As usual, thanks for your feedback.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-05  9:00             ` Richard Biener
@ 2014-09-09  0:01               ` Aldy Hernandez
  2014-09-09  9:16                 ` Richard Biener
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-09  0:01 UTC (permalink / raw)
  To: Richard Biener, Jason Merrill; +Cc: gcc-patches

On 09/05/14 02:00, Richard Biener wrote:

[jason: C++ questions throughout.]

> On Fri, Sep 5, 2014 at 4:38 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>> On 09/04/14 03:42, Richard Biener wrote:
>>>
>>> On Wed, Sep 3, 2014 at 7:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:

> I meant that LATE_WRITE_GLOBALS shouldn't be a langhook
> at all but instead the middle-end should be in control of that and
> implement it in a language independent way.  After all this will be
> called from LTO LTRANS phase.

This looks like a rat's nest :(.

Interestingly, most non-C/C++ languages are well behaved, and use the 
generic write_global_declarations() function.  Ada even goes as far as 
calling debug_hooks->global_decl() before the compilation proper and 
then once again after the compilation has finished (like we're planning 
on doing).  Java, which you thought was horrible, mostly just calls the 
generic write_global_declarations().  C++ is a different story...

It seems to me that C++ is the most complicated of the FE's when it 
comes to LANG_HOOKS_WRITE_GLOBALS.  Most annoyingly, it does many things 
*after* it has called finalize_compilation_unit (creating VTV 
constructors, calling check_global_declarations on pending_statics, 
building Java method aliases, etc etc).  See 
cp_write_global_declarations() for everything after 
finalize_compilation_unit).

What I have in mind is:

1. Move the FE specific things that come before the call to 
finalize_compilation_unit currently in each LANG_HOOKS_WRITE_GLOBALS, 
into the FE proper (lang_hooks.parse_file).  This may or may not mean 
calling {wrapup,check}_global_declarations directly from the FEs since 
some FE's call these in a sufficiently different order to merit everyone 
doing their own thing (not sure though).

2. Generate debug information by gathering the list of globals with 
lang_hooks.decls.getdecls (??) and then doing 
debug_hooks->early_global_decl() as discussed.

2. Call finalize_compilation_unit() directly from compile_file().

3. Call some (new) hook for C++ stuff after finalize_compilation_unit (???).

4. FOR_EACH_DEFINED_SYMBOL (node)
      debug_hooks->late_global_decl (node->decl)

    as suggested.

The wildcard here is C++.  Shall we create a hook for post 
finalize_compilation_unit() but pre late debug dumping (item 3 above)? 
Or can we move most of the post finalize_compilation_unit() stuff in C++ 
before it, thus into the FE proper?  Also, disturbingly C++ calls 
check_global_declarations() after finalize_compilation_unit (a couple 
times actually).

I think if we can get C++ to work, everything else basically falls into 
place... even Ada and Go ;-).

Comments highly welcome.
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-09  0:01               ` Aldy Hernandez
@ 2014-09-09  9:16                 ` Richard Biener
  2014-09-12  0:51                   ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-09-09  9:16 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches

On Tue, Sep 9, 2014 at 2:00 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/05/14 02:00, Richard Biener wrote:
>
> [jason: C++ questions throughout.]
>
>> On Fri, Sep 5, 2014 at 4:38 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>>>
>>> On 09/04/14 03:42, Richard Biener wrote:
>>>>
>>>>
>>>> On Wed, Sep 3, 2014 at 7:54 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
>
>
>> I meant that LATE_WRITE_GLOBALS shouldn't be a langhook
>> at all but instead the middle-end should be in control of that and
>> implement it in a language independent way.  After all this will be
>> called from LTO LTRANS phase.
>
>
> This looks like a rat's nest :(.
>
> Interestingly, most non-C/C++ languages are well behaved, and use the
> generic write_global_declarations() function.  Ada even goes as far as
> calling debug_hooks->global_decl() before the compilation proper and then
> once again after the compilation has finished (like we're planning on
> doing).  Java, which you thought was horrible, mostly just calls the generic
> write_global_declarations().  C++ is a different story...
>
> It seems to me that C++ is the most complicated of the FE's when it comes to
> LANG_HOOKS_WRITE_GLOBALS.  Most annoyingly, it does many things *after* it
> has called finalize_compilation_unit (creating VTV constructors, calling
> check_global_declarations on pending_statics, building Java method aliases,
> etc etc).  See cp_write_global_declarations() for everything after
> finalize_compilation_unit).

Yeah, it was the Java method aliases building I remember (I tried before
VTV materialized) ;)   So I falsely blamed Java - it's only remotely Javas
fault ... ;)

> What I have in mind is:
>
> 1. Move the FE specific things that come before the call to
> finalize_compilation_unit currently in each LANG_HOOKS_WRITE_GLOBALS, into
> the FE proper (lang_hooks.parse_file).  This may or may not mean calling
> {wrapup,check}_global_declarations directly from the FEs since some FE's
> call these in a sufficiently different order to merit everyone doing their
> own thing (not sure though).
>
> 2. Generate debug information by gathering the list of globals with
> lang_hooks.decls.getdecls (??) and then doing
> debug_hooks->early_global_decl() as discussed.

Or move that also to lang_hooks.parse_file?  ISTR lang_hooks.decls.getdecls
is sort of an "alternative" hook to write_global_declarations that is only
used by the generic implementation of write_global_declarations.

So if we move everything else but calling debug_hooks->early_global_decl ()
out of the write_global_declarations langhook then we could indeed
remove that hook and implement getdecls everywhere.

I suppose one of the hooks should go in the end.

> 2. Call finalize_compilation_unit() directly from compile_file().

Great!

> 3. Call some (new) hook for C++ stuff after finalize_compilation_unit (???).

Or fix the C++ stuff to work properly in a symtab way?  I suppose as
an intermediate step adding a new langhook for this on the branch is ok
but I'd rather not get that merged into trunk.

Maybe Jason can help cleaning this up.

> 4. FOR_EACH_DEFINED_SYMBOL (node)
>      debug_hooks->late_global_decl (node->decl)
>
>    as suggested.
>
> The wildcard here is C++.  Shall we create a hook for post
> finalize_compilation_unit() but pre late debug dumping (item 3 above)? Or
> can we move most of the post finalize_compilation_unit() stuff in C++ before
> it, thus into the FE proper?  Also, disturbingly C++ calls
> check_global_declarations() after finalize_compilation_unit (a couple times
> actually).
>
> I think if we can get C++ to work, everything else basically falls into
> place... even Ada and Go ;-).

I hope that C++ can be "fixed" to do things in proper order and not
behind symtabs back.

For the branch to be able to move forward we can certainly add some
hooks temporarily.

Or disable the Java/VTV stuff for the time being.  I don't remember
running into the check_global_declarations () issue (or what that does).

Jason?

Tahnks,
Richard.

> Comments highly welcome.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-09  9:16                 ` Richard Biener
@ 2014-09-12  0:51                   ` Aldy Hernandez
  2014-09-12  8:13                     ` Richard Biener
  2014-09-12 15:15                     ` Jason Merrill
  0 siblings, 2 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-12  0:51 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jason Merrill, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3204 bytes --]

On 09/09/14 02:16, Richard Biener wrote:
> On Tue, Sep 9, 2014 at 2:00 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>> On 09/05/14 02:00, Richard Biener wrote:

>> What I have in mind is:
>>
>> 1. Move the FE specific things that come before the call to
>> finalize_compilation_unit currently in each LANG_HOOKS_WRITE_GLOBALS, into
>> the FE proper (lang_hooks.parse_file).  This may or may not mean calling
>> {wrapup,check}_global_declarations directly from the FEs since some FE's
>> call these in a sufficiently different order to merit everyone doing their
>> own thing (not sure though).

Done.

>>
>> 2. Generate debug information by gathering the list of globals with
>> lang_hooks.decls.getdecls (??) and then doing
>> debug_hooks->early_global_decl() as discussed.
>
> Or move that also to lang_hooks.parse_file?  ISTR lang_hooks.decls.getdecls
> is sort of an "alternative" hook to write_global_declarations that is only
> used by the generic implementation of write_global_declarations.

Done.

>
> So if we move everything else but calling debug_hooks->early_global_decl ()
> out of the write_global_declarations langhook then we could indeed
> remove that hook and implement getdecls everywhere.
>
> I suppose one of the hooks should go in the end.
>
>> 2. Call finalize_compilation_unit() directly from compile_file().

Done.

>
> Great!
>
>> 3. Call some (new) hook for C++ stuff after finalize_compilation_unit (???).
>
> Or fix the C++ stuff to work properly in a symtab way?  I suppose as
> an intermediate step adding a new langhook for this on the branch is ok
> but I'd rather not get that merged into trunk.

Done.  For now I've called it 
LANG_HOOK_POST_COMPILATION_PARSING_CLEANUPS, and it is only applicable 
to C++, unless some other FE acts up in the process and needs similar 
massaging.

> Maybe Jason can help cleaning this up.

Jason's not much of a beer drinker AFAICT, so I'm trying to come up with 
a suitable bribe.

>
>> 4. FOR_EACH_DEFINED_SYMBOL (node)
>>       debug_hooks->late_global_decl (node->decl)
>>
>>     as suggested.

Done.

[Well... as DONE as a prototype can be :).  This is a work in progress, 
but I'd like y'all to peek at it, to make sure I'm not making obvious 
wrong turns that will have me rewriting code months from now, and hating 
you in the process.  And by you, I mean Jason *and* you.  I don't want 
anyone to feel left out by my frustration and anger.]

I drafted what I want Ada, Java, Fortran, and Go to look like (as well 
as the obvious C/C++ languages).

For C, guality.exp exhibits less failures than mainline.  I'm currently 
debugging inline virtual C++ destructors.  It seems the inliner can also 
call generate debugging info (debug_hooks->outlining_inline_function). 
The rest of the languages are tested as far as building jc1/f951/go1 
with no warnings :-))).

There are various cleanups and comments along the way.

Let me know if you're "mostly" OK with this, so I can push this to the 
branch and continue iterating with you incrementally.  It seems there 
will be no shortage of weird bugs in dwarf generation due to the fact 
that we stream early.  I'm hoping to start concentrating on those...

As usual, thanks.
Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 51404 bytes --]

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 240ca44..44af75f 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -105,6 +105,10 @@ gnat_parse_file (void)
 
   /* Call the front end.  */
   _ada_gnat1drv ();
+
+  /* Output global declarations and generate debug information for
+     them.  */
+  gnat_write_global_declarations ();
 }
 
 /* Return language mask for option processing.  */
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 266a942..fb187a6 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -5178,27 +5178,9 @@ gnat_write_global_declarations (void)
 	}
     }
 
-  /* Output debug information for all global type declarations first.  This
-     ensures that global types whose compilation hasn't been finalized yet,
-     for example pointers to Taft amendment types, have their compilation
-     finalized in the right context.  */
   FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter)
     if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter))
-      debug_hooks->global_decl (iter);
-
-  /* Proceed to optimize and emit assembly. */
-  symtab->finalize_compilation_unit ();
-
-  /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for the rest of globals.  */
-  if (!seen_error ())
-    {
-      timevar_push (TV_SYMOUT);
-      FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter)
-	if (TREE_CODE (iter) != TYPE_DECL && !DECL_IGNORED_P (iter))
-	  debug_hooks->global_decl (iter);
-      timevar_pop (TV_SYMOUT);
-    }
+      debug_hooks->early_global_decl (iter);
 }
 
 /* ************************************************************************
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 993a97b..1f5d557 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -847,6 +847,8 @@ extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT);
 /* This is the basic parsing function.  */
 extern void c_parse_file (void);
 
+extern void c_parse_final_cleanups (void);
+
 extern void warn_for_omitted_condop (location_t, tree);
 
 /* These macros provide convenient access to the various _STMT nodes.  */
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 7486691..fac25cc 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -1070,6 +1070,9 @@ c_common_parse_file (void)
       if (!this_input_filename)
 	break;
     }
+
+  if (!flag_syntax_only)
+    c_parse_final_cleanups ();
 }
 
 /* Returns the appropriate dump file for PHASE to dump with FLAGS.  */
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 1e09404..a0a047f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10270,9 +10270,8 @@ finish_declspecs (struct c_declspecs *specs)
   return specs;
 }
 
-/* A subroutine of c_write_global_declarations.  Perform final processing
-   on one file scope's declarations (or the external scope's declarations),
-   GLOBALS.  */
+/* Perform final processing on one file scope's declarations (or the
+   external scope's declarations), GLOBALS.  */
 
 static void
 c_write_global_declarations_1 (tree globals)
@@ -10310,22 +10309,10 @@ c_write_global_declarations_1 (tree globals)
   for (decl = globals; decl; decl = DECL_CHAIN (decl))
     {
       check_global_declaration_1 (decl);
-      debug_hooks->global_decl (decl, /*early=*/true);
+      debug_hooks->early_global_decl (decl);
     }
 }
 
-/* A subroutine of c_write_global_declarations Emit debug information for each
-   of the declarations in GLOBALS.  */
-
-static void
-c_write_global_declarations_2 (tree globals)
-{
-  tree decl;
-
-  for (decl = globals; decl ; decl = DECL_CHAIN (decl))
-    debug_hooks->global_decl (decl, /*early=*/false);
-}
-
 /* Callback to collect a source_ref from a DECL.  */
 
 static void
@@ -10373,8 +10360,11 @@ for_each_global_decl (void (*callback) (tree decl))
     callback (decl);
 }
 
+/* Perform any final parser cleanups and generate initial debugging
+   information.  */
+
 void
-c_write_global_declarations (void)
+c_parse_final_cleanups (void)
 {
   tree t;
   unsigned i;
@@ -10383,8 +10373,6 @@ c_write_global_declarations (void)
   if (pch_file)
     return;
 
-  timevar_start (TV_PHASE_DEFERRED);
-
   /* Do the Objective-C stuff.  This is where all the Objective-C
      module stuff gets generated (symtab, class/protocol/selector
      lists etc).  */
@@ -10426,29 +10414,7 @@ c_write_global_declarations (void)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
-  timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
-
-  /* We're done parsing; proceed to optimize and emit assembly.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  symtab->finalize_compilation_unit ();
-
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_DBGINFO);
-
-  /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for globals.  */
-  if (!seen_error ())
-    {
-      timevar_push (TV_SYMOUT);
-      FOR_EACH_VEC_ELT (*all_translation_units, i, t)
-	c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
-      c_write_global_declarations_2 (BLOCK_VARS (ext_block));
-      timevar_pop (TV_SYMOUT);
-    }
-
   ext_block = NULL;
-  timevar_stop (TV_PHASE_DBGINFO);
 }
 
 /* Register reserved keyword WORD as qualifier for address space AS.  */
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index 92cf60f..8ab4e67 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -92,8 +92,6 @@ along with GCC; see the file COPYING3.  If not see
 
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
 
 /* Hooks for tree gimplification.  */
 #undef LANG_HOOKS_GIMPLIFY_EXPR
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 6004d50..7586813 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -669,7 +669,6 @@ extern enum machine_mode c_default_pointer_mode;
 
 /* In c-decl.c */
 extern void c_finish_incomplete_decl (tree);
-extern void c_write_global_declarations (void);
 extern tree c_omp_reduction_id (enum tree_code, tree);
 extern tree c_omp_reduction_decl (tree);
 extern tree c_omp_reduction_lookup (tree, tree);
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 246800e..c78e808 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -83,8 +83,8 @@ extern void cp_common_init_ts (void);
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION	cxx_print_error_function
 #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS cp_write_global_declarations
+#undef LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS
+#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS cxx_post_compilation_parsing_cleanups
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function
 #undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 19f5232..053058a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5370,7 +5370,7 @@ extern tree cp_reconstruct_complex_type		(tree, tree);
 extern bool attributes_naming_typedef_ok	(tree);
 extern void cplus_decl_attributes		(tree *, tree, int);
 extern void finish_anon_union			(tree);
-extern void cp_write_global_declarations	(void);
+extern void cxx_post_compilation_parsing_cleanups (void);
 extern tree coerce_new_type			(tree);
 extern tree coerce_delete_type			(tree);
 extern void comdat_linkage			(tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d8fb35e..8d6913c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -866,30 +866,19 @@ walk_namespaces (walk_namespaces_fn f, void* data)
   return walk_namespaces_r (global_namespace, f, data);
 }
 
-/* Call wrapup_globals_declarations for the globals in NAMESPACE.  If
-   DATA is non-NULL, this is the last time we will call
-   wrapup_global_declarations for this NAMESPACE.  */
+/* Call wrapup_globals_declarations for the globals in NAMESPACE.  */
 
 int
-wrapup_globals_for_namespace (tree name_space, void* data)
+wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
 {
   cp_binding_level *level = NAMESPACE_LEVEL (name_space);
   vec<tree, va_gc> *statics = level->static_decls;
   tree *vec = statics->address ();
   int len = statics->length ();
-  int last_time = (data != 0);
-
-  if (last_time)
-    {
-      check_global_declarations (vec, len);
-      emit_debug_global_declarations (vec, len);
-      return 0;
-    }
 
   /* Write out any globals that need to be output.  */
   return wrapup_global_declarations (vec, len);
 }
-
 \f
 /* In C++, you don't have to write `struct S' to refer to `S'; you
    can just use `S'.  We accomplish this by creating a TYPE_DECL as
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4be4847..28bf6e4 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4286,24 +4286,43 @@ dump_tu (void)
     }
 }
 
+/* Issue warnings for globals in NAME_SPACE (unused statics, etc) and
+   generate debug information for said globals.  */
+
+static int
+emit_debug_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
+{
+  cp_binding_level *level = NAMESPACE_LEVEL (name_space);
+  vec<tree, va_gc> *statics = level->static_decls;
+  tree *vec = statics->address ();
+  int len = statics->length ();
+
+  check_global_declarations (vec, len);
+  emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY);
+  return 0;
+}
+
+/* Candidates for Java hidden aliases.  */
+static hash_set<tree> *java_hidden_aliases;
+
+static location_t locus_at_end_of_parsing;
+
 /* This routine is called at the end of compilation.
    Its job is to create all the code needed to initialize and
    destroy the global aggregates.  We do the destruction
    first, since that way we only need to reverse the decls once.  */
 
 void
-cp_write_global_declarations (void)
+c_parse_final_cleanups (void)
 {
   tree vars;
   bool reconsider;
   size_t i;
-  location_t locus;
   unsigned ssdf_count = 0;
   int retries = 0;
   tree decl;
-  hash_set<tree> *candidates;
 
-  locus = input_location;
+  locus_at_end_of_parsing = input_location;
   at_eof = 1;
 
   /* Bad parse errors.  Just forget about it.  */
@@ -4335,8 +4354,6 @@ cp_write_global_declarations (void)
 
   /* FIXME - huh?  was  input_line -= 1;*/
 
-  timevar_start (TV_PHASE_DEFERRED);
-
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
@@ -4432,7 +4449,7 @@ cp_write_global_declarations (void)
 
 	  /* Set the line and file, so that it is obviously not from
 	     the source file.  */
-	  input_location = locus;
+	  input_location = locus_at_end_of_parsing;
 	  ssdf_body = start_static_storage_duration_function (ssdf_count);
 
 	  /* Make sure the back end knows about all the variables.  */
@@ -4458,7 +4475,7 @@ cp_write_global_declarations (void)
 
 	  /* Finish up the static storage duration function for this
 	     round.  */
-	  input_location = locus;
+	  input_location = locus_at_end_of_parsing;
 	  finish_static_storage_duration_function (ssdf_body);
 
 	  /* All those initializations and finalizations might cause
@@ -4466,7 +4483,7 @@ cp_write_global_declarations (void)
 	     instantiations, etc.  */
 	  reconsider = true;
 	  ssdf_count++;
-	  /* ??? was:  locus.line++; */
+	  /* ??? was:  locus_at_end_of_parsing.line++; */
 	}
 
       /* Now do the same for thread_local variables.  */
@@ -4632,12 +4649,13 @@ cp_write_global_declarations (void)
   if (priority_info_map)
     splay_tree_foreach (priority_info_map,
 			generate_ctor_and_dtor_functions_for_priority,
-			/*data=*/&locus);
+			/*data=*/&locus_at_end_of_parsing);
   else if (c_dialect_objc () && objc_static_init_needed_p ())
     /* If this is obj-c++ and we need a static init, call
        generate_ctor_or_dtor_function.  */
     generate_ctor_or_dtor_function (/*constructor_p=*/true,
-				    DEFAULT_INIT_PRIORITY, &locus);
+				    DEFAULT_INIT_PRIORITY,
+				    &locus_at_end_of_parsing);
 
   /* We're done with the splay-tree now.  */
   if (priority_info_map)
@@ -4651,10 +4669,7 @@ cp_write_global_declarations (void)
   pop_lang_context ();
 
   /* Collect candidates for Java hidden aliases.  */
-  candidates = collect_candidates_for_java_method_aliases ();
-
-  timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
+  java_hidden_aliases = collect_candidates_for_java_method_aliases ();
 
   if (flag_vtable_verify)
     {
@@ -4663,7 +4678,28 @@ cp_write_global_declarations (void)
       vtv_build_vtable_verify_fndecl ();
     }
 
-  symtab->finalize_compilation_unit ();
+  /* Issue warnings about static, but not defined, functions, etc, and
+     generate initial debug information.  */
+  walk_namespaces (emit_debug_for_namespace, 0);
+  if (vec_safe_length (pending_statics) != 0)
+    {
+      check_global_declarations (pending_statics->address (),
+				 pending_statics->length ());
+      emit_debug_global_declarations (pending_statics->address (),
+				      pending_statics->length (),
+				      EMIT_DEBUG_EARLY);
+    }
+
+}
+
+/* Perform any post compilation-proper cleanups for the C++ front-end.
+   This should really go away.  No front-end should need to do
+   anything past the compilation process.  */
+
+void
+cxx_post_compilation_parsing_cleanups (void)
+{
+  timevar_start (TV_PHASE_LATE_PARSING_CLEANUPS);
 
   if (flag_vtable_verify)
     {
@@ -4675,27 +4711,13 @@ cp_write_global_declarations (void)
       vtv_generate_init_routine ();
     }
 
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_CHECK_DBGINFO);
-
-  /* Now, issue warnings about static, but not defined, functions,
-     etc., and emit debugging information.  */
-  walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
-  if (vec_safe_length (pending_statics) != 0)
-    {
-      check_global_declarations (pending_statics->address (),
-				 pending_statics->length ());
-      emit_debug_global_declarations (pending_statics->address (),
-				      pending_statics->length ());
-    }
-
   perform_deferred_noexcept_checks ();
 
   /* Generate hidden aliases for Java.  */
-  if (candidates)
+  if (java_hidden_aliases)
     {
-      build_java_method_aliases (candidates);
-      delete candidates;
+      build_java_method_aliases (java_hidden_aliases);
+      delete java_hidden_aliases;
     }
 
   finish_repo ();
@@ -4709,13 +4731,13 @@ cp_write_global_declarations (void)
       dump_tree_statistics ();
       dump_time_statistics ();
     }
-  input_location = locus;
+  input_location = locus_at_end_of_parsing;
 
 #ifdef ENABLE_CHECKING
   validate_conversion_obstack ();
 #endif /* ENABLE_CHECKING */
 
-  timevar_stop (TV_PHASE_CHECK_DBGINFO);
+  timevar_stop (TV_PHASE_LATE_PARSING_CLEANUPS);
 }
 
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 45b3b99..92c218f 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3859,7 +3859,7 @@ do_namespace_alias (tree alias, tree name_space)
 
   /* Emit debug info for namespace alias.  */
   if (!building_stmt_list_p ())
-    (*debug_hooks->global_decl) (alias, /*early=*/false);
+    (*debug_hooks->early_global_decl) (alias);
 }
 
 /* Like pushdecl, only it places X in the current namespace,
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 208cec9..3cba2dd 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -325,7 +325,8 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
 static void dbxout_common_name (tree, const char *, stab_code_type);
 static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree, bool);
+static void dbxout_early_global_decl (tree);
+static void dbxout_late_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void debug_free_queue (void);
@@ -366,7 +367,8 @@ const struct gcc_debug_hooks dbx_debug_hooks =
 #endif
   debug_nothing_int,		         /* end_function */
   dbxout_function_decl,
-  dbxout_global_decl,		         /* global_decl */
+  dbxout_early_global_decl,		 /* early_global_decl */
+  dbxout_late_global_decl,		 /* late_global_decl */
   dbxout_type_decl,			 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -402,7 +404,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_tree,		         /* begin_function */
   xcoffout_end_function,
   debug_nothing_tree,		         /* function_decl */
-  dbxout_global_decl,		         /* global_decl */
+  dbxout_early_global_decl,		 /* early_global_decl */
+  dbxout_late_global_decl,		 /* late_global_decl */
   dbxout_type_decl,			 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -1317,10 +1320,16 @@ dbxout_function_decl (tree decl)
 
 #endif /* DBX_DEBUGGING_INFO  */
 
+static void
+dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  /* NYI for non-dwarf.  */
+}
+
 /* Debug information for a global DECL.  Called from toplev.c after
    compilation proper has finished.  */
 static void
-dbxout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED)
+dbxout_late_global_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
diff --git a/gcc/debug.c b/gcc/debug.c
index b5818de..449d3a1 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -43,7 +43,8 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_tree,		         /* begin_function */
   debug_nothing_int,		         /* end_function */
   debug_nothing_tree,		         /* function_decl */
-  debug_nothing_tree_bool,	         /* global_decl */
+  debug_nothing_tree,	         	 /* early_global_decl */
+  debug_nothing_tree,	         	 /* late_global_decl */
   debug_nothing_tree_int,		 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -71,12 +72,6 @@ debug_nothing_tree (tree decl ATTRIBUTE_UNUSED)
 }
 
 void
-debug_nothing_tree_bool (tree decl ATTRIBUTE_UNUSED,
-			 bool early ATTRIBUTE_UNUSED)
-{
-}
-
-void
 debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED,
 			 tree t2 ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/debug.h b/gcc/debug.h
index 9440515..ec387ca 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -92,12 +92,15 @@ struct gcc_debug_hooks
      function.  */
   void (* function_decl) (tree decl);
 
-  /* Debug information for a global DECL.  Called from toplev.c after
-     compilation proper has finished.  EARLY is true if global_decl()
-     is being called early on in the compilation process (i.e., before
-     cgraph information is available and before code is
-     generated).  */
-  void (* global_decl) (tree decl, bool early);
+  /* Debug information for a global DECL.  Called from the parser after
+     the parsing process has finished.  */
+  void (* early_global_decl) (tree decl);
+
+  /* Augment debug information generated by early_global_decl with
+     more complete debug info (if applicable).  Called from toplev.c
+     after the compilation proper has finished and cgraph information
+     is available.  */
+  void (* late_global_decl) (tree decl);
 
   /* Debug information for a type DECL.  Called from toplev.c after
      compilation proper, also from various language front ends to
@@ -159,7 +162,6 @@ extern void debug_nothing_int_charstar_int_bool (unsigned int, const char *,
 extern void debug_nothing_int (unsigned int);
 extern void debug_nothing_int_int (unsigned int, unsigned int);
 extern void debug_nothing_tree (tree);
-extern void debug_nothing_tree_bool (tree, bool);
 extern void debug_nothing_tree_tree (tree, tree);
 extern void debug_nothing_tree_int (tree, int);
 extern void debug_nothing_tree_tree_tree_bool (tree, tree, tree, bool);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ddc44f4..0ad8b5d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2430,7 +2430,8 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree, bool);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
@@ -2468,7 +2469,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_begin_function,
   dwarf2out_end_function,	/* end_function */
   dwarf2out_function_decl,	/* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,
+  dwarf2out_late_global_decl,
   dwarf2out_type_decl,		/* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,		/* deferred_inline_function */
@@ -2609,7 +2611,7 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
   /* Die is used and must not be pruned as unused.  */
   BOOL_BITFIELD die_perennial_p : 1;
   BOOL_BITFIELD comdat_type_p : 1; /* DIE has a type signature */
-  /* Die was generated early via dwarf2out_early_decl.  */
+  /* Die was generated early via dwarf2out_early_global_decl.  */
   BOOL_BITFIELD dumped_early : 1;
   /* Lots of spare bits.  */
 }
@@ -17721,12 +17723,12 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 				decl_quals (node_or_origin),
 				context_die);
 	}
+    add_location:
       if (origin == NULL && DECL_ARTIFICIAL (node))
 	add_AT_flag (parm_die, DW_AT_artificial, 1);
 
       if (node && node != origin)
         equate_decl_number_to_die (node, parm_die);
-    add_location:
       if (! DECL_ABSTRACT (node_or_origin))
 	add_location_or_const_value_attribute (parm_die, node_or_origin,
 					       node == NULL, DW_AT_location);
@@ -20817,29 +20819,64 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from
-   toplev.c after compilation proper has finished.
+/* Output initial debug information for global DECL.  Called from the
+   end of the parsing process.
 
-   dwarf2out_decl() will be called twice on each global symbol: once
-   immediately after parsing (EARLY=true), and once after the full
-   compilation has finished (EARLY=false).  There are checks in
-   dwarf2out_decl() to make sure that if we have a DECL DIE upon
-   entry, that the previously created DIE is reused.  No new DECL DIEs
-   should be created when EARLY=false.
-
-   The second time dwarf2out_decl() is called (or for that matter, the
-   second time any DECL DIE is seen throughout dwarf2out), only
-   information not previously available (e.g. location) is tacked onto
-   the early dumped DIE.  That's the plan anyhow ;-).  */
+   This is the initial debug generation process.  As such, the DIEs
+   generated may be incomplete.  A later debug generation pass
+   (dwarf2out_late_global_decl) will augment the information generated
+   in this pass (e.g., with complete location info).  */
 
 static void
-dwarf2out_global_decl (tree decl, bool early)
+dwarf2out_early_global_decl (tree decl)
 {
-  if (early)
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
     {
-      dwarf2out_early_decl (decl);
-      return;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+	{
+	  /* A missing cfun means the symbol is unused and was removed
+	     from the callgraph.  */
+	  if (!DECL_STRUCT_FUNCTION (decl))
+	    goto early_decl_exit;
+
+	  push_cfun (DECL_STRUCT_FUNCTION (decl));
+	  current_function_decl = decl;
+	}
+      dw_die_ref die = dwarf2out_decl (decl);
+      if (die)
+	die->dumped_early = true;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+	{
+	  pop_cfun ();
+	  current_function_decl = NULL;
+	}
     }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+  return;
+}
+
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.  */
+
+static void
+dwarf2out_late_global_decl (tree decl)
+{
   /* Output DWARF2 information for file-scope tentative data object
      declarations, file-scope (extern) function declarations (which
      had no corresponding body) and file-scope tagged type declarations
@@ -21041,11 +21078,7 @@ dwarf2out_decl (tree decl)
      We should always be reusing DIEs created early.  */
   dw_die_ref early_die = NULL;
   if (decl_die_table)
-    {
-      early_die = lookup_decl_die (decl);
-      if (early_die && !early_die->dumped_early)
-	early_die = NULL;
-    }
+    early_die = lookup_decl_die (decl);
 #endif
 
   switch (TREE_CODE (decl))
@@ -21176,57 +21209,12 @@ dwarf2out_decl (tree decl)
 #ifdef ENABLE_CHECKING
   /* If we early created a DIE, make sure it didn't get re-created by
      mistake.  */
-  gcc_assert (!early_die || early_die == die);
+  if (early_die && early_die->dumped_early)
+    gcc_assert (early_die == die);
 #endif
   return die;
 }
 
-/* Early dumping of DECLs before we lose language data.  */
-
-void
-dwarf2out_early_decl (tree decl)
-{
-  /* gen_decl_die() will set DECL_ABSTRACT because
-     cgraph_function_possibly_inlined_p() returns true.  This is in
-     turn will cause DW_AT_inline attributes to be set.
-
-     This happens because at early dwarf generation, there is no
-     cgraph information, causing cgraph_function_possibly_inlined_p()
-     to return true.  Trick cgraph_function_possibly_inlined_p()
-     while we generate dwarf early.  */
-  bool save = symtab->global_info_ready;
-  symtab->global_info_ready = true;
-
-  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
-     other DECLs and they can point to template types or other things
-     that dwarf2out can't handle when done via dwarf2out_decl.  */
-  if (TREE_CODE (decl) != TYPE_DECL
-      && TREE_CODE (decl) != PARM_DECL)
-    {
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	{
-	  /* A missing cfun means the symbol is unused and was removed
-	     from the callgraph.  */
-	  if (!DECL_STRUCT_FUNCTION (decl))
-	    goto early_decl_exit;
-
-	  push_cfun (DECL_STRUCT_FUNCTION (decl));
-	  current_function_decl = decl;
-	}
-      dw_die_ref die = dwarf2out_decl (decl);
-      if (die)
-	die->dumped_early = true;
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	{
-	  pop_cfun ();
-	  current_function_decl = NULL;
-	}
-    }
- early_decl_exit:
-  symtab->global_info_ready = save;
-  return;
-}
-
 /* Write the debugging output for DECL.  */
 
 static void
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index da3a0d0..ef0faac 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -81,7 +81,6 @@ static bool global_bindings_p (void);
 /* Each front end provides its own.  */
 static bool gfc_init (void);
 static void gfc_finish (void);
-static void gfc_write_global_declarations (void);
 static void gfc_be_parse_file (void);
 static alias_set_type gfc_get_alias_set (tree);
 static void gfc_init_ts (void);
@@ -108,7 +107,6 @@ static const struct attribute_spec gfc_attribute_table[] =
 #undef LANG_HOOKS_NAME
 #undef LANG_HOOKS_INIT
 #undef LANG_HOOKS_FINISH
-#undef LANG_HOOKS_WRITE_GLOBALS
 #undef LANG_HOOKS_OPTION_LANG_MASK
 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
 #undef LANG_HOOKS_INIT_OPTIONS
@@ -142,7 +140,6 @@ static const struct attribute_spec gfc_attribute_table[] =
 #define LANG_HOOKS_NAME                 "GNU Fortran"
 #define LANG_HOOKS_INIT                 gfc_init
 #define LANG_HOOKS_FINISH               gfc_finish
-#define LANG_HOOKS_WRITE_GLOBALS	gfc_write_global_declarations
 #define LANG_HOOKS_OPTION_LANG_MASK	gfc_option_lang_mask
 #define LANG_HOOKS_INIT_OPTIONS_STRUCT  gfc_init_options_struct
 #define LANG_HOOKS_INIT_OPTIONS         gfc_init_options
@@ -220,6 +217,19 @@ gfc_be_parse_file (void)
   /* Clear the binding level stack.  */
   while (!global_bindings_p ())
     poplevel (0, 0);
+
+  /* Finalize all of the globals.
+
+     Emulated tls lowering needs to see all TLS variables before we
+     call finalize_compilation_unit.  The C/C++ front ends manage this
+     by calling decl_rest_of_compilation on each global and static
+     variable as they are seen.  The Fortran front end waits until
+     here.  */
+  for (tree decl = getdecls (); decl ; decl = DECL_CHAIN (decl))
+    rest_of_decl_compilation (decl, true, true);
+
+  /* Do the debug dance.  */
+  global_decl_processing_and_early_debug ();
 }
 
 
@@ -263,32 +273,6 @@ gfc_finish (void)
   return;
 }
 
-/* ??? This is something of a hack.
-
-   Emulated tls lowering needs to see all TLS variables before we call
-   finalize_compilation_unit.  The C/C++ front ends manage this
-   by calling decl_rest_of_compilation on each global and static variable
-   as they are seen.  The Fortran front end waits until this hook.
-
-   A Correct solution is for finalize_compilation_unit not to be
-   called during the WRITE_GLOBALS langhook, and have that hook only do what
-   its name suggests and write out globals.  But the C++ and Java front ends
-   have (unspecified) problems with aliases that gets in the way.  It has
-   been suggested that these problems would be solved by completing the
-   conversion to cgraph-based aliases.  */
-
-static void
-gfc_write_global_declarations (void)
-{
-  tree decl;
-
-  /* Finalize all of the globals.  */
-  for (decl = getdecls(); decl ; decl = DECL_CHAIN (decl))
-    rest_of_decl_compilation (decl, true, true);
-
-  write_global_declarations ();
-}
-
 /* These functions and variables deal with binding contours.  We only
    need these functions for the list of PARM_DECLs, but we leave the
    functions more general; these are a simplified version of the
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 38e6f99..0c7f50e 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4693,7 +4693,7 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym)
 					      TREE_TYPE (decl),
 					      sym->attr.dimension,
 					      false, false);
-  debug_hooks->global_decl (decl, /*early=*/false);
+  debug_hooks->early_global_decl (decl);
 }
 
 
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 6bac84f..6d65e92 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -2915,7 +2915,8 @@ Gcc_backend::lookup_builtin(const std::string& name)
 }
 
 // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
-// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
+// FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
+// emit early debugging information.
 
 void
 Gcc_backend::write_global_definitions(
@@ -2988,10 +2989,15 @@ Gcc_backend::write_global_definitions(
 
   wrapup_global_declarations(defs, i);
 
-  symtab->finalize_compilation_unit();
+  emit_debug_global_declarations (defs, i, EMIT_DEBUG_EARLY);
 
+  /* ?? Can we leave this call here, thus getting called before
+     finalize_compilation_unit?
+
+     Originally this was called *AFTER* finalize_compilation_unit.  If
+     `go' really needs this call after finalize_compilation_unit, we
+     can use LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS (yuck).  */
   check_global_declarations(defs, i);
-  emit_debug_global_declarations(defs, i);
 
   delete[] defs;
 }
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 24b6437..e8412ac 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -284,6 +284,9 @@ go_langhook_parse_file (void)
 {
   go_parse_input_files (in_fnames, num_in_fnames, flag_syntax_only,
 			go_require_return_statement);
+
+  /* Final processing of globals and early debug info generation.  */
+  go_write_globals ();
 }
 
 static tree
@@ -429,14 +432,6 @@ go_langhook_getdecls (void)
   return NULL;
 }
 
-/* Write out globals.  */
-
-static void
-go_langhook_write_globals (void)
-{
-  go_write_globals ();
-}
-
 /* Go specific gimplification.  We need to gimplify
    CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle
    it.  */
@@ -534,7 +529,6 @@ go_localize_identifier (const char *ident)
 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
 #undef LANG_HOOKS_PUSHDECL
 #undef LANG_HOOKS_GETDECLS
-#undef LANG_HOOKS_WRITE_GLOBALS
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #undef LANG_HOOKS_EH_PERSONALITY
 
@@ -551,7 +545,6 @@ go_localize_identifier (const char *ident)
 #define LANG_HOOKS_GLOBAL_BINDINGS_P	go_langhook_global_bindings_p
 #define LANG_HOOKS_PUSHDECL		go_langhook_pushdecl
 #define LANG_HOOKS_GETDECLS		go_langhook_getdecls
-#define LANG_HOOKS_WRITE_GLOBALS	go_langhook_write_globals
 #define LANG_HOOKS_GIMPLIFY_EXPR	go_langhook_gimplify_expr
 #define LANG_HOOKS_EH_PERSONALITY	go_langhook_eh_personality
 
diff --git a/gcc/godump.c b/gcc/godump.c
index 01f8410..ea89ed6 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -493,12 +493,18 @@ go_function_decl (tree decl)
   go_decl (decl);
 }
 
+static void
+go_early_global_decl (tree decl)
+{
+  real_debug_hooks->early_global_decl (decl);
+}
+
 /* A global variable decl.  */
 
 static void
-go_global_decl (tree decl, bool early)
+go_late_global_decl (tree decl)
 {
-  real_debug_hooks->global_decl (decl, early);
+  real_debug_hooks->late_global_decl (decl);
   go_decl (decl);
 }
 
@@ -1240,7 +1246,8 @@ dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
   go_debug_hooks.define = go_define;
   go_debug_hooks.undef = go_undef;
   go_debug_hooks.function_decl = go_function_decl;
-  go_debug_hooks.global_decl = go_global_decl;
+  go_debug_hooks.early_global_decl = go_early_global_decl;
+  go_debug_hooks.late_global_decl = go_late_global_decl;
   go_debug_hooks.type_decl = go_type_decl;
 
   macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 0d51165..dd1d53d 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -3267,17 +3267,4 @@ in_same_package (tree name1, tree name2)
   return (pkg1 == pkg2);
 }
 
-/* lang_hooks.decls.final_write_globals: perform final processing on
-   global variables.  */
-
-void
-java_write_globals (void)
-{
-  tree *vec = vec_safe_address (pending_static_fields);
-  int len = vec_safe_length (pending_static_fields);
-  write_global_declarations ();
-  emit_debug_global_declarations (vec, len);
-  vec_free (pending_static_fields);
-}
-
 #include "gt-java-class.h"
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index e832f44..cca5f70 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -1176,8 +1176,6 @@ int cxx_keyword_p (const char *name, int length);
 
 extern GTY(()) vec<tree, va_gc> *pending_static_fields;
 
-extern void java_write_globals (void);   
-
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
 /* Access flags etc for a method (a FUNCTION_DECL): */
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 9c4a9cf..0abfff7 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "bitmap.h"
 #include "target.h"
 #include "wide-int.h"
+#include "toplev.h"
 
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
@@ -1980,6 +1981,13 @@ java_parse_file (void)
   /* Arrange for any necessary initialization to happen.  */
   java_emit_static_constructor ();
   gcc_assert (global_bindings_p ());
+
+  /* Do final processing on globals and emit early debug information.  */
+  tree *vec = vec_safe_address (pending_static_fields);
+  int len = vec_safe_length (pending_static_fields);
+  global_decl_processing_and_early_debug ();
+  emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY);
+  vec_free (pending_static_fields);
 }
 
 
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 8a68691..be6c4c7 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -142,8 +142,6 @@ struct GTY(()) language_function {
 #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name
 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION	java_print_error_function
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS java_write_globals
 
 #undef LANG_HOOKS_TYPE_FOR_MODE
 #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index e77d2d9..7d3903f 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -204,7 +204,7 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_GETDECLS	getdecls
 #define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
-#define LANG_HOOKS_WRITE_GLOBALS write_global_declarations
+#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL	lhd_decl_ok_for_sibcall
 #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
@@ -228,7 +228,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
   LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
   LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
-  LANG_HOOKS_WRITE_GLOBALS, \
+  LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
   LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
   LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
   LANG_HOOKS_OMP_PREDETERMINED_SHARING, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 8ff91ba..dfc3ab6 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -290,15 +290,16 @@ lhd_decl_ok_for_sibcall (const_tree decl ATTRIBUTE_UNUSED)
   return true;
 }
 
-/* lang_hooks.decls.final_write_globals: perform final processing on
-   global variables.  */
+/* Generic global declaration processing and early debug generation.
+   This is meant to be called by the front-ends at the end of parsing.
+   C/C++ do their own thing, but other front-ends may call this.  */
+
 void
-write_global_declarations (void)
+global_decl_processing_and_early_debug (void)
 {
   tree globals, decl, *vec;
   int len, i;
 
-  timevar_start (TV_PHASE_DEFERRED);
   /* Really define vars that have had only a tentative definition.
      Really output inline functions that must actually be callable
      and have not been output so far.  */
@@ -315,19 +316,9 @@ write_global_declarations (void)
 
   wrapup_global_declarations (vec, len);
   check_global_declarations (vec, len);
-  timevar_stop (TV_PHASE_DEFERRED);
-
-  timevar_start (TV_PHASE_OPT_GEN);
-  /* This lang hook is dual-purposed, and also finalizes the
-     compilation unit.  */
-  symtab->finalize_compilation_unit ();
-  timevar_stop (TV_PHASE_OPT_GEN);
 
-  timevar_start (TV_PHASE_DBGINFO);
-  emit_debug_global_declarations (vec, len);
-  timevar_stop (TV_PHASE_DBGINFO);
+  emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY);
 
-  /* Clean up.  */
   free (vec);
 }
 
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 72fa85e..40cfdbc 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -181,9 +181,11 @@ struct lang_hooks_for_decls
      We will already have checked that it has static binding.  */
   bool (*warn_unused_global) (const_tree);
 
-  /* Obtain a list of globals and do final output on them at end
-     of compilation */
-  void (*final_write_globals) (void);
+  /* Perform any post compilation-proper parser cleanups and
+     processing.  This is currently only needed for the C++ parser,
+     which hopefully can be cleaned up so this hook is no longer
+     necessary.  */
+  void (*post_compilation_parsing_cleanups) (void);
 
   /* True if this decl may be called via a sibcall.  */
   bool (*ok_for_sibcall) (const_tree);
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 1f39949..88fd46c 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1083,19 +1083,6 @@ lto_getdecls (void)
   return NULL_TREE;
 }
 
-static void
-lto_write_globals (void)
-{
-  if (flag_wpa)
-    return;
-
-  /* Output debug info for global variables.  */  
-  varpool_node *vnode;
-  FOR_EACH_DEFINED_VARIABLE (vnode)
-    if (!decl_function_context (vnode->decl))
-      debug_hooks->global_decl (vnode->decl, /*early=*/false);
-}
-
 static tree
 lto_builtin_function (tree decl)
 {
@@ -1275,8 +1262,6 @@ static void lto_init_ts (void)
 #define LANG_HOOKS_PUSHDECL lto_pushdecl
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lto_getdecls
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS lto_write_globals
 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lto_register_builtin_type
 #undef LANG_HOOKS_BUILTIN_FUNCTION
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index df59981..f79a1ce 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -417,8 +417,7 @@ objc_init (void)
   return true;
 }
 
-/* This is called automatically (at the very end of compilation) by
-   c_write_global_declarations and cp_write_global_declarations.  */
+/* This is called at the end of parsing by the C/C++ parsers.  */
 void
 objc_write_global_declarations (void)
 {
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index d81b184..a7d2f67 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -119,7 +119,8 @@ static void sdbout_begin_block		(unsigned int, unsigned int);
 static void sdbout_end_block		(unsigned int, unsigned int);
 static void sdbout_source_line		(unsigned int, const char *, int, bool);
 static void sdbout_end_epilogue		(unsigned int, const char *);
-static void sdbout_global_decl		(tree, bool);
+static void sdbout_early_global_decl	(tree);
+static void sdbout_late_global_decl	(tree);
 static void sdbout_begin_prologue	(unsigned int, const char *);
 static void sdbout_end_prologue		(unsigned int, const char *);
 static void sdbout_begin_function	(tree);
@@ -294,7 +295,8 @@ const struct gcc_debug_hooks sdb_debug_hooks =
   sdbout_begin_function,	         /* begin_function */
   sdbout_end_function,		         /* end_function */
   debug_nothing_tree,		         /* function_decl */
-  sdbout_global_decl,		         /* global_decl */
+  sdbout_early_global_decl,		 /* early_global_decl */
+  sdbout_late_global_decl,		 /* late_global_decl */
   sdbout_symbol,			 /* type_decl */
   debug_nothing_tree_tree_tree_bool,	 /* imported_module_or_decl */
   debug_nothing_tree,		         /* deferred_inline_function */
@@ -1417,11 +1419,17 @@ sdbout_reg_parms (tree parms)
       }
 }
 
+static void
+sdbout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  /* NYI for non-dwarf.  */
+}
+
 /* Output debug information for a global DECL.  Called from toplev.c
    after compilation proper has finished.  */
 
 static void
-sdbout_global_decl (tree decl, bool early ATTRIBUTE_UNUSED)
+sdbout_late_global_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL
       && !DECL_EXTERNAL (decl)
diff --git a/gcc/timevar.def b/gcc/timevar.def
index a04d05c..d9d95de 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -31,11 +31,16 @@
 
 /* The total execution time.  */
 DEFTIMEVAR (TV_TOTAL                 , "total time")
-/* The compiler phases.  These must be mutually exclusive.
-   Ideally, they would sum to near the total time.  */
+/* The compiler phases.
+
+   These must be mutually exclusive, and the NAME field must begin
+   with "phase".
+
+   Also, their sum must be within a millionth of the total time (see
+   validate_phases).  */
 DEFTIMEVAR (TV_PHASE_SETUP           , "phase setup")
 DEFTIMEVAR (TV_PHASE_PARSING         , "phase parsing")
-DEFTIMEVAR (TV_PHASE_DEFERRED        , "phase lang. deferred")
+DEFTIMEVAR (TV_PHASE_LATE_PARSING_CLEANUPS, "phase late parsing cleanups")
 DEFTIMEVAR (TV_PHASE_OPT_GEN         , "phase opt and generate")
 DEFTIMEVAR (TV_PHASE_DBGINFO         , "phase debug info")
 DEFTIMEVAR (TV_PHASE_CHECK_DBGINFO   , "phase check & debug info")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ceefa1b..2347d6c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -519,10 +519,13 @@ check_global_declarations (tree *v, int len)
     check_global_declaration_1 (v[i]);
 }
 
-/* Emit debugging information for all global declarations in VEC.  */
+/* Emit debugging information for all global declarations in VEC.
+   WHEN is either EMIT_DEBUG_EARLY or EMIT_DEBUG_LATE depending on if
+   we are generating early debug (at the end of parsing), or the late
+   (post compilation) version.  */
 
 void
-emit_debug_global_declarations (tree *vec, int len)
+emit_debug_global_declarations (tree *vec, int len, enum emit_debug when)
 {
   int i;
 
@@ -532,7 +535,14 @@ emit_debug_global_declarations (tree *vec, int len)
 
   timevar_push (TV_SYMOUT);
   for (i = 0; i < len; i++)
-    debug_hooks->global_decl (vec[i], /*early=*/false);
+    {
+      if (when == EMIT_DEBUG_EARLY)
+	debug_hooks->early_global_decl (vec[i]);
+      else if (when == EMIT_DEBUG_LATE)
+	debug_hooks->late_global_decl (vec[i]);
+      else
+	gcc_unreachable ();
+    }
   timevar_pop (TV_SYMOUT);
 }
 
@@ -545,8 +555,7 @@ compile_file (void)
   timevar_start (TV_PHASE_PARSING);
   timevar_push (TV_PARSE_GLOBAL);
 
-  /* Call the parser, which parses the entire file (calling
-     rest_of_compilation for each function).  */
+  /* Parse entire file and generate initial debug information.  */
   lang_hooks.parse_file ();
 
   timevar_pop (TV_PARSE_GLOBAL);
@@ -560,12 +569,33 @@ compile_file (void)
 
   ggc_protect_identifiers = false;
 
-  /* This must also call finalize_compilation_unit.  */
-  lang_hooks.decls.final_write_globals ();
+  /* Run the actual compilation process.  */
+  if (!in_lto_p)
+    {
+      timevar_start (TV_PHASE_OPT_GEN);
+      symtab->finalize_compilation_unit ();
+      timevar_stop (TV_PHASE_OPT_GEN);
+    }
+
+  /* Perform any post compilation-proper parser cleanups and
+     processing.  This is currently only needed for the C++ parser,
+     which can be hopefully cleaned up so this hook is no longer
+     necessary.  */
+  if (lang_hooks.decls.post_compilation_parsing_cleanups)
+    lang_hooks.decls.post_compilation_parsing_cleanups ();
 
   if (seen_error ())
     return;
 
+  /* After the parser has generated debugging information, augment
+     this information with any new location/etc information that may
+     have become available after the compilation proper.  */
+  timevar_start (TV_PHASE_DBGINFO);
+  symtab_node *node;
+  FOR_EACH_DEFINED_SYMBOL (node)
+    debug_hooks->late_global_decl (node->decl);
+  timevar_stop (TV_PHASE_DBGINFO);
+
   timevar_start (TV_PHASE_LATE_ASM);
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
diff --git a/gcc/toplev.h b/gcc/toplev.h
index 1b54578..ff1fd9d 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -42,8 +42,14 @@ extern bool wrapup_global_declaration_2 (tree);
 extern bool wrapup_global_declarations (tree *, int);
 extern void check_global_declaration_1 (tree);
 extern void check_global_declarations (tree *, int);
-extern void emit_debug_global_declarations (tree *, int);
-extern void write_global_declarations (void);
+
+enum emit_debug {
+  EMIT_DEBUG_EARLY,
+  EMIT_DEBUG_LATE
+};
+extern void emit_debug_global_declarations (tree *, int, enum emit_debug);
+
+extern void global_decl_processing_and_early_debug (void);
 
 extern void dump_memory_report (bool);
 extern void dump_profile_report (void);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index ad474a5..9100cd1 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4494,9 +4494,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
   return successfully_inlined;
 }
 
-/* Expand call statements reachable from STMT_P.
-   We can only have CALL_EXPRs as the "toplevel" tree code or nested
-   in a MODIFY_EXPR.  */
+/* Expand call statements in BB when profitable.  */
 
 static bool
 gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
diff --git a/gcc/tree.c b/gcc/tree.c
index 8e9876e..9c7251c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5089,6 +5089,8 @@ free_lang_data_in_decl (tree decl)
 	 At this point, it is not needed anymore.  */
       DECL_SAVED_TREE (decl) = NULL_TREE;
 
+      /* ?? This should be OK to remove now that we are generating dwarf
+	 early.  */
       /* Clear the abstract origin if it refers to a method.  Otherwise
          dwarf2out.c will ICE as we clear TYPE_METHODS and thus the
 	 origin will not be output correctly.  */
@@ -5630,7 +5632,11 @@ free_lang_data (void)
   unsigned i;
 
   /* If we are the LTO frontend we have freed lang-specific data already.  */
-  if (in_lto_p)
+  if (in_lto_p
+      /* FIXME: Eventually we need to remove this so the function
+	 proceeds and we can be sure there is no language specific
+	 data past cgraph.  */
+      || !flag_generate_lto)
     return 0;
 
   /* Allocate and assign alias sets to the standard integer types
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 2ad9e9b..b0c305f 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -163,7 +163,8 @@ static void vmsdbgout_begin_epilogue (unsigned int, const char *);
 static void vmsdbgout_end_epilogue (unsigned int, const char *);
 static void vmsdbgout_begin_function (tree);
 static void vmsdbgout_decl (tree);
-static void vmsdbgout_global_decl (tree, bool);
+static void vmsdbgout_early_global_decl (tree);
+static void vmsdbgout_late_global_decl (tree);
 static void vmsdbgout_type_decl (tree, int);
 static void vmsdbgout_abstract_function (tree);
 
@@ -188,7 +189,8 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
    vmsdbgout_begin_function,
    vmsdbgout_end_function,
    vmsdbgout_decl,
-   vmsdbgout_global_decl,
+   vmsdbgout_early_global_decl,
+   vmsdbgout_late_global_decl,
    vmsdbgout_type_decl,		  /* type_decl */
    debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
    debug_nothing_tree,		  /* deferred_inline_function */
@@ -1510,10 +1512,18 @@ vmsdbgout_decl (tree decl)
 /* Not implemented in VMS Debug.  */
 
 static void
-vmsdbgout_global_decl (tree decl, bool early)
+vmsdbgout_early_global_decl (tree decl)
+{
+  /* NYI for non-dwarf.  */
+}
+
+/* Not implemented in VMS Debug.  */
+
+static void
+vmsdbgout_late_global_decl (tree decl)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
-    (*dwarf2_debug_hooks.global_decl) (decl, early);
+    (*dwarf2_debug_hooks.late_global_decl) (decl);
 }
 
 /* Not implemented in VMS Debug.  */

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12  0:51                   ` Aldy Hernandez
@ 2014-09-12  8:13                     ` Richard Biener
  2014-09-12 15:15                     ` Jason Merrill
  1 sibling, 0 replies; 40+ messages in thread
From: Richard Biener @ 2014-09-12  8:13 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches

On Fri, Sep 12, 2014 at 2:51 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/09/14 02:16, Richard Biener wrote:
>>
>> On Tue, Sep 9, 2014 at 2:00 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>>>
>>> On 09/05/14 02:00, Richard Biener wrote:
>
>
>>> What I have in mind is:
>>>
>>> 1. Move the FE specific things that come before the call to
>>> finalize_compilation_unit currently in each LANG_HOOKS_WRITE_GLOBALS,
>>> into
>>> the FE proper (lang_hooks.parse_file).  This may or may not mean calling
>>> {wrapup,check}_global_declarations directly from the FEs since some FE's
>>> call these in a sufficiently different order to merit everyone doing
>>> their
>>> own thing (not sure though).
>
>
> Done.
>
>>>
>>> 2. Generate debug information by gathering the list of globals with
>>> lang_hooks.decls.getdecls (??) and then doing
>>> debug_hooks->early_global_decl() as discussed.
>>
>>
>> Or move that also to lang_hooks.parse_file?  ISTR
>> lang_hooks.decls.getdecls
>> is sort of an "alternative" hook to write_global_declarations that is only
>> used by the generic implementation of write_global_declarations.
>
>
> Done.
>
>>
>> So if we move everything else but calling debug_hooks->early_global_decl
>> ()
>> out of the write_global_declarations langhook then we could indeed
>> remove that hook and implement getdecls everywhere.
>>
>> I suppose one of the hooks should go in the end.
>>
>>> 2. Call finalize_compilation_unit() directly from compile_file().
>
>
> Done.
>
>>
>> Great!
>>
>>> 3. Call some (new) hook for C++ stuff after finalize_compilation_unit
>>> (???).
>>
>>
>> Or fix the C++ stuff to work properly in a symtab way?  I suppose as
>> an intermediate step adding a new langhook for this on the branch is ok
>> but I'd rather not get that merged into trunk.
>
>
> Done.  For now I've called it LANG_HOOK_POST_COMPILATION_PARSING_CLEANUPS,
> and it is only applicable to C++, unless some other FE acts up in the
> process and needs similar massaging.
>
>> Maybe Jason can help cleaning this up.
>
>
> Jason's not much of a beer drinker AFAICT, so I'm trying to come up with a
> suitable bribe.

I'm sure you can come up with something ;)

>>
>>> 4. FOR_EACH_DEFINED_SYMBOL (node)
>>>       debug_hooks->late_global_decl (node->decl)
>>>
>>>     as suggested.
>
>
> Done.
>
> [Well... as DONE as a prototype can be :).  This is a work in progress, but
> I'd like y'all to peek at it, to make sure I'm not making obvious wrong
> turns that will have me rewriting code months from now, and hating you in
> the process.  And by you, I mean Jason *and* you.  I don't want anyone to
> feel left out by my frustration and anger.]
>
> I drafted what I want Ada, Java, Fortran, and Go to look like (as well as
> the obvious C/C++ languages).
>
> For C, guality.exp exhibits less failures than mainline.  I'm currently
> debugging inline virtual C++ destructors.  It seems the inliner can also
> call generate debugging info (debug_hooks->outlining_inline_function). The
> rest of the languages are tested as far as building jc1/f951/go1 with no
> warnings :-))).
>
> There are various cleanups and comments along the way.
>
> Let me know if you're "mostly" OK with this, so I can push this to the
> branch and continue iterating with you incrementally.  It seems there will
> be no shortage of weird bugs in dwarf generation due to the fact that we
> stream early.  I'm hoping to start concentrating on those...

Yeah, it looks very good.  Let's cross fingers that it'll work ;)

Thanks,
Richard.

> As usual, thanks.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12  0:51                   ` Aldy Hernandez
  2014-09-12  8:13                     ` Richard Biener
@ 2014-09-12 15:15                     ` Jason Merrill
  2014-09-12 17:11                       ` Aldy Hernandez
  2014-12-18 19:26                       ` Aldy Hernandez
  1 sibling, 2 replies; 40+ messages in thread
From: Jason Merrill @ 2014-09-12 15:15 UTC (permalink / raw)
  To: Aldy Hernandez, Richard Biener; +Cc: gcc-patches

On 09/11/2014 08:51 PM, Aldy Hernandez wrote:
> -  timevar_start (TV_PHASE_DEFERRED);

> -  timevar_stop (TV_PHASE_DEFERRED);
> -  timevar_start (TV_PHASE_OPT_GEN);

Why?

>    /* Generate hidden aliases for Java.  */
> -  if (candidates)
> +  if (java_hidden_aliases)
>      {
> -      build_java_method_aliases (candidates);
> -      delete candidates;
> +      build_java_method_aliases (java_hidden_aliases);
> +      delete java_hidden_aliases;
>      }

Didn't it work to move this before finalize?  I think the VTV stuff is 
all that really needs to come after it, and that can move out of the 
front end if this hook is a problem (which I don't really think it is).

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 15:15                     ` Jason Merrill
@ 2014-09-12 17:11                       ` Aldy Hernandez
  2014-09-12 17:33                         ` Jason Merrill
  2014-09-15  9:32                         ` Richard Biener
  2014-12-18 19:26                       ` Aldy Hernandez
  1 sibling, 2 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-12 17:11 UTC (permalink / raw)
  To: Jason Merrill, Richard Biener; +Cc: gcc-patches

On 09/12/14 08:15, Jason Merrill wrote:
> On 09/11/2014 08:51 PM, Aldy Hernandez wrote:
>> -  timevar_start (TV_PHASE_DEFERRED);
>
>> -  timevar_stop (TV_PHASE_DEFERRED);
>> -  timevar_start (TV_PHASE_OPT_GEN);
>
> Why?

TV_PHASE_OPT_GEN is now in compile_file(), where we call 
finalize_compilation_unit directly.

TV_PHASE_DEFERRED, on the other hand, is a bit problematic because it 
was originally wrapping the code inside LANG_HOOKS_WRITE_GLOBALS, which 
will now reside inside the parser (and is thus included in 
TV_PHASE_PARSING now).  Originally it was mutually exclusive with 
TV_PHASE_PARSING, but now resides within the parser, so I decided to get 
rid of it since it's all technically in the parser.

There is code in timevar*.c that makes sure that TV_PHASE_* elapsed 
times add up to the total time.  So we either get rid of 
TV_PHASE_DEFERRED and include its time in TV_PHASE_PARSING (avoiding 
double counting), or we include a separate, non PHASE timer for it, with 
timevar_push(TV_blah) where "blah" is NOT "PHASE".

Up to you, but I'm highly in favor of getting rid of things ;-).

>
>>    /* Generate hidden aliases for Java.  */
>> -  if (candidates)
>> +  if (java_hidden_aliases)
>>      {
>> -      build_java_method_aliases (candidates);
>> -      delete candidates;
>> +      build_java_method_aliases (java_hidden_aliases);
>> +      delete java_hidden_aliases;
>>      }
>
> Didn't it work to move this before finalize?  I think the VTV stuff is
> all that really needs to come after it, and that can move out of the
> front end if this hook is a problem (which I don't really think it is).

I was too chicken to try.  I will do so as a follow up.

I am committing the patch to the branch, and will address both issues 
you speak of in followups.  Let me know what you prefer for the timevar 
issue.

Thanks.
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 17:11                       ` Aldy Hernandez
@ 2014-09-12 17:33                         ` Jason Merrill
  2014-09-12 17:48                           ` Aldy Hernandez
  2014-09-15  9:32                         ` Richard Biener
  1 sibling, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2014-09-12 17:33 UTC (permalink / raw)
  To: Aldy Hernandez, Richard Biener; +Cc: gcc-patches

On 09/12/2014 01:10 PM, Aldy Hernandez wrote:
> TV_PHASE_DEFERRED, on the other hand, is a bit problematic because it
> was originally wrapping the code inside LANG_HOOKS_WRITE_GLOBALS, which
> will now reside inside the parser (and is thus included in
> TV_PHASE_PARSING now).  Originally it was mutually exclusive with
> TV_PHASE_PARSING, but now resides within the parser, so I decided to get
> rid of it since it's all technically in the parser.
>
> There is code in timevar*.c that makes sure that TV_PHASE_* elapsed
> times add up to the total time.  So we either get rid of
> TV_PHASE_DEFERRED and include its time in TV_PHASE_PARSING (avoiding
> double counting), or we include a separate, non PHASE timer for it, with
> timevar_push(TV_blah) where "blah" is NOT "PHASE".

Why can't it keep the same name and just timevar_push/pop instead of 
timevar_start/stop?

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 17:33                         ` Jason Merrill
@ 2014-09-12 17:48                           ` Aldy Hernandez
  2014-09-12 17:56                             ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-12 17:48 UTC (permalink / raw)
  To: Jason Merrill, Richard Biener; +Cc: gcc-patches

On 09/12/14 10:33, Jason Merrill wrote:
> On 09/12/2014 01:10 PM, Aldy Hernandez wrote:
>> TV_PHASE_DEFERRED, on the other hand, is a bit problematic because it
>> was originally wrapping the code inside LANG_HOOKS_WRITE_GLOBALS, which
>> will now reside inside the parser (and is thus included in
>> TV_PHASE_PARSING now).  Originally it was mutually exclusive with
>> TV_PHASE_PARSING, but now resides within the parser, so I decided to get
>> rid of it since it's all technically in the parser.
>>
>> There is code in timevar*.c that makes sure that TV_PHASE_* elapsed
>> times add up to the total time.  So we either get rid of
>> TV_PHASE_DEFERRED and include its time in TV_PHASE_PARSING (avoiding
>> double counting), or we include a separate, non PHASE timer for it, with
>> timevar_push(TV_blah) where "blah" is NOT "PHASE".
>
> Why can't it keep the same name and just timevar_push/pop instead of
> timevar_start/stop?

Unless I'm misunderstanding something, validate_phases() verifies that 
the numbers add up by looking at the actual string name of the phase, 
irregardless of if you timevar_push/pop'ed it:

	static char phase_prefix[] = "phase ";
	...
	if (strncmp (tv->name, phase_prefix, sizeof phase_prefix - 1)

I could timevar_push/pop it but we'd have to change the name:

DEFTIMEVAR (TV_PHASE_DEFERRED        , "phase lang. deferred")

Did I miss something?
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 17:48                           ` Aldy Hernandez
@ 2014-09-12 17:56                             ` Jason Merrill
  2014-09-16 15:49                               ` Aldy Hernandez
  0 siblings, 1 reply; 40+ messages in thread
From: Jason Merrill @ 2014-09-12 17:56 UTC (permalink / raw)
  To: Aldy Hernandez, Richard Biener; +Cc: gcc-patches

On 09/12/2014 01:48 PM, Aldy Hernandez wrote:
> Unless I'm misunderstanding something, validate_phases() verifies that
> the numbers add up by looking at the actual string name of the phase,
> irregardless of if you timevar_push/pop'ed it:

Yes, but why wouldn't the numbers add up?  The comment for 
timevar_push_1 says "No further elapsed time is attributed to the 
previous topmost timing variable on the stack; subsequent elapsed time 
is attributed to TIMEVAR, until it is popped or another element is 
pushed on top."

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 17:11                       ` Aldy Hernandez
  2014-09-12 17:33                         ` Jason Merrill
@ 2014-09-15  9:32                         ` Richard Biener
  2014-09-15 18:46                           ` Jason Merrill
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-09-15  9:32 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches

On Fri, Sep 12, 2014 at 7:10 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 09/12/14 08:15, Jason Merrill wrote:
>>
>> On 09/11/2014 08:51 PM, Aldy Hernandez wrote:
>>>
>>> -  timevar_start (TV_PHASE_DEFERRED);
>>
>>
>>> -  timevar_stop (TV_PHASE_DEFERRED);
>>> -  timevar_start (TV_PHASE_OPT_GEN);
>>
>>
>> Why?
>
>
> TV_PHASE_OPT_GEN is now in compile_file(), where we call
> finalize_compilation_unit directly.
>
> TV_PHASE_DEFERRED, on the other hand, is a bit problematic because it was
> originally wrapping the code inside LANG_HOOKS_WRITE_GLOBALS, which will now
> reside inside the parser (and is thus included in TV_PHASE_PARSING now).
> Originally it was mutually exclusive with TV_PHASE_PARSING, but now resides
> within the parser, so I decided to get rid of it since it's all technically
> in the parser.
>
> There is code in timevar*.c that makes sure that TV_PHASE_* elapsed times
> add up to the total time.  So we either get rid of TV_PHASE_DEFERRED and
> include its time in TV_PHASE_PARSING (avoiding double counting), or we
> include a separate, non PHASE timer for it, with timevar_push(TV_blah) where
> "blah" is NOT "PHASE".
>
> Up to you, but I'm highly in favor of getting rid of things ;-).
>
>>
>>>    /* Generate hidden aliases for Java.  */
>>> -  if (candidates)
>>> +  if (java_hidden_aliases)
>>>      {
>>> -      build_java_method_aliases (candidates);
>>> -      delete candidates;
>>> +      build_java_method_aliases (java_hidden_aliases);
>>> +      delete java_hidden_aliases;
>>>      }
>>
>>
>> Didn't it work to move this before finalize?  I think the VTV stuff is
>> all that really needs to come after it, and that can move out of the
>> front end if this hook is a problem (which I don't really think it is).
>
>
> I was too chicken to try.  I will do so as a follow up.

Didn't work in the past btw - I've tried it once or twice.

Btw, if the VTV stuff really needs to come afterwards how does VTV
work with LTO then?

Eventually the VTV stuff can be integrated with the cgraph instead.

Richard.

> I am committing the patch to the branch, and will address both issues you
> speak of in followups.  Let me know what you prefer for the timevar issue.
>
> Thanks.
> Aldy
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-15  9:32                         ` Richard Biener
@ 2014-09-15 18:46                           ` Jason Merrill
  0 siblings, 0 replies; 40+ messages in thread
From: Jason Merrill @ 2014-09-15 18:46 UTC (permalink / raw)
  To: Richard Biener, Aldy Hernandez; +Cc: gcc-patches

On 09/15/2014 05:32 AM, Richard Biener wrote:
> Btw, if the VTV stuff really needs to come afterwards how does VTV
> work with LTO then?

It's conservatively correct: it emits information for all the vtables 
that are actually generated for the TU.  If LTO optimizes some of them 
away, the VTV information is not updated, but that only means a missed 
optimization.

> Eventually the VTV stuff can be integrated with the cgraph instead.

That would be ideal, yes.

Jason


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 17:56                             ` Jason Merrill
@ 2014-09-16 15:49                               ` Aldy Hernandez
  0 siblings, 0 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-09-16 15:49 UTC (permalink / raw)
  To: Jason Merrill, Richard Biener; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1589 bytes --]

On 09/12/14 10:56, Jason Merrill wrote:
> On 09/12/2014 01:48 PM, Aldy Hernandez wrote:
>> Unless I'm misunderstanding something, validate_phases() verifies that
>> the numbers add up by looking at the actual string name of the phase,
>> irregardless of if you timevar_push/pop'ed it:
>
> Yes, but why wouldn't the numbers add up?  The comment for
> timevar_push_1 says "No further elapsed time is attributed to the
> previous topmost timing variable on the stack; subsequent elapsed time
> is attributed to TIMEVAR, until it is popped or another element is
> pushed on top."

As discussed on IRC, because even though a push will stop any timer on 
the stack, the timers throttled with timevar_{start,stop} do not live on 
the stack and will continue counting even if a nested timevar_{push,pop} 
happens, thus counting time twice.

You've suggested stopping the parsing and starting the deferred timer, 
which I've implemented here.

A few things: I didn't do anything with non C/C++ languages, which 
either don't care about TV_* timers, or don't implement TV_PHASE_DEFERRED.

Also, see ?? note in c_write_global_declarations_1.  I'm not sure how 
fine grained you want things.  If I were to keep track of 
TV_PHASE_DBGINFO here properly, it would start becoming a mess of nested 
phase timers that we'd have to manually keep track of.  This smells of 
overusing global variables.  I would prefer to use a 
timevar_push(*DBGINFO*) variant for dbginfo (non "phase" timer), but I'm 
also fine leaving things with the patch as is (modulo the comment).

Up to you sir.

OK for branch?

Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 4279 bytes --]

commit c349dc8af009ac41ba1f86c3fde9052fb5282629
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Tue Sep 16 08:38:10 2014 -0700

    Resurrect TV_PHASE_DEFERRED.

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index a0a047f..89e3193 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10306,11 +10306,16 @@ c_write_global_declarations_1 (tree globals)
     }
   while (reconsider);
 
+  /* ?? For completeness, we could stop the TV_PHASE_DEFERRED timer
+     here, and start the TV_PHASE_DBGINFO timer.  Is it worth it, or
+     would it convolute things?  */
   for (decl = globals; decl; decl = DECL_CHAIN (decl))
     {
       check_global_declaration_1 (decl);
       debug_hooks->early_global_decl (decl);
     }
+  /* ?? Similarly here. Stop TV_PHASE_DBGINFO and start
+     TV_PHASE_DEFERRED again.  */
 }
 
 /* Callback to collect a source_ref from a DECL.  */
@@ -10373,6 +10378,9 @@ c_parse_final_cleanups (void)
   if (pch_file)
     return;
 
+  timevar_stop (TV_PHASE_PARSING);
+  timevar_start (TV_PHASE_DEFERRED);
+
   /* Do the Objective-C stuff.  This is where all the Objective-C
      module stuff gets generated (symtab, class/protocol/selector
      lists etc).  */
@@ -10414,6 +10422,9 @@ c_parse_final_cleanups (void)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
+  timevar_stop (TV_PHASE_DEFERRED);
+  timevar_start (TV_PHASE_PARSING);
+
   ext_block = NULL;
 }
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 28bf6e4..64cd968 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4354,6 +4354,9 @@ c_parse_final_cleanups (void)
 
   /* FIXME - huh?  was  input_line -= 1;*/
 
+  timevar_stop (TV_PHASE_PARSING);
+  timevar_start (TV_PHASE_DEFERRED);
+
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
@@ -4671,6 +4674,9 @@ c_parse_final_cleanups (void)
   /* Collect candidates for Java hidden aliases.  */
   java_hidden_aliases = collect_candidates_for_java_method_aliases ();
 
+  timevar_stop (TV_PHASE_DEFERRED);
+  timevar_start (TV_PHASE_PARSING);
+
   if (flag_vtable_verify)
     {
       vtv_recover_class_info ();
@@ -4680,6 +4686,8 @@ c_parse_final_cleanups (void)
 
   /* Issue warnings about static, but not defined, functions, etc, and
      generate initial debug information.  */
+  timevar_stop (TV_PHASE_PARSING);
+  timevar_start (TV_PHASE_DBGINFO);
   walk_namespaces (emit_debug_for_namespace, 0);
   if (vec_safe_length (pending_statics) != 0)
     {
@@ -4689,7 +4697,8 @@ c_parse_final_cleanups (void)
 				      pending_statics->length (),
 				      EMIT_DEBUG_EARLY);
     }
-
+  timevar_stop (TV_PHASE_DBGINFO);
+  timevar_start (TV_PHASE_PARSING);
 }
 
 /* Perform any post compilation-proper cleanups for the C++ front-end.
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index dfc3ab6..49658d7 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -300,6 +300,8 @@ global_decl_processing_and_early_debug (void)
   tree globals, decl, *vec;
   int len, i;
 
+  timevar_stop (TV_PHASE_PARSING);
+  timevar_start (TV_PHASE_DEFERRED);
   /* Really define vars that have had only a tentative definition.
      Really output inline functions that must actually be callable
      and have not been output so far.  */
@@ -316,9 +318,13 @@ global_decl_processing_and_early_debug (void)
 
   wrapup_global_declarations (vec, len);
   check_global_declarations (vec, len);
+  timevar_stop (TV_PHASE_DEFERRED);
 
+  timevar_start (TV_PHASE_DBGINFO);
   emit_debug_global_declarations (vec, len, EMIT_DEBUG_EARLY);
+  timevar_stop (TV_PHASE_DBGINFO);
 
+  timevar_start (TV_PHASE_PARSING);
   free (vec);
 }
 
diff --git a/gcc/timevar.def b/gcc/timevar.def
index d9d95de..15fe7f3 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -40,6 +40,7 @@ DEFTIMEVAR (TV_TOTAL                 , "total time")
    validate_phases).  */
 DEFTIMEVAR (TV_PHASE_SETUP           , "phase setup")
 DEFTIMEVAR (TV_PHASE_PARSING         , "phase parsing")
+DEFTIMEVAR (TV_PHASE_DEFERRED        , "phase lang. deferred")
 DEFTIMEVAR (TV_PHASE_LATE_PARSING_CLEANUPS, "phase late parsing cleanups")
 DEFTIMEVAR (TV_PHASE_OPT_GEN         , "phase opt and generate")
 DEFTIMEVAR (TV_PHASE_DBGINFO         , "phase debug info")

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-09-12 15:15                     ` Jason Merrill
  2014-09-12 17:11                       ` Aldy Hernandez
@ 2014-12-18 19:26                       ` Aldy Hernandez
  2014-12-19 11:20                         ` Richard Biener
  1 sibling, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-12-18 19:26 UTC (permalink / raw)
  To: Jason Merrill, Richard Biener; +Cc: gcc-patches

Hi Jason.

It's embarrassing that I just got to this now.  I hope you don't repay 
the favor and take as long responding to me :(.

On 09/12/14 08:15, Jason Merrill wrote:
> On 09/11/2014 08:51 PM, Aldy Hernandez wrote:

>>    /* Generate hidden aliases for Java.  */
>> -  if (candidates)
>> +  if (java_hidden_aliases)
>>      {
>> -      build_java_method_aliases (candidates);
>> -      delete candidates;
>> +      build_java_method_aliases (java_hidden_aliases);
>> +      delete java_hidden_aliases;
>>      }
>
> Didn't it work to move this before finalize?  I think the VTV stuff is
> all that really needs to come after it, and that can move out of the
> front end if this hook is a problem (which I don't really think it is).

I can't move the call to build_java_method_aliases until the compilation 
proper has run because said function iterates through all the functions 
with FOR_EACH_FUNCTION, and the set of available functions at parse time 
and after the optimization passes are quite different, presumably 
because we've pruned all the unused functions.

If I move the call to build_java_method_aliases before the optimization 
passes, we end up emitting many more hidden aliases which cause 
handle_alias_pairs() in cgraphunit.c to bark with:

error: 'void _ZGAN8__JArrayC4Ev()' aliased to external symbol 
'_ZN8__JArrayC4Ev'

So we either leave building Java method aliases after the optimization 
passes, or we somehow tighten the candidate selection in 
collect_candidates_for_java_method_aliases():

       if (DECL_CLASS_SCOPE_P (fndecl)
	  && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
	  && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))

What do you suggest?

I can, however, move all the other non-VTV stuff to the parser in a 
subsequent patch, while you respond to this query.

Thanks.
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-18 19:26                       ` Aldy Hernandez
@ 2014-12-19 11:20                         ` Richard Biener
  2014-12-19 18:58                           ` Jan Hubicka
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Biener @ 2014-12-19 11:20 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, gcc-patches, Jan Hubicka

On Thu, Dec 18, 2014 at 8:23 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> Hi Jason.
>
> It's embarrassing that I just got to this now.  I hope you don't repay the
> favor and take as long responding to me :(.
>
> On 09/12/14 08:15, Jason Merrill wrote:
>>
>> On 09/11/2014 08:51 PM, Aldy Hernandez wrote:
>
>
>>>    /* Generate hidden aliases for Java.  */
>>> -  if (candidates)
>>> +  if (java_hidden_aliases)
>>>      {
>>> -      build_java_method_aliases (candidates);
>>> -      delete candidates;
>>> +      build_java_method_aliases (java_hidden_aliases);
>>> +      delete java_hidden_aliases;
>>>      }
>>
>>
>> Didn't it work to move this before finalize?  I think the VTV stuff is
>> all that really needs to come after it, and that can move out of the
>> front end if this hook is a problem (which I don't really think it is).
>
>
> I can't move the call to build_java_method_aliases until the compilation
> proper has run because said function iterates through all the functions with
> FOR_EACH_FUNCTION, and the set of available functions at parse time and
> after the optimization passes are quite different, presumably because we've
> pruned all the unused functions.
>
> If I move the call to build_java_method_aliases before the optimization
> passes, we end up emitting many more hidden aliases which cause
> handle_alias_pairs() in cgraphunit.c to bark with:
>
> error: 'void _ZGAN8__JArrayC4Ev()' aliased to external symbol
> '_ZN8__JArrayC4Ev'
>
> So we either leave building Java method aliases after the optimization
> passes, or we somehow tighten the candidate selection in
> collect_candidates_for_java_method_aliases():
>
>       if (DECL_CLASS_SCOPE_P (fndecl)
>           && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
>           && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
>
> What do you suggest?

Yeah, I've told you that this is a major blocker I couldn't resolve the last
time I tried to move things.

IMHO this Java method aliases needs to be made cgraph-aware somehow,
thus we need to build the aliases as proper aliases during candidate
collection but somehow mark them reclaimable by the cgraph code
(builtding the aliases is only done if TREE_ASM_WRITTEN).

Honza may have an idea here?

Richard.

> I can, however, move all the other non-VTV stuff to the parser in a
> subsequent patch, while you respond to this query.
>
> Thanks.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 11:20                         ` Richard Biener
@ 2014-12-19 18:58                           ` Jan Hubicka
  2014-12-19 19:01                             ` Jan Hubicka
  2014-12-19 19:03                             ` Aldy Hernandez
  0 siblings, 2 replies; 40+ messages in thread
From: Jan Hubicka @ 2014-12-19 18:58 UTC (permalink / raw)
  To: Richard Biener; +Cc: Aldy Hernandez, Jason Merrill, gcc-patches, Jan Hubicka

> 
> Yeah, I've told you that this is a major blocker I couldn't resolve the last
> time I tried to move things.
> 
> IMHO this Java method aliases needs to be made cgraph-aware somehow,
> thus we need to build the aliases as proper aliases during candidate
> collection but somehow mark them reclaimable by the cgraph code
> (builtding the aliases is only done if TREE_ASM_WRITTEN).
> 
> Honza may have an idea here?

Hmm, would you mind explain me what are Java method aliases?
Making alias removed when unused would probably require extra flag (as you can
not make comdat alias of non-comdat symbol) but should be easy to do.

honza
> 
> Richard.
> 
> > I can, however, move all the other non-VTV stuff to the parser in a
> > subsequent patch, while you respond to this query.
> >
> > Thanks.
> > Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 18:58                           ` Jan Hubicka
@ 2014-12-19 19:01                             ` Jan Hubicka
  2014-12-19 19:02                               ` Aldy Hernandez
  2014-12-19 19:03                             ` Aldy Hernandez
  1 sibling, 1 reply; 40+ messages in thread
From: Jan Hubicka @ 2014-12-19 19:01 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Biener, Aldy Hernandez, Jason Merrill, gcc-patches

> > 
> > Yeah, I've told you that this is a major blocker I couldn't resolve the last
> > time I tried to move things.
> > 
> > IMHO this Java method aliases needs to be made cgraph-aware somehow,
> > thus we need to build the aliases as proper aliases during candidate
> > collection but somehow mark them reclaimable by the cgraph code
> > (builtding the aliases is only done if TREE_ASM_WRITTEN).
> > 
> > Honza may have an idea here?
> 
> Hmm, would you mind explain me what are Java method aliases?
> Making alias removed when unused would probably require extra flag (as you can
> not make comdat alias of non-comdat symbol) but should be easy to do.

Looking at the code, making Java aliases to be output at the same time we output
thunks in C++ may just work....

Honza
> 
> honza
> > 
> > Richard.
> > 
> > > I can, however, move all the other non-VTV stuff to the parser in a
> > > subsequent patch, while you respond to this query.
> > >
> > > Thanks.
> > > Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 19:01                             ` Jan Hubicka
@ 2014-12-19 19:02                               ` Aldy Hernandez
  2014-12-19 19:31                                 ` Jason Merrill
  0 siblings, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-12-19 19:02 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Biener, Jason Merrill, gcc-patches

On 12/19/14 10:58, Jan Hubicka wrote:
>>>
>>> Yeah, I've told you that this is a major blocker I couldn't resolve the last
>>> time I tried to move things.
>>>
>>> IMHO this Java method aliases needs to be made cgraph-aware somehow,
>>> thus we need to build the aliases as proper aliases during candidate
>>> collection but somehow mark them reclaimable by the cgraph code
>>> (builtding the aliases is only done if TREE_ASM_WRITTEN).
>>>
>>> Honza may have an idea here?
>>
>> Hmm, would you mind explain me what are Java method aliases?
>> Making alias removed when unused would probably require extra flag (as you can
>> not make comdat alias of non-comdat symbol) but should be easy to do.
>
> Looking at the code, making Java aliases to be output at the same time we output
> thunks in C++ may just work....

Can you elaborate on this?  Sorry, this is an area I'm largely 
unfamiliar with.

Thanks.
Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 18:58                           ` Jan Hubicka
  2014-12-19 19:01                             ` Jan Hubicka
@ 2014-12-19 19:03                             ` Aldy Hernandez
  1 sibling, 0 replies; 40+ messages in thread
From: Aldy Hernandez @ 2014-12-19 19:03 UTC (permalink / raw)
  To: Jan Hubicka, Richard Biener; +Cc: Jason Merrill, gcc-patches

On 12/19/14 10:53, Jan Hubicka wrote:
>>
>> Yeah, I've told you that this is a major blocker I couldn't resolve the last
>> time I tried to move things.
>>
>> IMHO this Java method aliases needs to be made cgraph-aware somehow,
>> thus we need to build the aliases as proper aliases during candidate
>> collection but somehow mark them reclaimable by the cgraph code
>> (builtding the aliases is only done if TREE_ASM_WRITTEN).
>>
>> Honza may have an idea here?
>
> Hmm, would you mind explain me what are Java method aliases?
> Making alias removed when unused would probably require extra flag (as you can

Actually, this was my gut reaction solution.

Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 19:02                               ` Aldy Hernandez
@ 2014-12-19 19:31                                 ` Jason Merrill
  2014-12-19 19:50                                   ` Jan Hubicka
  2014-12-20 10:09                                   ` Aldy Hernandez
  0 siblings, 2 replies; 40+ messages in thread
From: Jason Merrill @ 2014-12-19 19:31 UTC (permalink / raw)
  To: Aldy Hernandez, Jan Hubicka; +Cc: Richard Biener, gcc-patches

It looks like java aliases are still using assemble_alias directly; 
switching to using same_body aliases like thunks and such should handle 
the issue.

Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 19:31                                 ` Jason Merrill
@ 2014-12-19 19:50                                   ` Jan Hubicka
  2014-12-20 10:09                                   ` Aldy Hernandez
  1 sibling, 0 replies; 40+ messages in thread
From: Jan Hubicka @ 2014-12-19 19:50 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Aldy Hernandez, Jan Hubicka, Richard Biener, gcc-patches

> It looks like java aliases are still using assemble_alias directly;

assemble_alias dispatch to code adding alias pair to callgarph, so that should
be safe.  My understanding is that Aldys concern is that creating the aliases
early leads to undefined symbol because we produce aliases that never get their
function bodies output by FE.

> switching to using same_body aliases like thunks and such should
> handle the issue.

Yes, I think producing java alias at the same time we produce same_body alias should just work
(not that I would like the same body alias machinery - it is major pain to see these appearing
at random time from DECL_ASSEMBLER_NAME hook)

Honza
> 
> Jason

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-19 19:31                                 ` Jason Merrill
  2014-12-19 19:50                                   ` Jan Hubicka
@ 2014-12-20 10:09                                   ` Aldy Hernandez
  2015-01-08 12:24                                     ` Richard Biener
  1 sibling, 1 reply; 40+ messages in thread
From: Aldy Hernandez @ 2014-12-20 10:09 UTC (permalink / raw)
  To: Jason Merrill, Jan Hubicka; +Cc: Richard Biener, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 763 bytes --]

On 12/19/14 11:03, Jason Merrill wrote:

First of all, my bad Richard.  I vaguely remember you mentioning 
something about Java, but it was early enough in the project that I had 
no idea what you were talking about.  Thanks for your patience.

> It looks like java aliases are still using assemble_alias directly;
> switching to using same_body aliases like thunks and such should handle
> the issue.

Ah, I see.  Attached is a patch against _MAINLINE_ that fixes the issue 
I am seeing, without introducing any regressions.

Would it be crazy to ask for permission to commit this into mainline, 
and avoiding dragging this along on the branch?  If not, I have a 
similar patch for the branch I can commit there.

Let me know.

Thanks for everyone's input.
Aldy

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 4107 bytes --]

commit 6ebeefeb10f3396a2dc2b28802f2f432a04e757b
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Fri Dec 19 20:43:16 2014 -0800

    	* decl2.c (collect_candidates_for_java_method_aliases): Remove.
    	(build_java_method_aliases): Adapt to use create_same_body_alias
    	instead of assemble_alias.  Move variable declarations to
    	definition and tidy up.
    	(cp_write_global_declarations): Call build_java_method_aliases
    	instead of collecting candidates first.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 69201b0..13d09bb 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3972,20 +3972,17 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
 }
 
 /* Java requires that we be able to reference a local address for a
-   method, and not be confused by PLT entries.  If hidden aliases are
-   supported, collect and return all the functions for which we should
-   emit a hidden alias.  */
+   method, and not be confused by PLT entries.  If supported, create a
+   hidden alias for all such methods.  */
 
-static hash_set<tree> *
-collect_candidates_for_java_method_aliases (void)
+static void
+build_java_method_aliases (void)
 {
-  struct cgraph_node *node;
-  hash_set<tree> *candidates = NULL;
-
 #ifndef HAVE_GAS_HIDDEN
-  return candidates;
+  return;
 #endif
 
+  struct cgraph_node *node;
   FOR_EACH_FUNCTION (node)
     {
       tree fndecl = node->decl;
@@ -3994,55 +3991,18 @@ collect_candidates_for_java_method_aliases (void)
 	  && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
 	  && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
 	{
-	  if (candidates == NULL)
-	    candidates = new hash_set<tree>;
-	  candidates->add (fndecl);
-	}
-    }
-
-  return candidates;
-}
-
-
-/* Java requires that we be able to reference a local address for a
-   method, and not be confused by PLT entries.  If hidden aliases are
-   supported, emit one for each java function that we've emitted.
-   CANDIDATES is the set of FUNCTION_DECLs that were gathered
-   by collect_candidates_for_java_method_aliases.  */
-
-static void
-build_java_method_aliases (hash_set<tree> *candidates)
-{
-  struct cgraph_node *node;
-
-#ifndef HAVE_GAS_HIDDEN
-  return;
-#endif
-
-  FOR_EACH_FUNCTION (node)
-    {
-      tree fndecl = node->decl;
-
-      if (TREE_ASM_WRITTEN (fndecl)
-	  && candidates->contains (fndecl))
-	{
 	  /* Mangle the name in a predictable way; we need to reference
 	     this from a java compiled object file.  */
-	  tree oid, nid, alias;
-	  const char *oname;
-	  char *nname;
-
-	  oid = DECL_ASSEMBLER_NAME (fndecl);
-	  oname = IDENTIFIER_POINTER (oid);
+	  tree oid = DECL_ASSEMBLER_NAME (fndecl);
+	  const char *oname = IDENTIFIER_POINTER (oid);
 	  gcc_assert (oname[0] == '_' && oname[1] == 'Z');
-	  nname = ACONCAT (("_ZGA", oname+2, NULL));
-	  nid = get_identifier (nname);
+	  char *nname = ACONCAT (("_ZGA", oname + 2, NULL));
 
-	  alias = make_alias_for (fndecl, nid);
+	  tree alias = make_alias_for (fndecl, get_identifier (nname));
 	  TREE_PUBLIC (alias) = 1;
 	  DECL_VISIBILITY (alias) = VISIBILITY_HIDDEN;
 
-	  assemble_alias (alias, oid);
+	  cgraph_node::create_same_body_alias (alias, fndecl);
 	}
     }
 }
@@ -4375,7 +4335,6 @@ cp_write_global_declarations (void)
   unsigned ssdf_count = 0;
   int retries = 0;
   tree decl;
-  hash_set<tree> *candidates;
 
   locus = input_location;
   at_eof = 1;
@@ -4726,8 +4685,8 @@ cp_write_global_declarations (void)
      linkage now.  */
   pop_lang_context ();
 
-  /* Collect candidates for Java hidden aliases.  */
-  candidates = collect_candidates_for_java_method_aliases ();
+  /* Generate Java hidden aliases.  */
+  build_java_method_aliases ();
 
   timevar_stop (TV_PHASE_DEFERRED);
   timevar_start (TV_PHASE_OPT_GEN);
@@ -4767,13 +4726,6 @@ cp_write_global_declarations (void)
 
   perform_deferred_noexcept_checks ();
 
-  /* Generate hidden aliases for Java.  */
-  if (candidates)
-    {
-      build_java_method_aliases (candidates);
-      delete candidates;
-    }
-
   finish_repo ();
 
   /* The entire file is now complete.  If requested, dump everything

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
  2014-12-20 10:09                                   ` Aldy Hernandez
@ 2015-01-08 12:24                                     ` Richard Biener
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Biener @ 2015-01-08 12:24 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: Jason Merrill, Jan Hubicka, gcc-patches

On Sat, Dec 20, 2014 at 5:49 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 12/19/14 11:03, Jason Merrill wrote:
>
> First of all, my bad Richard.  I vaguely remember you mentioning something
> about Java, but it was early enough in the project that I had no idea what
> you were talking about.  Thanks for your patience.
>
>> It looks like java aliases are still using assemble_alias directly;
>> switching to using same_body aliases like thunks and such should handle
>> the issue.
>
>
> Ah, I see.  Attached is a patch against _MAINLINE_ that fixes the issue I am
> seeing, without introducing any regressions.

Well, I think it's a bit late now (but only affects Java, so...).  Jasons call.

> Would it be crazy to ask for permission to commit this into mainline, and
> avoiding dragging this along on the branch?  If not, I have a similar patch
> for the branch I can commit there.
>
> Let me know.

Thanks for fixing this!
Richard.

> Thanks for everyone's input.
> Aldy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [debug-early] reuse variable DIEs and fix their context
@ 2015-01-08 15:20 Aldy Hernandez
  0 siblings, 0 replies; 40+ messages in thread
From: Aldy Hernandez @ 2015-01-08 15:20 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches, Jan Hubicka, Jason Merrill

Jason suggested keeping it in the branch since it doesn't fix any regressions, so it's living there for now.

AldyOn Jan 8, 2015 4:24 AM, Richard Biener <richard.guenther@gmail.com> wrote:
>
> On Sat, Dec 20, 2014 at 5:49 AM, Aldy Hernandez <aldyh@redhat.com> wrote: 
> > On 12/19/14 11:03, Jason Merrill wrote: 
> > 
> > First of all, my bad Richard.  I vaguely remember you mentioning something 
> > about Java, but it was early enough in the project that I had no idea what 
> > you were talking about.  Thanks for your patience. 
> > 
> >> It looks like java aliases are still using assemble_alias directly; 
> >> switching to using same_body aliases like thunks and such should handle 
> >> the issue. 
> > 
> > 
> > Ah, I see.  Attached is a patch against _MAINLINE_ that fixes the issue I am 
> > seeing, without introducing any regressions. 
>
> Well, I think it's a bit late now (but only affects Java, so...).  Jasons call. 
>
> > Would it be crazy to ask for permission to commit this into mainline, and 
> > avoiding dragging this along on the branch?  If not, I have a similar patch 
> > for the branch I can commit there. 
> > 
> > Let me know. 
>
> Thanks for fixing this! 
> Richard. 
>
> > Thanks for everyone's input. 
> > Aldy 

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2015-01-08 15:20 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-27  2:43 [debug-early] reuse variable DIEs and fix their context Aldy Hernandez
2014-08-28 13:58 ` Richard Biener
2014-08-28 17:35   ` Aldy Hernandez
2014-08-28 18:01     ` Jason Merrill
2014-08-28 19:13       ` Richard Biener
2014-08-28 20:14         ` Jason Merrill
2014-08-29  9:09           ` Richard Biener
2014-09-03 17:55       ` Aldy Hernandez
2014-09-04 10:42         ` Richard Biener
2014-09-05  2:38           ` Aldy Hernandez
2014-09-05  9:00             ` Richard Biener
2014-09-09  0:01               ` Aldy Hernandez
2014-09-09  9:16                 ` Richard Biener
2014-09-12  0:51                   ` Aldy Hernandez
2014-09-12  8:13                     ` Richard Biener
2014-09-12 15:15                     ` Jason Merrill
2014-09-12 17:11                       ` Aldy Hernandez
2014-09-12 17:33                         ` Jason Merrill
2014-09-12 17:48                           ` Aldy Hernandez
2014-09-12 17:56                             ` Jason Merrill
2014-09-16 15:49                               ` Aldy Hernandez
2014-09-15  9:32                         ` Richard Biener
2014-09-15 18:46                           ` Jason Merrill
2014-12-18 19:26                       ` Aldy Hernandez
2014-12-19 11:20                         ` Richard Biener
2014-12-19 18:58                           ` Jan Hubicka
2014-12-19 19:01                             ` Jan Hubicka
2014-12-19 19:02                               ` Aldy Hernandez
2014-12-19 19:31                                 ` Jason Merrill
2014-12-19 19:50                                   ` Jan Hubicka
2014-12-20 10:09                                   ` Aldy Hernandez
2015-01-08 12:24                                     ` Richard Biener
2014-12-19 19:03                             ` Aldy Hernandez
2014-09-04 17:53         ` H.J. Lu
2014-09-04 17:54           ` Aldy Hernandez
2014-09-04 18:23             ` Richard Biener
2014-09-04 18:35               ` Aldy Hernandez
2014-09-04 18:38                 ` Christophe Lyon
2014-09-04 19:42                 ` Jan-Benedict Glaw
2015-01-08 15:20 Aldy Hernandez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).