aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-03-05 21:17:44 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-03-05 21:17:44 +0100
commit1e3c1d950e3723c46ef467306bcaea3a4f1a85f2 (patch)
tree0a203dfd5709e8e57936d2ab25e4fc15b3529a67 /gcc/dwarf2out.c
parent8993fde43241743b76372651364048d45ce2309e (diff)
downloadgcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.zip
gcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.tar.gz
gcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.tar.bz2
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
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 63c46c0..b5f921a 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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);