diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-03-05 21:17:44 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-03-05 21:17:44 +0100 |
commit | 1e3c1d950e3723c46ef467306bcaea3a4f1a85f2 (patch) | |
tree | 0a203dfd5709e8e57936d2ab25e4fc15b3529a67 /gcc/dwarf2out.c | |
parent | 8993fde43241743b76372651364048d45ce2309e (diff) | |
download | gcc-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.c | 54 |
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); |