aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
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);