summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-04 16:37:36 +0000
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-04 16:37:36 +0000
commit604bb4b40c10256e89cf078af101857560f1aa74 (patch)
tree64d516c6714ccf738bf4c8580b17ca9b6cfea129
parent138af246461066d3ad5af2297a9bf4bea2a8b769 (diff)
downloadgcc-604bb4b40c10256e89cf078af101857560f1aa74.tar.gz
dearly: Emit DIEs for decls early in the compilation process.
This is the original patch from Michael Matz, ported to a more recent mainline. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214906 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/debug.h2
-rw-r--r--gcc/dwarf2out.c120
-rw-r--r--gcc/tree.c7
3 files changed, 118 insertions, 11 deletions
diff --git a/gcc/debug.h b/gcc/debug.h
index 3ac7976c5de..28bc2104b1b 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -187,6 +187,8 @@ 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 23a80d831cb..e624e38ca7e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3679,7 +3679,7 @@ decl_ultimate_origin (const_tree decl)
/* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the
nodes in the function to point to themselves; ignore that if
we're trying to output the abstract instance of this function. */
- if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl)
+ if (/*DECL_ABSTRACT (decl) &&*/ DECL_ABSTRACT_ORIGIN (decl) == decl)
return NULL_TREE;
/* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
@@ -4779,6 +4779,7 @@ remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
while (c->die_tag == tag)
{
remove_child_with_prev (c, prev);
+ c->die_parent = NULL;
/* Might have removed every child. */
if (c == c->die_sib)
return;
@@ -5517,6 +5518,49 @@ debug_dwarf (void)
print_indent = 0;
print_die (comp_unit_die (), stderr);
}
+
+/* Perform some sanity checks on DIEs after they have been generated
+ earlier in the compilation process. */
+
+static void
+check_die (dw_die_ref die, unsigned level)
+{
+ static unsigned long mark = 1;
+ dw_die_ref c, p;
+ /* Check that all our childs have their parent set to us. */
+ c = die->die_child;
+ if (c) do {
+ c = c->die_sib;
+ gcc_assert (c->die_parent == die);
+ } while (c != die->die_child);
+
+ /* Check the we are part of our parent's child list. */
+ mark++;
+ p = die->die_parent;
+ if (p)
+ {
+ c = p->die_child;
+ gcc_assert (c);
+ do {
+ c = c->die_sib;
+ /* Found it. */
+ if (c == die)
+ break;
+ /* If we're at start --> not found. */
+ gcc_assert (c != p->die_child);
+ /* If we've seen this node already the circular list doesn't
+ even go back to start. */
+ gcc_assert (c->die_abbrev != mark);
+ c->die_abbrev = mark;
+ } while (1);
+ }
+
+ if (!level)
+ return;
+
+ FOR_EACH_CHILD (die, c, check_die (c, level - 1));
+}
+
/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU
for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL
@@ -17603,8 +17647,22 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
{
tree node_or_origin = node ? node : origin;
tree ultimate_origin;
- dw_die_ref parm_die
- = new_die (DW_TAG_formal_parameter, context_die, node);
+ dw_die_ref parm_die;
+
+ if (TREE_CODE_CLASS (TREE_CODE (node_or_origin)) == tcc_declaration)
+ {
+ parm_die = lookup_decl_die (node);
+
+ if (parm_die && parm_die->die_parent == NULL)
+ {
+ add_child_die (context_die, parm_die);
+ /* XXX check that parm_die already has all the right attributes
+ that we would add below? */
+ return parm_die;
+ }
+ }
+
+ parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
{
@@ -17612,7 +17670,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
ultimate_origin = decl_ultimate_origin (node_or_origin);
if (node || ultimate_origin)
origin = ultimate_origin;
- if (origin != NULL)
+ if (origin != NULL && node != origin)
add_abstract_origin_attribute (parm_die, origin);
else if (emit_name_p)
add_name_and_src_coords_attributes (parm_die, node);
@@ -18150,7 +18208,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
&& debug_info_level > DINFO_LEVEL_TERSE)
old_die = force_decl_die (decl);
- if (origin != NULL)
+ if (origin != NULL && origin != decl)
{
gcc_assert (!declaration || local_scope_p (context_die));
@@ -18297,9 +18355,12 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
equate_decl_number_to_die (decl, subr_die);
}
- else if (!DECL_EXTERNAL (decl))
+ else if (!DECL_EXTERNAL (decl)
+ && (!DECL_STRUCT_FUNCTION (decl)
+ || DECL_STRUCT_FUNCTION (decl)->gimple_df))
{
HOST_WIDE_INT cfa_fb_offset;
+
struct function *fun = DECL_STRUCT_FUNCTION (decl);
if (!old_die || !get_AT (old_die, DW_AT_inline))
@@ -18462,10 +18523,20 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
add_AT_location_description (subr_die, DW_AT_static_link,
loc_list_from_tree (fun->static_chain_decl, 2));
}
+ else if (!DECL_EXTERNAL (decl))
+ {
+ if (!old_die || !get_AT (old_die, DW_AT_inline))
+ equate_decl_number_to_die (decl, subr_die);
+ }
/* Generate child dies for template paramaters. */
if (debug_info_level > DINFO_LEVEL_TERSE)
- gen_generic_params_dies (decl);
+ {
+ /* XXX */
+ if (!lookup_decl_die (decl))
+ equate_decl_number_to_die (decl, subr_die);
+ gen_generic_params_dies (decl);
+ }
/* Now output descriptions of the arguments for this function. This gets
(unnecessarily?) complex because of the fact that the DECL_ARGUMENT list
@@ -18569,7 +18640,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
a BLOCK node representing the function's outermost pair of curly braces,
and any blocks used for the base and member initializers of a C++
constructor function. */
- if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
+ if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK
+ && (!DECL_STRUCT_FUNCTION (decl)
+ || DECL_STRUCT_FUNCTION (decl)->gimple_df))
{
int call_site_note_count = 0;
int tail_call_site_note_count = 0;
@@ -18889,7 +18962,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
and if we already emitted a DIE for it, don't emit a second
DIE for it again. Allow re-declarations of DECLs that are
inside functions, though. */
- if (old_die && declaration && !local_scope_p (context_die))
+ if (old_die && !declaration && !local_scope_p (context_die))
return;
/* For static data members, the declaration in the class is supposed
@@ -21010,6 +21083,35 @@ dwarf2out_decl (tree decl)
}
gen_decl_die (decl, NULL, context_die);
+
+ dw_die_ref die = lookup_decl_die (decl);
+ if (die)
+ check_die (die, 0);
+}
+
+/* Early dumping of DECLs before we lose language data. */
+
+void
+dwarf2out_early_decl (tree decl)
+{
+ /* 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)
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (decl));
+ current_function_decl = decl;
+ }
+ dwarf2out_decl (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ pop_cfun ();
+ current_function_decl = NULL;
+ }
+ }
}
/* Write the debugging output for DECL. */
diff --git a/gcc/tree.c b/gcc/tree.c
index d1d67efa629..afc8e3d9559 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5032,6 +5032,10 @@ 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);
@@ -5630,8 +5634,7 @@ free_lang_data (void)
unsigned i;
/* If we are the LTO frontend we have freed lang-specific data already. */
- if (in_lto_p
- || !flag_generate_lto)
+ if (in_lto_p)
return 0;
/* Allocate and assign alias sets to the standard integer types