[patch 10/10] debug-early merge: compiler proper
Richard Biener
richard.guenther@gmail.com
Fri May 22 11:26:00 GMT 2015
On Wed, May 20, 2015 at 5:50 PM, Aldy Hernandez <aldyh@redhat.com> wrote:
> On 05/18/2015 06:56 AM, Richard Biener wrote:
>
> BTW, thanks for the review.
>
>> On Fri, May 8, 2015 at 2:40 AM, Aldy Hernandez <aldyh@redhat.com> wrote:
>>>
>>> As seen on TV.
>>
>>
>> +/* FIRST_TIME is set to TRUE for the first time we are called for a
>> + translation unit from finalize_compilation_unit() or false
>> + otherwise. */
>> +
>> static void
>> -analyze_functions (void)
>> +analyze_functions (bool first_time)
>> {
>> ...
>> + if (first_time)
>> + {
>> + symtab_node *snode;
>> + FOR_EACH_SYMBOL (snode)
>> + check_global_declaration (snode->decl);
>> + }
>> +
>>
>> I think it is better to split analyze_functions (why does it have it's own
>> copy
>> of unreachable node removal?) into analysis and unused-symbol removal
>> and have the
>> check_global_declaration call be in finalize_compilation_unit directly.
>> Honza?
>
>
> Leaving things as is, as per Honza's comment ??
>
>>
>> @@ -1113,6 +1131,19 @@ analyze_functions (void)
>> {
>> if (symtab->dump_file)
>> fprintf (symtab->dump_file, " %s", node->name ());
>> +
>> + /* See if the debugger can use anything before the DECL
>> + passes away. Perhaps it can notice a DECL that is now a
>> + constant and can tag the early DIE with an appropriate
>> + attribute.
>> +
>> + Otherwise, this is the last chance the debug_hooks have
>> + at looking at optimized away DECLs, since
>> + late_global_decl will subsequently be called from the
>> + contents of the now pruned symbol table. */
>> + if (!decl_function_context (node->decl))
>> + (*debug_hooks->late_global_decl) (node->decl);
>> +
>> node->remove ();
>>
>> so this applies to VAR_DECLs only - shouldn't this be in the
>> varpool_node::remove function then? You can even register/deregister
>> a hook for this in finalize_compilation_unit. That would IMHO be better.
>
>
> The problem is that varpool_node::remove() may be called before we
> have finished parsing the DECL, thus before we call
> early_global_decl() on it. So we would essentially be calling
> late_global_decl() on a DECL for which we haven't called
> early_global_decl().
>
> To complicate matters, we may call ::remove() before we finish parsing
> a decl. In the C front-end, for instance, we call ::remove() from
> duplicate_decls(), before we even call rest_of_decl_compilation (where
> we call early_global_decl).
>
> Calling late_global_decl so early, before we have even finished
> parsing, seems wrong and obviously causes problems. One example is
> dwarf2out can put the DECL into the deferred_asm_names list, only to
> have duplicate_decls() gcc_free it from under us.
>
>>
>> All debug stuff apart from dwarf2out.c changes (I assume Jason reviews
>> them) are ok.
>>
>> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
>> index 02012d5..15b6dd2 100644
>> --- a/gcc/gengtype.c
>> +++ b/gcc/gengtype.c
>> @@ -4718,7 +4718,8 @@ write_roots (pair_p variables, bool emit_pch)
>> this funcion will have to be adjusted to be more like
>> output_mangled_typename. */
>>
>> -static void
>> +/* ?? Why are we keeping this? Is this actually used anywhere? */
>> +static void ATTRIBUTE_UNUSED
>> output_typename (outf_p of, const_type_p t)
>> {
>> switch (t->kind)
>>
>> Just remove the function.
>
>
> Done.
>
>>
>> The langhooks changes are ok.
>>
>> diff --git a/gcc/passes.c b/gcc/passes.c
>> index 04ff042..4dee8ad 100644
>> --- a/gcc/passes.c
>> +++ b/gcc/passes.c
>> @@ -293,6 +293,28 @@ rest_of_decl_compilation (tree decl,
>> else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
>> && TREE_STATIC (decl))
>> varpool_node::get_create (decl);
>> +
>> + /* Generate early debug for global variables. Any local variables will
>> + be handled by either handling reachable functions from
>> + finalize_compilation_unit (and by consequence, locally scoped
>> + symbols), or by rest_of_type_compilation below.
>> +
>> + Also, pick up function prototypes, which will be mostly ignored
>> + by the different early_global_decl() hooks, but will at least be
>> + used by Go's hijack of the debug_hooks to implement
>> + -fdump-go-spec. */
>> + if (!flag_wpa
>> + && !in_lto_p
>>
>> Just check !in_lto_p, !flag_wpa is redundant.
>
>
> Done.
>
>>
>> + && !decl_function_context (decl)
>> + && !current_function_decl
>>
>> Why that? !decl_function_context should catch relevant cases?
>
>
> You'd think, huh? The issue here are extern declarations appearing
> inside of a function. For this case, decl_function_context is NULL,
> because the actual context is toplevel, but current_function_decl is
> set to the function where the extern declaration appears.
>
> For example:
>
> namespace S
> {
> int
> f()
> {
> {
> int i = 42;
> {
> extern int i; // Local extern declaration.
> return i;
> }
> }
> }
> }
>
> I have added a big fat comment in the code now, since it's clearly not
> obvious why we need current_function_decl.
>
>>
>> + && !decl_type_context (decl))
>> + (*debug_hooks->early_global_decl) (decl);
>>
>> I'll note that nested functions and class methods are not getting
>> early_global_decl()ed here. I suppose their containing function/type
>> is supposed to generate early dwarf by means of dwarf2out walking
>> over children.
>
>
> Indeed, and I had properly commented this:
>
> /* Emit early debug for reachable functions, and by consequence,
> locally scoped symbols. */
> struct cgraph_node *cnode;
> FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode)
> (*debug_hooks->early_global_decl) (cnode->decl);
>
> I did, however, remove the !decl_function_context() restriction in this
> snippet from the previous iteration of this patch because of the nested
> function problem you mention.
>
> Doubly nested functions were fine because dwarf2out will walk the inner
> function, by virtue of it being a symbol local to the top level function,
> however it was missing triply nested functions because the 2nd nested
> functions was considered a declaration so its children (> 2 nested
> functions) were not walked. I ran into this with Ada, and removed the
> !decl_function_context() while generating early dwarf. IIRC, the restriction
> was originally there to limit extra DIEs that may be generated, but since
> I'm already on the hook for cleaning up DIEs shortly after the merge, we're
> going to have deal with this anyhow.
>
> I also added a test for triply nested functions for C+debug-early, since Ada
> seemed to be the only front-end stressing >= 3 nested functions. I will
> repost the test when I repost the testsuite changes.
>
>>
>> timevar changes are ok.
>>
>> the toplev changes are ok.
>>
>> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
>> index ad1bb23..2a9f417 100644
>> --- a/gcc/tree-core.h
>> +++ b/gcc/tree-core.h
>> @@ -1334,6 +1334,9 @@ struct GTY(()) tree_block {
>> tree abstract_origin;
>> tree fragment_origin;
>> tree fragment_chain;
>> +
>> + /* Pointer to the DWARF lexical block. */
>> + struct die_struct *die;
>> };
>>
>> struct GTY(()) tree_type_common {
>>
>> Ick - do we need this? dwarf2out.c has a hashtable to map blocks to
>> DIEs (which you don't remove in turn).
>
>
> We need a way to reference the early created DIE from late debugging, and we
> can't use block_map because it gets cloberred across functions. It's
> currently being released in late debug (dwarf2out_function_decl),
> that's why you see it not set to NULL in dwarf2out_c_finalize.
>
> Also, it uses BLOCK_NUMBERs, which according to the documentation in
> tree.h, are not guaranteed to be unique across functions.
>
> As Honza mentioned, we're already using a DIE map in types through
> TYPE_SYMTAB_DIE. See lookup_type_die() in dwarf2out.c.
>
> Could we leave this as is?
But why then not eliminate block_map in favor of using the new ->die member?
Having both looks very odd to me.
Can you cook up a patch for trunk adding that field to tree_block and removing
the block_map map in favor of sth like what we do for
lookup_type_die/equate_type_number_to_die
and TYPE_SYMTAB_DIE?
> How does this version, which has been committed to the debug-early branch,
> look?
No further look right now, but I assume it's fine apart from the
block_map issue (and dwarf2out.c of course).
Richard.
> Aldy
More information about the Gcc-patches
mailing list