dearly: Emit DIEs for decls early in the compilation process.

This is the original patch from Michael Matz, ported to a more recent
mainline.

From-SVN: r214906
This commit is contained in:
Aldy Hernandez 2014-09-04 16:37:36 +00:00
parent 5143726943
commit 73179e4a24
3 changed files with 118 additions and 11 deletions

View File

@ -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 *

View File

@ -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. */

View File

@ -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