re PR debug/51902 (lexical_blocks inside inlined_subroutines generate duplicate debug_ranges)

PR debug/51902
	* tree.h (BLOCK_SAME_RANGE): Define.
	* function.c (block_fragments_nreverse): Clear BLOCK_SAME_RANGE
	if BLOCK_FRAGMENT_CHAIN is non-NULL, but has it cleared.
	Also clear BLOCK_SAME_RANGE if fragment chain's supercontext fragment
	isn't equal to supercontext fragment's fragment chain.
	Adjust BLOCK_SUPERCONTEXT to point to supercontext fragment's
	fragment origin.
	(blocks_nreverse_all): Likewise.
	(reorder_blocks_1): Compute BLOCK_SAME_RANGE bits.  Set
	BLOCK_SUPERCONTEXT to supercontext fragment instead of
	supercontext fragment's fragment origin.
	* dwarf2out.c (add_high_low_attributes): If stmt has the same
	range as its parent (or parents thereof etc.), use the parent's
	DW_AT_ranges value instead of creating a new .debug_ranges range.

From-SVN: r184958
This commit is contained in:
Jakub Jelinek 2012-03-05 21:17:44 +01:00 committed by Jakub Jelinek
parent 8993fde432
commit 1e3c1d950e
4 changed files with 138 additions and 9 deletions

View File

@ -1,3 +1,21 @@
2012-03-05 Jakub Jelinek <jakub@redhat.com>
PR debug/51902
* tree.h (BLOCK_SAME_RANGE): Define.
* function.c (block_fragments_nreverse): Clear BLOCK_SAME_RANGE
if BLOCK_FRAGMENT_CHAIN is non-NULL, but has it cleared.
Also clear BLOCK_SAME_RANGE if fragment chain's supercontext fragment
isn't equal to supercontext fragment's fragment chain.
Adjust BLOCK_SUPERCONTEXT to point to supercontext fragment's
fragment origin.
(blocks_nreverse_all): Likewise.
(reorder_blocks_1): Compute BLOCK_SAME_RANGE bits. Set
BLOCK_SUPERCONTEXT to supercontext fragment instead of
supercontext fragment's fragment origin.
* dwarf2out.c (add_high_low_attributes): If stmt has the same
range as its parent (or parents thereof etc.), use the parent's
DW_AT_ranges value instead of creating a new .debug_ranges range.
2012-03-05 Richard Henderson <rth@redhat.com>
PR tree-opt/52242

View File

@ -18134,7 +18134,9 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
if (BLOCK_FRAGMENT_CHAIN (stmt)
&& (dwarf_version >= 3 || !dwarf_strict))
{
tree chain;
tree chain, superblock = NULL_TREE;
dw_die_ref pdie;
dw_attr_ref attr = NULL;
if (inlined_function_outer_scope_p (stmt))
{
@ -18143,6 +18145,56 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
add_AT_lbl_id (die, DW_AT_entry_pc, label);
}
/* Optimize duplicate .debug_ranges lists or even tails of
lists. If this BLOCK has same ranges as its supercontext,
lookup DW_AT_ranges attribute in the supercontext (and
recursively so), verify that the ranges_table contains the
right values and use it instead of adding a new .debug_range. */
for (chain = stmt, pdie = die;
BLOCK_SAME_RANGE (chain);
chain = BLOCK_SUPERCONTEXT (chain))
{
dw_attr_ref new_attr;
pdie = pdie->die_parent;
if (pdie == NULL)
break;
if (BLOCK_SUPERCONTEXT (chain) == NULL_TREE)
break;
new_attr = get_AT (pdie, DW_AT_ranges);
if (new_attr == NULL
|| new_attr->dw_attr_val.val_class != dw_val_class_range_list)
break;
attr = new_attr;
superblock = BLOCK_SUPERCONTEXT (chain);
}
if (attr != NULL
&& (ranges_table[attr->dw_attr_val.v.val_offset
/ 2 / DWARF2_ADDR_SIZE].num
== BLOCK_NUMBER (superblock))
&& BLOCK_FRAGMENT_CHAIN (superblock))
{
unsigned long off = attr->dw_attr_val.v.val_offset
/ 2 / DWARF2_ADDR_SIZE;
unsigned long supercnt = 0, thiscnt = 0;
for (chain = BLOCK_FRAGMENT_CHAIN (superblock);
chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
{
++supercnt;
gcc_checking_assert (ranges_table[off + supercnt].num
== BLOCK_NUMBER (chain));
}
gcc_checking_assert (ranges_table[off + supercnt + 1].num == 0);
for (chain = BLOCK_FRAGMENT_CHAIN (stmt);
chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
++thiscnt;
gcc_assert (supercnt >= thiscnt);
add_AT_range_list (die, DW_AT_ranges,
(off + supercnt - thiscnt)
* 2 * DWARF2_ADDR_SIZE);
return;
}
add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
chain = BLOCK_FRAGMENT_CHAIN (stmt);

View File

@ -3998,18 +3998,35 @@ generate_setjmp_warnings (void)
/* Reverse the order of elements in the fragment chain T of blocks,
and return the new head of the chain (old last element). */
and return the new head of the chain (old last element).
In addition to that clear BLOCK_SAME_RANGE flags when needed
and adjust BLOCK_SUPERCONTEXT from the super fragment to
its super fragment origin. */
static tree
block_fragments_nreverse (tree t)
{
tree prev = 0, block, next;
tree prev = 0, block, next, prev_super = 0;
tree super = BLOCK_SUPERCONTEXT (t);
if (BLOCK_FRAGMENT_ORIGIN (super))
super = BLOCK_FRAGMENT_ORIGIN (super);
for (block = t; block; block = next)
{
next = BLOCK_FRAGMENT_CHAIN (block);
BLOCK_FRAGMENT_CHAIN (block) = prev;
if ((prev && !BLOCK_SAME_RANGE (prev))
|| (BLOCK_FRAGMENT_CHAIN (BLOCK_SUPERCONTEXT (block))
!= prev_super))
BLOCK_SAME_RANGE (block) = 0;
prev_super = BLOCK_SUPERCONTEXT (block);
BLOCK_SUPERCONTEXT (block) = super;
prev = block;
}
t = BLOCK_FRAGMENT_ORIGIN (t);
if (BLOCK_FRAGMENT_CHAIN (BLOCK_SUPERCONTEXT (t))
!= prev_super)
BLOCK_SAME_RANGE (t) = 0;
BLOCK_SUPERCONTEXT (t) = super;
return prev;
}
@ -4026,11 +4043,15 @@ blocks_nreverse_all (tree t)
{
next = BLOCK_CHAIN (block);
BLOCK_CHAIN (block) = prev;
BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block));
if (BLOCK_FRAGMENT_CHAIN (block)
&& BLOCK_FRAGMENT_ORIGIN (block) == NULL_TREE)
BLOCK_FRAGMENT_CHAIN (block)
= block_fragments_nreverse (BLOCK_FRAGMENT_CHAIN (block));
{
BLOCK_FRAGMENT_CHAIN (block)
= block_fragments_nreverse (BLOCK_FRAGMENT_CHAIN (block));
if (!BLOCK_SAME_RANGE (BLOCK_FRAGMENT_CHAIN (block)))
BLOCK_SAME_RANGE (block) = 0;
}
BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block));
prev = block;
}
return prev;
@ -4085,6 +4106,7 @@ static void
reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
{
rtx insn;
tree prev_beg = NULL_TREE, prev_end = NULL_TREE;
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
@ -4098,12 +4120,17 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
gcc_assert (BLOCK_FRAGMENT_ORIGIN (block) == NULL_TREE);
origin = block;
if (prev_end)
BLOCK_SAME_RANGE (prev_end) = 0;
prev_end = NULL_TREE;
/* If we have seen this block before, that means it now
spans multiple address regions. Create a new fragment. */
if (TREE_ASM_WRITTEN (block))
{
tree new_block = copy_node (block);
BLOCK_SAME_RANGE (new_block) = 0;
BLOCK_FRAGMENT_ORIGIN (new_block) = origin;
BLOCK_FRAGMENT_CHAIN (new_block)
= BLOCK_FRAGMENT_CHAIN (origin);
@ -4113,6 +4140,11 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
block = new_block;
}
if (prev_beg == current_block && prev_beg)
BLOCK_SAME_RANGE (block) = 1;
prev_beg = origin;
BLOCK_SUBBLOCKS (block) = 0;
TREE_ASM_WRITTEN (block) = 1;
/* When there's only one block for the entire function,
@ -4120,10 +4152,22 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
will cause infinite recursion. */
if (block != current_block)
{
tree super;
if (block != origin)
gcc_assert (BLOCK_SUPERCONTEXT (origin) == current_block);
BLOCK_SUPERCONTEXT (block) = current_block;
gcc_assert (BLOCK_SUPERCONTEXT (origin) == current_block
|| BLOCK_FRAGMENT_ORIGIN (BLOCK_SUPERCONTEXT
(origin))
== current_block);
if (VEC_empty (tree, *p_block_stack))
super = current_block;
else
{
super = VEC_last (tree, *p_block_stack);
gcc_assert (super == current_block
|| BLOCK_FRAGMENT_ORIGIN (super)
== current_block);
}
BLOCK_SUPERCONTEXT (block) = super;
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
BLOCK_SUBBLOCKS (current_block) = block;
current_block = origin;
@ -4134,8 +4178,20 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
{
NOTE_BLOCK (insn) = VEC_pop (tree, *p_block_stack);
current_block = BLOCK_SUPERCONTEXT (current_block);
if (BLOCK_FRAGMENT_ORIGIN (current_block))
current_block = BLOCK_FRAGMENT_ORIGIN (current_block);
prev_beg = NULL_TREE;
prev_end = BLOCK_SAME_RANGE (NOTE_BLOCK (insn))
? NOTE_BLOCK (insn) : NULL_TREE;
}
}
else
{
prev_beg = NULL_TREE;
if (prev_end)
BLOCK_SAME_RANGE (prev_end) = 0;
prev_end = NULL_TREE;
}
}
}

View File

@ -2088,6 +2088,9 @@ struct GTY(()) tree_omp_clause {
#define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin)
#define BLOCK_ABSTRACT(NODE) (BLOCK_CHECK (NODE)->block.abstract_flag)
/* True if BLOCK has the same ranges as its BLOCK_SUPERCONTEXT. */
#define BLOCK_SAME_RANGE(NODE) (BLOCK_CHECK (NODE)->base.nameless_flag)
/* An index number for this block. These values are not guaranteed to
be unique across functions -- whether or not they are depends on
the debugging output format in use. */