From: Aldy Hernandez <aldyh@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: Richard Biener <richard.guenther@gmail.com>,
gcc-patches <gcc-patches@gcc.gnu.org>
Subject: Re: [debug-early] C++ clones and limbo DIEs
Date: Wed, 28 Jan 2015 19:32:00 -0000 [thread overview]
Message-ID: <54C92A80.80306@redhat.com> (raw)
In-Reply-To: <54C92A59.4070401@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 35 bytes --]
And now with the actual patch ;-).
[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 15969 bytes --]
* c-family/cilk.c (create_cilk_wrapper_body): Emit debug
information for wrappers.
* cp/decl2.c (emit_debug_for_namespace): Add FIXME note for
templates.
* cp/optimize.c (maybe_clone_body): Emit early debug for clones.
* dbxout.c (dbx_debug_hooks): Add early_finish field.
* sdbout.c (sdb_debug_hooks): Same.
* vmsdbgout.c (vmsdbg_debug_hooks): Same.
* debug.h (gcc_debug_hooks): Same.
* dwarf2out.c (dwarf2_debug_hooks): Same.
(new_die): Inhibit limbo dies unless generating early dwarf.
(gen_subprogram_die): Do not create a new DIE if we have an
old DIE and it has DW_AT_abstract_origin set.
(lookup_filename): Return NULL when no file name.
(optimize_location_lists): Abstract flushing of limbo list to...
(dwarf2out_early_finish): ...here. New function.
(dwarf2out_abstract_function): Do not set DECL_ABSTRACT_P
recursively if DECL_ABSTRACT_P of parent is set.
* toplev.c (toplev::main): Add temporary debugging aid.
* tree.c (free_lang_data): Call debug_hooks->early_finish.
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index 82dd2cb..c9a4a4b 100644
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "diagnostic.h"
#include "cilk.h"
+#include "debug.h"
enum add_variable_type {
/* Reference to previously-defined variable. */
@@ -573,6 +574,14 @@ create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
pop_cfun_to (outer);
+ /* It is rather unfortunate that Cilk creates trees this late
+ (during gimplification). However, until this gets fixed,
+ specially handle emitting DWARF for this new function and
+ immediately clean up the limbo_die_list where the new function's
+ DIE will inevitably end up. */
+ debug_hooks->early_global_decl (fndecl);
+ debug_hooks->early_finish ();
+
/* Recognize the new function. */
call_graph_add_fn (fndecl);
return fndecl;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 691688b..70abc99 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4346,6 +4346,9 @@ emit_debug_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
check_global_declarations (vec, len);
+ /* FIXME: What does this do for templates? I think we don't want to
+ send a template off to early_global_decl, but rather walk through
+ its specializations and emit them. */
for (tree t = level->names; t; t = TREE_CHAIN(t))
debug_hooks->early_global_decl (t);
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 62e32d2..ab3e93e 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -539,6 +539,10 @@ maybe_clone_body (tree fn)
/* Start processing the function. */
start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
+ /* Generate early dwarf for the clone now that we have a body
+ for it. */
+ debug_hooks->early_global_decl (clone);
+
/* Tell cgraph if both ctors or both dtors are known to have
the same body. */
if (can_alias
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 430a2eb..202ef8a 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -359,6 +359,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_init,
dbxout_finish,
debug_nothing_void,
+ debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
dbxout_start_source_file,
@@ -400,6 +401,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
dbxout_init,
dbxout_finish,
debug_nothing_void,
+ debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
dbxout_start_source_file,
diff --git a/gcc/debug.c b/gcc/debug.c
index 449d3a1..d0e00c0 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -27,6 +27,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
{
debug_nothing_charstar,
debug_nothing_charstar,
+ debug_nothing_void, /* early_finish */
debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
diff --git a/gcc/debug.h b/gcc/debug.h
index f9485bc..a8d3f23 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -30,6 +30,9 @@ struct gcc_debug_hooks
/* Output debug symbols. */
void (* finish) (const char *main_filename);
+ /* Run cleanups necessary after early debug generation. */
+ void (* early_finish) (void);
+
/* Called from cgraph_optimize before starting to assemble
functions/variables/toplevel asms. */
void (* assembly_start) (void);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e3ccda2..bf9268a 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dfa.h"
#include "gdb/gdb-index.h"
#include "rtl-iter.h"
+#include "print-tree.h"
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
static rtx_insn *last_var_location_insn;
@@ -2424,6 +2425,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
static void dwarf2out_init (const char *);
static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
static void dwarf2out_assembly_start (void);
static void dwarf2out_define (unsigned int, const char *);
static void dwarf2out_undef (unsigned int, const char *);
@@ -2451,6 +2453,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
{
dwarf2out_init,
dwarf2out_finish,
+ dwarf2out_early_finish,
dwarf2out_assembly_start,
dwarf2out_define,
dwarf2out_undef,
@@ -4903,6 +4906,25 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
{
limbo_die_node *limbo_node;
+ /* No DIEs created after early dwarf should end up in limbo,
+ because the limbo list should not persist past LTO streaming.
+ If some corner case (Cilk), is creating definitions too late,
+ it should itself take care of calling
+ dwarf2out_early_global_decl() and flushing the limbo_die_list
+ afterwards via dwarf2out_early_finish(). See cilk.c for an
+ example of such stupidity. */
+ if (tag_value != DW_TAG_compile_unit
+ && !early_dwarf_dumping
+ /* FIXME: Allow late limbo DIE creation for LTO, especially
+ in the ltrans stage, but once we implement LTO dwarf
+ streaming, we should remove this exception. */
+ && !in_lto_p)
+ {
+ fprintf (stderr, "symbol ended up in limbo too late:");
+ debug_tree (t);
+ gcc_unreachable ();
+ }
+
limbo_node = ggc_cleared_alloc<limbo_die_node> ();
limbo_node->die = die;
limbo_node->created_for = t;
@@ -18277,9 +18299,10 @@ dwarf2out_abstract_function (tree decl)
current_function_decl = decl;
was_abstract = DECL_ABSTRACT_P (decl);
- set_decl_abstract_flags (decl, 1);
+ if (!was_abstract)
+ set_decl_abstract_flags (decl, 1);
dwarf2out_decl (decl);
- if (! was_abstract)
+ if (!was_abstract)
set_decl_abstract_flags (decl, 0);
current_function_decl = save_fn;
@@ -18443,14 +18466,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
if (old_die && old_die->die_parent == NULL)
add_child_die (context_die, old_die);
- subr_die = new_die (DW_TAG_subprogram, context_die, decl);
- add_abstract_origin_attribute (subr_die, origin);
- /* This is where the actual code for a cloned function is.
- Let's emit linkage name attribute for it. This helps
- debuggers to e.g, set breakpoints into
- constructors/destructors when the user asks "break
- K::K". */
- add_linkage_name (subr_die, decl);
+ if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+ {
+ /* If we have a DW_AT_abstract_origin we have a working
+ cached version. */
+ subr_die = old_die;
+ }
+ else
+ {
+ subr_die = new_die (DW_TAG_subprogram, context_die, decl);
+ add_abstract_origin_attribute (subr_die, origin);
+ /* This is where the actual code for a cloned function is.
+ Let's emit linkage name attribute for it. This helps
+ debuggers to e.g, set breakpoints into
+ constructors/destructors when the user asks "break
+ K::K". */
+ add_linkage_name (subr_die, decl);
+ }
}
/* A cached copy, possibly from early dwarf generation. Reuse as
much as possible. */
@@ -21738,6 +21770,9 @@ lookup_filename (const char *file_name)
{
struct dwarf_file_data * created;
+ if (!file_name)
+ return NULL;
+
/* Check to see if the file name that was searched on the previous
call matches this file name. If so, return the index. */
if (file_table_last_lookup
@@ -24739,10 +24774,19 @@ optimize_location_lists (dw_die_ref die)
static void
dwarf2out_finish (const char *filename)
{
- limbo_die_node *node, *next_node;
comdat_type_node *ctnode;
dw_die_ref main_comp_unit_die;
+ /* If the limbo list has anything, it should be things that were
+ created after the compilation proper. Anything from the early
+ dwarf pass, should have parents and should never be in the limbo
+ list this late. */
+ for (limbo_die_node *node = limbo_die_list; node; node = node->next)
+ gcc_assert (!node->die->dumped_early);
+
+ /* Flush out any latecomers to the limbo party. */
+ dwarf2out_early_finish();
+
/* PCH might result in DW_AT_producer string being restored from the
header compilation, so always fill it with empty string initially
and overwrite only here. */
@@ -24767,55 +24811,6 @@ dwarf2out_finish (const char *filename)
add_comp_dir_attribute (comp_unit_die ());
}
- /* Traverse the limbo die list, and add parent/child links. The only
- dies without parents that should be here are concrete instances of
- inline functions, and the comp_unit_die. We can ignore the comp_unit_die.
- For concrete instances, we can get the parent die from the abstract
- instance. */
- for (node = limbo_die_list; node; node = next_node)
- {
- dw_die_ref die = node->die;
- next_node = node->next;
-
- if (die->die_parent == NULL)
- {
- dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
-
- if (origin && origin->die_parent)
- add_child_die (origin->die_parent, die);
- else if (is_cu_die (die))
- ;
- else if (seen_error ())
- /* It's OK to be confused by errors in the input. */
- add_child_die (comp_unit_die (), die);
- else
- {
- /* In certain situations, the lexical block containing a
- nested function can be optimized away, which results
- in the nested function die being orphaned. Likewise
- with the return type of that nested function. Force
- this to be a child of the containing function.
-
- It may happen that even the containing function got fully
- inlined and optimized out. In that case we are lost and
- assign the empty child. This should not be big issue as
- the function is likely unreachable too. */
- gcc_assert (node->created_for);
-
- if (DECL_P (node->created_for))
- origin = get_context_die (DECL_CONTEXT (node->created_for));
- else if (TYPE_P (node->created_for))
- origin = scope_die_for (node->created_for, comp_unit_die ());
- else
- origin = comp_unit_die ();
-
- add_child_die (origin, die);
- }
- }
- }
-
- limbo_die_list = NULL;
-
#if ENABLE_ASSERT_CHECKING
{
dw_die_ref die = comp_unit_die (), c;
@@ -24863,6 +24858,7 @@ dwarf2out_finish (const char *filename)
/* Traverse the DIE's and add add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die ());
+ limbo_die_node *node;
for (node = limbo_die_list; node; node = node->next)
add_sibling_attributes (node->die);
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -25124,6 +25120,66 @@ dwarf2out_finish (const char *filename)
output_indirect_strings ();
}
+/* Perform any cleanups needed after the early debug generation pass
+ has run. */
+
+static void
+dwarf2out_early_finish (void)
+{
+ /* Traverse the limbo die list, and add parent/child links. The only
+ dies without parents that should be here are concrete instances of
+ inline functions, and the comp_unit_die. We can ignore the comp_unit_die.
+ For concrete instances, we can get the parent die from the abstract
+ instance.
+
+ The point here is to flush out the limbo list so that it is empty
+ and we don't need to stream it for LTO. */
+ limbo_die_node *node, *next_node;
+ for (node = limbo_die_list; node; node = next_node)
+ {
+ dw_die_ref die = node->die;
+ next_node = node->next;
+
+ if (die->die_parent == NULL)
+ {
+ dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+
+ if (origin && origin->die_parent)
+ add_child_die (origin->die_parent, die);
+ else if (is_cu_die (die))
+ ;
+ else if (seen_error ())
+ /* It's OK to be confused by errors in the input. */
+ add_child_die (comp_unit_die (), die);
+ else
+ {
+ /* In certain situations, the lexical block containing a
+ nested function can be optimized away, which results
+ in the nested function die being orphaned. Likewise
+ with the return type of that nested function. Force
+ this to be a child of the containing function.
+
+ It may happen that even the containing function got fully
+ inlined and optimized out. In that case we are lost and
+ assign the empty child. This should not be big issue as
+ the function is likely unreachable too. */
+ gcc_assert (node->created_for);
+
+ if (DECL_P (node->created_for))
+ origin = get_context_die (DECL_CONTEXT (node->created_for));
+ else if (TYPE_P (node->created_for))
+ origin = scope_die_for (node->created_for, comp_unit_die ());
+ else
+ origin = comp_unit_die ();
+
+ add_child_die (origin, die);
+ }
+ }
+ }
+
+ limbo_die_list = NULL;
+}
+
/* Reset all state within dwarf2out.c so that we can rerun the compiler
within the same process. For use by toplev::finalize. */
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index d7b2d6b..43b8cf2 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -279,6 +279,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
{
sdbout_init, /* init */
sdbout_finish, /* finish */
+ debug_nothing_void, /* early_finish */
debug_nothing_void, /* assembly_start */
debug_nothing_int_charstar, /* define */
debug_nothing_int_charstar, /* undef */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 42a2cdc..6b58ed2 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2136,6 +2136,21 @@ toplev::main (int argc, char **argv)
if (version_flag)
print_version (stderr, "");
+ /* FIXME: Temporary debugging aid to know which LTO phase we are in
+ without having to pass -v to the driver and all its verbosity. */
+ if (0)
+ {
+ fprintf(stderr, "MAIN: cc1*\n");
+ if (flag_lto)
+ fprintf(stderr, "\tMAIN: flag_lto\n");
+ if (in_lto_p)
+ fprintf(stderr, "\tMAIN: in_lto_p\n");
+ if (flag_wpa)
+ fprintf(stderr, "\tMAIN: flag_wpa\n");
+ if (flag_ltrans)
+ fprintf(stderr, "\tMAIN: flag_ltrans\n");
+ }
+
if (help_flag)
print_plugins_help (stderr, "");
diff --git a/gcc/tree.c b/gcc/tree.c
index 8743763..80b4287 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5730,6 +5730,10 @@ free_lang_data (void)
{
unsigned i;
+ /* Clean up anything that needs cleaning up after initial debug
+ generation. */
+ (*debug_hooks->early_finish) ();
+
/* If we are the LTO frontend we have freed lang-specific data already. */
if (in_lto_p
/* FIXME: Eventually we need to remove this so the function
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 5cb66bc..6da48eb 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -179,6 +179,7 @@ static void vmsdbgout_abstract_function (tree);
const struct gcc_debug_hooks vmsdbg_debug_hooks
= {vmsdbgout_init,
vmsdbgout_finish,
+ debug_nothing_void,
vmsdbgout_assembly_start,
vmsdbgout_define,
vmsdbgout_undef,
next prev parent reply other threads:[~2015-01-28 18:29 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-16 3:11 Aldy Hernandez
2015-01-16 4:30 ` Jason Merrill
2015-01-16 11:03 ` Richard Biener
2015-01-16 16:38 ` Jason Merrill
2015-01-16 18:09 ` Aldy Hernandez
2015-01-16 18:51 ` Richard Biener
2015-01-28 19:44 ` Aldy Hernandez
2015-01-16 17:54 ` Aldy Hernandez
2015-01-16 21:38 ` Jason Merrill
2015-01-23 19:53 ` Aldy Hernandez
2015-01-26 9:21 ` Richard Biener
2015-01-27 22:33 ` Jason Merrill
2015-01-28 19:24 ` Aldy Hernandez
2015-01-28 19:32 ` Aldy Hernandez [this message]
2015-01-28 19:47 ` Jason Merrill
2015-01-30 22:15 ` Aldy Hernandez
2015-01-30 22:23 ` Jason Merrill
2015-01-31 7:28 ` Aldy Hernandez
2015-02-01 6:27 ` Jason Merrill
2015-02-01 8:43 ` Richard Biener
2015-02-02 3:15 ` Aldy Hernandez
2015-02-02 4:16 ` Jason Merrill
2015-02-05 0:27 ` Aldy Hernandez
2015-02-05 20:11 ` Jason Merrill
2015-02-06 1:15 ` Aldy Hernandez
2015-02-06 14:02 ` Jason Merrill
2015-02-06 16:42 ` Aldy Hernandez
2015-02-06 17:40 ` Jason Merrill
2015-02-06 17:47 ` Aldy Hernandez
2015-02-10 10:52 ` Richard Biener
2015-02-10 17:58 ` Jason Merrill
2015-02-12 18:04 ` Aldy Hernandez
2015-02-12 19:27 ` Jason Merrill
2015-02-16 20:46 ` Aldy Hernandez
2015-02-01 8:42 ` Richard Biener
2015-02-02 1:48 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54C92A80.80306@redhat.com \
--to=aldyh@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=richard.guenther@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).