@@ -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 *
@@ -3677,7 +3677,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
@@ -4777,6 +4777,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;
@@ -5515,6 +5516,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
@@ -8657,9 +8701,10 @@ 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)",
+ dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s (parent DIE=%#lx))",
(unsigned long)die->die_offset,
- dwarf_tag_name (die->die_tag));
+ dwarf_tag_name (die->die_tag),
+ die->die_parent ? die->die_parent->die_offset : 0);
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
{
@@ -17598,8 +17643,40 @@ 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 = NULL;
+
+ 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)
+ {
+ /* Check that parm_die already has the right attributes that
+ we would have added below. If any attributes are
+ missing, fall through to add them.
+
+ ?? Add more checks here. */
+ if (! DECL_ABSTRACT (node_or_origin)
+ && !get_AT (parm_die, DW_AT_location)
+ && !get_AT (parm_die, DW_AT_const_value))
+ /* We are missing location info, and are about to add it. */
+ ;
+ else
+ {
+ add_child_die (context_die, parm_die);
+ return parm_die;
+ }
+ }
+ }
+
+ bool reusing_die;
+ if (parm_die)
+ reusing_die = true;
+ else
+ {
+ parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
+ reusing_die = false;
+ }
switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
{
@@ -17607,7 +17684,11 @@ 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 (reusing_die)
+ goto add_location;
+
+ 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);
@@ -17631,6 +17712,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
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);
@@ -18147,7 +18229,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));
@@ -18177,7 +18259,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
&& !get_AT (old_die, DW_AT_inline))
{
/* Detect and ignore this case, where we are trying to output
- something we have already output. */
+ something we have already output.
+
+ If we have no location information, this must be a
+ partially generated DIE from early dwarf generation.
+ Fall through and generate it. */
+ if (get_AT (old_die, DW_AT_low_pc)
+ || get_AT (old_die, DW_AT_ranges))
return;
}
@@ -18196,6 +18284,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
{
subr_die = old_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
@@ -18204,6 +18296,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
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
{
@@ -18294,9 +18387,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))
@@ -18459,10 +18555,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
@@ -18566,7 +18672,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;
@@ -18886,7 +18994,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
@@ -21007,6 +21115,54 @@ 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)
+{
+ /* 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;
+ }
+ dwarf2out_decl (decl);
+ 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. */
@@ -5030,6 +5030,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);
@@ -5628,8 +5632,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