[PATCH] Prune useless .debug_loc entries (PR debug/43442)
Jakub Jelinek
jakub@redhat.com
Mon Mar 22 09:24:00 GMT 2010
Hi!
While working on PR43058, I've noticed that we emit tons of useless
.debug_loc entries. By useless I mean locations for variable in ranges
where the variable isn't said to be in scope. If a variable DIE is
a child of DW_TAG_lexical_block or DW_TAG_inlined_subroutine which has
DW_AT_ranges 0-10 20-30 40-50, then a .debug_loc entry that the variable
is alive in regXYZ between 12 and 18 or 30 and 40 is IMNSHO not useful
to any of the debug info consumers, the debugger will not find the variable
on insn 15 at all, as it is not in scope there.
While it would be best to prune this already at var-tracking time (and
perhaps, even avoid tracking related VALUEs that aren't used for anything
else beyond certain spot), it would be very hard. There is some minor code
motion even after var-tracking (delayed branch scheduling) and because of
that movement, splitting blocks into fragments would be also premature.
Perhaps one day when cfg is maintained up to final var-tracking could be
taught about SEQUENCEs and dbr stuff and run after dbr, right before final.
So this patch instead does the pruning at the time when debug info is
generated. It is done by remembering block scope change events
(each group of NOTE_INSN_BLOCK_{BEG,END} notes with no intervening real
insns is assigned an even number, odd numbers in between stand for
places in real insns between the two scope change note groups.
Each dwarf2out_var_location call remembers the scope change event counter
value at the spot where the note is present (it can be also at the
scope change note boundary if there are no insns in between it and the
NOTE_INSN_BLOCK_{BEG,END} notes, or somewhere in between - notes for
inside of a call are always considered in between the note groups)
and when we create location lists from var_loc_node chain recorded
by dwarf2out_var_location, we can skip entries which are not in the range(s)
of the containing DW_TAG_lexical_block/DW_TAG_inlined_subroutine.
The patch has big effect on the size of debug info. Here are changes
from vanilla tree with the patch below applied but effectively disabled
(added "|| 1" in the first conditional in in_scope_var_loc_node, so
all nodes are considered to be in scope like they used to be) to
patched tree where the "|| 1" is missing.
x86_64-linux stage3 cc1plus all nodes in scope:
[28] .debug_info PROGBITS 0000000000000000 10eb517 149eab7 00 0 0 1
[32] .debug_loc PROGBITS 0000000000000000 2a6ace7 1e300ab 00 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 49fcab8 7b8020 00 0 0 1
x86_64-linux stage3 cc1plus with the patch:
[28] .debug_info PROGBITS 0000000000000000 10eb517 149af57 00 0 0 1
[32] .debug_loc PROGBITS 0000000000000000 2a672c4 1318257 00 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 3ee1241 7b7fa0 00 0 0 1
i686-linux stage3 cc1plus all nodes in scope:
[28] .debug_info PROGBITS 00000000 1002ada 139b6cd 00 0 0 1
[33] .debug_loc PROGBITS 00000000 2905694 f6b1b1 00 0 0 1
[35] .debug_ranges PROGBITS 00000000 39d3741 3c1400 00 0 0 1
i686-linux stage3 cc1plus with the patch:
[28] .debug_info PROGBITS 00000000 1002ada 1397d82 00 0 0 1
[33] .debug_loc PROGBITS 00000000 2901ed0 9b0f44 00 0 0 1
[35] .debug_ranges PROGBITS 00000000 3415d10 3c1438 00 0 0 1
This was --enable-checking=yes,rtl build btw. Approximately 3500 variables
(mostly __t or __i from the various rtl checking macros) lost their DW_AT_location
altogether, because none of the .debug_loc entries for them overlapped with the
ranges of the containing block, and .debug_loc shrunk by ~ 37%.
cc1plus size on x86_64 decreased from 86921679 to 75274552 bytes, and on i686
from 65568300 59548797 to bytes.
Attached is a short analysis of a few randomly chosen variables that lost their
DW_AT_location resp. their location list shrunk. Always .debug_info snippet
is followed by related .debug_ranges snippet followed by .debug_loc snippet.
Earlier version of the patch (the one attached in the PR) saved even more,
but only because it was throwing also entries which were in scope - I assumed
block fragments are sorted in order of increasing PC, but they were sorted
with smallest PC fragment coming first, then highest PC fragment, then one
before highest PC fragment, etc. down to second PC fragment. So for one or
two fragments blocks it worked well, but for more fragmented blocks it could
think some range is not in scope when it actually was. This got fixed by
the function.c changes - the effect is that now DW_AT_ranges lists are
sorted by increasing PC, at least within each section (hot cold partitioning
still can make the sorting appear in different order, they are sorted
by increasing assembly line number and not PC actually, but that's what
is desirable for the location list pruning anyway).
CCing some folks from the debug info consumer side to verify that we are
indeed dropping info that consumers aren't interested in.
I'd say it can be declared to fix a regression that .debug_loc size increased
by huge amount from 4.4; if it would be for something useful, that's of course
price to be paid for better debug info, but if lots of that growth accounts
for info that no debug info consumer will ever care about...
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Jakub
-------------- next part --------------
2010-03-22 Jakub Jelinek <jakub@redhat.com>
PR debug/43442
* debug.h (struct gcc_debug_hooks): Change last argument of
begin_block and end_block callbacks to rtx.
(debug_nothing_int_int): Remove.
(debug_nothing_int_rtx): New prototype.
* debug.c (do_nothing_debug_hooks): Change begin_block and
end_block callbacks to debug_nothing_int_rtx.
(debug_nothing_int_int): Remove.
(debug_nothing_int_rtx): New function.
* dwarf2out.c (dwarf2_debug_hooks): Change function_decl callback
to dwarf2out_function_decl.
(struct var_loc_node): Add block_evcntr field.
(struct block_map_struct): New type.
(lowest_blocknum, highest_blocknum, block_map, block_evcntr): New
static variables.
(containing_block, in_scope_var_loc_node): New functions.
(dw_loc_list): Use them to skip over useless location list ranges.
Add DIE argument.
(loc_list_from_tree, loc_descriptor_from_tree,
loc_list_for_address_of_addr_expr_of_indirect_ref): Add DIE
argument, adjust callers.
(tls_mem_loc_descriptor, add_location_or_const_value_attribute,
add_bound_info, gen_array_type_die, gen_subprogram_die,
gen_variable_die): Adjust callers.
(dwarf2out_abstract_function): Save block_map and clear it for
inline fn debug info generation, restore afterwards.
(gen_lexical_block_die, gen_inlined_subroutine_die): If block_map,
set new created DIE's decl_id to block index in block_map array,
set die field in block_map array.
(gen_block_die): When seeing a BLOCK_FRAGMENT_CHAIN, make sure to
recurse with the right context_die.
(dwarf2out_function_decl): New function.
(update_block_evcntr): New function.
(dwarf2out_begin_block, dwarf2out_end_block): Change second argument
to rtx, call update_block_evcntr, fill in block's block_map fields.
(dwarf2out_var_location): Compute new block_evcntr field.
* final.c (final_scan_insn): Pass note insn itself rather than
BLOCK_NUMBER (NOTE_BLOCK (insn)) as second argument to begin_block
and end_block debug hooks.
* vmsdbgout.c (vmsdbgout_begin_block, vmsdbgout_end_block): Change
second argument to rtx.
* dbxout.c (dbxout_begin_block, dbxout_end_block): Likewise.
* xcoffout.h (xcoffout_begin_block, xcoffout_end_block): Likewise.
* xcoffout.c (xcoffout_begin_block, xcoffout_end_block): Likewise.
* sdbout.c (sdbout_begin_block, sdbout_end_block): Likewise.
* function.c (block_fragments_nreverse, blocks_nreverse_all): New
functions.
(reorder_blocks): Use blocks_nreverse_all instead of blocks_nreverse.
(reorder_blocks_1): Assert BLOCK_FRAGMENT_ORIGIN is NULL. Don't
call block_nreverse here.
--- gcc/debug.h.jj 2009-11-02 12:16:49.000000000 +0100
+++ gcc/debug.h 2010-03-19 18:19:45.000000000 +0100
@@ -49,12 +49,11 @@ struct gcc_debug_hooks
in the source file we are returning to. */
void (* end_source_file) (unsigned int line);
- /* Record the beginning of block N, counting from 1 and not
- including the function-scope block, at LINE. */
- void (* begin_block) (unsigned int line, unsigned int n);
+ /* Record the beginning of block on NOTE. */
+ void (* begin_block) (unsigned int line, rtx note);
- /* Record the end of a block. Arguments as for begin_block. */
- void (* end_block) (unsigned int line, unsigned int n);
+ /* Record the end of a block. */
+ void (* end_block) (unsigned int line, rtx note);
/* Returns nonzero if it is appropriate not to emit any debugging
information for BLOCK, because it doesn't contain any
@@ -173,7 +172,7 @@ extern void debug_nothing_int_charstar (
extern void debug_nothing_int_charstar_int_bool (unsigned int, const char *,
int, bool);
extern void debug_nothing_int (unsigned int);
-extern void debug_nothing_int_int (unsigned int, unsigned int);
+extern void debug_nothing_int_rtx (unsigned int, rtx);
extern void debug_nothing_tree (tree);
extern void debug_nothing_tree_tree (tree, tree);
extern void debug_nothing_tree_int (tree, int);
--- gcc/debug.c.jj 2009-11-02 12:16:49.000000000 +0100
+++ gcc/debug.c 2010-03-19 18:19:45.000000000 +0100
@@ -32,8 +32,8 @@ const struct gcc_debug_hooks do_nothing_
debug_nothing_int_charstar,
debug_nothing_int_charstar,
debug_nothing_int,
- debug_nothing_int_int, /* begin_block */
- debug_nothing_int_int, /* end_block */
+ debug_nothing_int_rtx, /* begin_block */
+ debug_nothing_int_rtx, /* end_block */
debug_true_const_tree, /* ignore_block */
debug_nothing_int_charstar_int_bool, /* source_line */
debug_nothing_int_charstar, /* begin_prologue */
@@ -128,8 +128,8 @@ debug_nothing_int (unsigned int line ATT
}
void
-debug_nothing_int_int (unsigned int line ATTRIBUTE_UNUSED,
- unsigned int n ATTRIBUTE_UNUSED)
+debug_nothing_int_rtx (unsigned int line ATTRIBUTE_UNUSED,
+ rtx note ATTRIBUTE_UNUSED)
{
}
--- gcc/dwarf2out.c.jj 2010-03-19 17:52:59.000000000 +0100
+++ gcc/dwarf2out.c 2010-03-21 17:54:14.000000000 +0100
@@ -5399,9 +5399,10 @@ static void dwarf2out_define (unsigned i
static void dwarf2out_undef (unsigned int, const char *);
static void dwarf2out_start_source_file (unsigned, const char *);
static void dwarf2out_end_source_file (unsigned);
-static void dwarf2out_begin_block (unsigned, unsigned);
-static void dwarf2out_end_block (unsigned, unsigned);
+static void dwarf2out_begin_block (unsigned, rtx);
+static void dwarf2out_end_block (unsigned, rtx);
static bool dwarf2out_ignore_block (const_tree);
+static void dwarf2out_function_decl (tree);
static void dwarf2out_global_decl (tree);
static void dwarf2out_type_decl (tree, int);
static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
@@ -5436,7 +5437,7 @@ const struct gcc_debug_hooks dwarf2_debu
dwarf2out_end_epilogue,
dwarf2out_begin_function,
debug_nothing_int, /* end_function */
- dwarf2out_decl, /* function_decl */
+ dwarf2out_function_decl, /* function_decl */
dwarf2out_global_decl,
dwarf2out_type_decl, /* type_decl */
dwarf2out_imported_module_or_decl,
@@ -5722,6 +5723,7 @@ struct GTY ((chain_next ("%h.next"))) va
const char * GTY (()) label;
const char * GTY (()) section_label;
struct var_loc_node * GTY (()) next;
+ unsigned int block_evcntr;
};
/* Variable location list. */
@@ -6081,8 +6083,8 @@ static dw_loc_descr_ref concat_loc_descr
enum var_init_status);
static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
enum var_init_status);
-static dw_loc_list_ref loc_list_from_tree (tree, int);
-static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+static dw_loc_list_ref loc_list_from_tree (tree, dw_die_ref, int);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree, dw_die_ref, int);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
static tree field_type (const_tree);
static unsigned int simple_type_align_in_bits (const_tree);
@@ -6295,6 +6297,27 @@ static char ranges_section_label[2 * MAX
#define SEPARATE_LINE_CODE_LABEL "LSM"
#endif
+/* Lowest and highest BLOCK_NUMBER in the current function. */
+static unsigned int lowest_blocknum, highest_blocknum;
+
+/* Struct to map BLOCK_NUMBER (subblock) - lowest_blocknum
+ to block_evcntr value on entry and exit of the block
+ (resp. fragment thereof), the block itself and die if any
+ has been generated for it. */
+struct block_map_struct
+{
+ unsigned int entry_block_evcntr;
+ unsigned int exit_block_evcntr;
+ tree block;
+ struct die_struct *die;
+} *block_map;
+
+/* This counts significant events in block scope changes.
+ 0 is at the beginning of function, odd numbers are in real
+ insns in between block scope changes, and each group of
+ NOTE_INSN_BLOCK_BEG/END notes with no intervening real
+ insn is given an even number. */
+static unsigned int block_evcntr;
/* We allow a language front-end to designate a function that is to be
called to "demangle" any name before it is put into a DIE. */
@@ -12781,7 +12804,7 @@ tls_mem_loc_descriptor (rtx mem)
|| !DECL_THREAD_LOCAL_P (base))
return NULL;
- loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1);
+ loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), NULL, 1);
if (loc_result == NULL)
return NULL;
@@ -14046,21 +14069,80 @@ dw_loc_list_1 (tree loc, rtx varloc, int
return descr;
}
+/* Return a block if DIE is in scope of some lexical block
+ (or inlined_subroutine block) in current function, NULL otherwise. */
+
+static tree
+containing_block (dw_die_ref die)
+{
+ if (block_map == NULL)
+ return NULL_TREE;
+ for (; die != NULL; die = die->die_parent)
+ switch (die->die_tag)
+ {
+ case DW_TAG_lexical_block:
+ case DW_TAG_inlined_subroutine:
+ if (die->decl_id == (unsigned) -1
+ || die->decl_id > highest_blocknum - lowest_blocknum
+ || block_map[die->decl_id].die != die)
+ return NULL_TREE;
+ return block_map[die->decl_id].block;
+ case DW_TAG_subprogram:
+ case DW_TAG_compile_unit:
+ return NULL_TREE;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
+/* If *BLOCK is non-NULL, skip over VAR_LOCATION notes that are not useful
+ for debug info, as their range doesn't overlap any of the containing's
+ block fragment. */
+
+static struct var_loc_node *
+in_scope_var_loc_node (struct var_loc_node *node, tree *block)
+{
+ if (node == NULL || *block == NULL_TREE)
+ return node;
+ /* Skip over block fragments that end before the VAR_LOCATION note
+ or at the same location. */
+ while (block_map[BLOCK_NUMBER (*block) - lowest_blocknum].exit_block_evcntr
+ <= node->block_evcntr)
+ {
+ *block = BLOCK_FRAGMENT_CHAIN (*block);
+ /* If all fragments of the containing block are before this
+ var_loc_node, no further var_loc_node is in scope. */
+ if (!*block)
+ return NULL;
+ }
+ /* Skip over VAR_LOCATION notes where the next VAR_LOCATION note starts before
+ start of the next fragment or at the same location. */
+ while (node->next
+ && (block_map[BLOCK_NUMBER (*block)
+ - lowest_blocknum].entry_block_evcntr
+ >= node->next->block_evcntr))
+ node = node->next;
+ return node;
+}
+
/* Return the dwarf representation of the location list LOC_LIST of
DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree
function. */
static dw_loc_list_ref
-dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
+dw_loc_list (var_loc_list *loc_list, tree decl, dw_die_ref die,
+ int want_address)
{
const char *endname, *secname;
rtx varloc;
enum var_init_status initialized;
- struct var_loc_node *node;
+ struct var_loc_node *node, *next;
dw_loc_descr_ref descr;
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
dw_loc_list_ref list = NULL;
dw_loc_list_ref *listp = &list;
+ tree block = containing_block (die);
/* Now that we know what section we are using for a base,
actually construct the list of locations.
@@ -14075,42 +14157,45 @@ dw_loc_list (var_loc_list *loc_list, tre
secname = secname_for_decl (decl);
- for (node = loc_list->first; node->next; node = node->next)
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
- {
- /* The variable has a location between NODE->LABEL and
- NODE->NEXT->LABEL. */
- initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
- if (descr)
- {
- *listp = new_loc_list (descr, node->label, node->next->label,
- secname);
- listp = &(*listp)->dw_loc_next;
- }
- }
-
- /* If the variable has a location at the last label
- it keeps its location until the end of function. */
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
- {
- initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
- if (descr)
+ for (node = in_scope_var_loc_node (loc_list->first, &block);
+ node; node = next)
+ {
+ next = node;
+ while ((next = in_scope_var_loc_node (next->next, &block)) != NULL)
{
- if (!current_function_decl)
- endname = text_end_label;
- else
+ rtx loc1 = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
+ rtx loc2 = NOTE_VAR_LOCATION_LOC (next->var_loc_note);
+ if (!rtx_equal_p (loc1, loc2)
+ || (NOTE_VAR_LOCATION_STATUS (node->var_loc_note)
+ != NOTE_VAR_LOCATION_STATUS (next->var_loc_note)
+ && ((NOTE_VAR_LOCATION_STATUS (node->var_loc_note)
+ == VAR_INIT_STATUS_UNINITIALIZED)
+ || (NOTE_VAR_LOCATION_STATUS (next->var_loc_note)
+ == VAR_INIT_STATUS_UNINITIALIZED))))
+ break;
+ }
+ if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+ {
+ /* The variable has a location between NODE->LABEL and
+ either NEXT->LABEL or the end of function. */
+ initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
+ varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
+ if (descr)
{
- ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
- current_function_funcdef_no);
- endname = ggc_strdup (label_id);
+ if (next)
+ endname = next->label;
+ else if (!current_function_decl)
+ endname = text_end_label;
+ else
+ {
+ ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+ current_function_funcdef_no);
+ endname = ggc_strdup (label_id);
+ }
+ *listp = new_loc_list (descr, node->label, endname, secname);
+ listp = &(*listp)->dw_loc_next;
}
-
- *listp = new_loc_list (descr, node->label, endname, secname);
- listp = &(*listp)->dw_loc_next;
}
}
@@ -14235,7 +14320,8 @@ cst_pool_loc_descr (tree loc)
into simple arithmetics. */
static dw_loc_list_ref
-loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
+loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, dw_die_ref die,
+ bool toplev)
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
@@ -14260,18 +14346,18 @@ loc_list_for_address_of_addr_expr_of_ind
return 0;
}
if (!offset && !bitpos)
- list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
+ list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), die, toplev ? 2 : 1);
else if (toplev
&& int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
&& (dwarf_version >= 4 || !dwarf_strict))
{
- list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), die, 0);
if (!list_ret)
return 0;
if (offset)
{
/* Variable offset. */
- list_ret1 = loc_list_from_tree (offset, 0);
+ list_ret1 = loc_list_from_tree (offset, die, 0);
if (list_ret1 == 0)
return 0;
add_loc_list (&list_ret, list_ret1);
@@ -14302,7 +14388,7 @@ loc_list_for_address_of_addr_expr_of_ind
to refer to register values). */
static dw_loc_list_ref
-loc_list_from_tree (tree loc, int want_address)
+loc_list_from_tree (tree loc, dw_die_ref die, int want_address)
{
dw_loc_descr_ref ret = NULL, ret1 = NULL;
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
@@ -14346,7 +14432,7 @@ loc_list_from_tree (tree loc, int want_a
if (want_address)
{
list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
- (loc, want_address == 2);
+ (loc, die, want_address == 2);
if (list_ret)
have_address = 1;
else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
@@ -14355,7 +14441,7 @@ loc_list_from_tree (tree loc, int want_a
}
/* Otherwise, process the argument and look for the address. */
if (!list_ret && !ret)
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 1);
else
{
if (want_address)
@@ -14423,7 +14509,7 @@ loc_list_from_tree (tree loc, int want_a
case PARM_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
- return loc_list_from_tree (DECL_VALUE_EXPR (loc),
+ return loc_list_from_tree (DECL_VALUE_EXPR (loc), die,
want_address);
/* FALLTHRU */
@@ -14435,7 +14521,7 @@ loc_list_from_tree (tree loc, int want_a
if (loc_list && loc_list->first)
{
- list_ret = dw_loc_list (loc_list, loc, want_address);
+ list_ret = dw_loc_list (loc_list, loc, die, want_address);
have_address = want_address != 0;
break;
}
@@ -14494,18 +14580,18 @@ loc_list_from_tree (tree loc, int want_a
case INDIRECT_REF:
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
have_address = 1;
break;
case COMPOUND_EXPR:
- return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
+ return loc_list_from_tree (TREE_OPERAND (loc, 1), die, want_address);
CASE_CONVERT:
case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
case MODIFY_EXPR:
- return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
+ return loc_list_from_tree (TREE_OPERAND (loc, 0), die, want_address);
case COMPONENT_REF:
case BIT_FIELD_REF:
@@ -14525,7 +14611,7 @@ loc_list_from_tree (tree loc, int want_a
gcc_assert (obj != loc);
- list_ret = loc_list_from_tree (obj,
+ list_ret = loc_list_from_tree (obj, die,
want_address == 2
&& !bitpos && !offset ? 2 : 1);
/* TODO: We can extract value of the small expression via shifting even
@@ -14542,7 +14628,7 @@ loc_list_from_tree (tree loc, int want_a
if (offset != NULL_TREE)
{
/* Variable offset. */
- list_ret1 = loc_list_from_tree (offset, 0);
+ list_ret1 = loc_list_from_tree (offset, die, 0);
if (list_ret1 == 0)
return 0;
add_loc_list (&list_ret, list_ret1);
@@ -14632,8 +14718,8 @@ loc_list_from_tree (tree loc, int want_a
op = DW_OP_mod;
goto do_binop;
}
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
- list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
+ list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), die, 0);
if (list_ret == 0 || list_ret1 == 0)
return 0;
@@ -14664,7 +14750,7 @@ loc_list_from_tree (tree loc, int want_a
if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
&& host_integerp (TREE_OPERAND (loc, 1), 0))
{
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
if (list_ret == 0)
return 0;
@@ -14712,8 +14798,8 @@ loc_list_from_tree (tree loc, int want_a
goto do_binop;
do_binop:
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
- list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
+ list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), die, 0);
if (list_ret == 0 || list_ret1 == 0)
return 0;
@@ -14737,7 +14823,7 @@ loc_list_from_tree (tree loc, int want_a
goto do_unop;
do_unop:
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
if (list_ret == 0)
return 0;
@@ -14761,12 +14847,12 @@ loc_list_from_tree (tree loc, int want_a
case COND_EXPR:
{
dw_loc_descr_ref lhs
- = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+ = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), die, 0);
dw_loc_list_ref rhs
- = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
+ = loc_list_from_tree (TREE_OPERAND (loc, 2), die, 0);
dw_loc_descr_ref bra_node, jump_node, tmp;
- list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), die, 0);
if (list_ret == 0 || lhs == 0 || rhs == 0)
return 0;
@@ -14872,9 +14958,9 @@ loc_list_from_tree (tree loc, int want_a
/* Same as above but return only single location expression. */
static dw_loc_descr_ref
-loc_descriptor_from_tree (tree loc, int want_address)
+loc_descriptor_from_tree (tree loc, dw_die_ref die, int want_address)
{
- dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
+ dw_loc_list_ref ret = loc_list_from_tree (loc, die, want_address);
if (!ret)
return NULL;
if (ret->dw_loc_next)
@@ -15882,7 +15968,7 @@ add_location_or_const_value_attribute (d
&& add_const_value_attribute (die, rtl))
return true;
}
- list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+ list = loc_list_from_tree (decl, die, decl_by_reference_p (decl) ? 0 : 2);
if (list)
{
add_AT_location_description (die, attr, list);
@@ -16355,7 +16441,7 @@ add_bound_info (dw_die_ref subrange_die,
dw_die_ref ctx, decl_die;
dw_loc_list_ref list;
- list = loc_list_from_tree (bound, want_address);
+ list = loc_list_from_tree (bound, subrange_die, want_address);
if (list == NULL)
break;
@@ -16981,7 +17067,7 @@ gen_array_type_die (tree type, dw_die_re
&& DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{
tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
- dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
+ dw_loc_list_ref loc = loc_list_from_tree (szdecl, array_die, 2);
size = int_size_in_bytes (TREE_TYPE (szdecl));
if (loc && size > 0)
@@ -17080,7 +17166,7 @@ descr_info_loc (tree val, tree base_decl
CASE_CONVERT:
return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
case VAR_DECL:
- return loc_descriptor_from_tree (val, 0);
+ return loc_descriptor_from_tree (val, NULL, 0);
case INTEGER_CST:
if (host_integerp (val, 0))
return int_loc_descriptor (tree_low_cst (val, 0));
@@ -17592,6 +17678,7 @@ dwarf2out_abstract_function (tree decl)
tree context;
int was_abstract;
htab_t old_decl_loc_table;
+ struct block_map_struct *old_block_map;
/* Make sure we have the actual abstract inline, not a clone. */
decl = DECL_ORIGIN (decl);
@@ -17606,6 +17693,8 @@ dwarf2out_abstract_function (tree decl)
get locations in abstract instantces. */
old_decl_loc_table = decl_loc_table;
decl_loc_table = NULL;
+ old_block_map = block_map;
+ block_map = NULL;
/* Be sure we've emitted the in-class declaration DIE (if any) first, so
we don't get confused by DECL_ABSTRACT. */
@@ -17630,6 +17719,7 @@ dwarf2out_abstract_function (tree decl)
current_function_decl = save_fn;
decl_loc_table = old_decl_loc_table;
+ block_map = old_block_map;
pop_cfun ();
}
@@ -17947,7 +18037,7 @@ gen_subprogram_die (tree decl, dw_die_re
if (cfun->static_chain_decl)
add_AT_location_description (subr_die, DW_AT_static_link,
- loc_list_from_tree (cfun->static_chain_decl, 2));
+ loc_list_from_tree (cfun->static_chain_decl, NULL, 2));
}
/* Generate child dies for template paramaters. */
@@ -18130,7 +18220,7 @@ gen_variable_die (tree decl, tree origin
{
if (get_AT (var_die, DW_AT_location) == NULL)
{
- loc = loc_list_from_tree (com_decl, off ? 1 : 2);
+ loc = loc_list_from_tree (com_decl, var_die, off ? 1 : 2);
if (loc)
{
if (off)
@@ -18161,7 +18251,7 @@ gen_variable_die (tree decl, tree origin
com_die_arg.decl_id = DECL_UID (com_decl);
com_die_arg.die_parent = context_die;
com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
- loc = loc_list_from_tree (com_decl, 2);
+ loc = loc_list_from_tree (com_decl, NULL, 2);
if (com_die == NULL)
{
const char *cnam
@@ -18175,7 +18265,7 @@ gen_variable_die (tree decl, tree origin
add_AT_location_description (com_die, DW_AT_location, loc);
/* Avoid sharing the same loc descriptor between
DW_TAG_common_block and DW_TAG_variable. */
- loc = loc_list_from_tree (com_decl, 2);
+ loc = loc_list_from_tree (com_decl, NULL, 2);
}
else if (DECL_EXTERNAL (decl))
add_AT_flag (com_die, DW_AT_declaration, 1);
@@ -18187,7 +18277,7 @@ gen_variable_die (tree decl, tree origin
else if (get_AT (com_die, DW_AT_location) == NULL && loc)
{
add_AT_location_description (com_die, DW_AT_location, loc);
- loc = loc_list_from_tree (com_decl, 2);
+ loc = loc_list_from_tree (com_decl, NULL, 2);
remove_AT (com_die, DW_AT_declaration);
}
var_die = new_die (DW_TAG_variable, com_die, decl);
@@ -18446,6 +18536,14 @@ gen_lexical_block_die (tree stmt, dw_die
{
dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+ stmt_die->decl_id = -1;
+ if (block_map)
+ {
+ gcc_assert (BLOCK_NUMBER (stmt) >= lowest_blocknum
+ && BLOCK_NUMBER (stmt) <= highest_blocknum);
+ stmt_die->decl_id = BLOCK_NUMBER (stmt) - lowest_blocknum;
+ block_map[stmt_die->decl_id].die = stmt_die;
+ }
if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
add_high_low_attributes (stmt, stmt_die);
@@ -18476,6 +18574,14 @@ gen_inlined_subroutine_die (tree stmt, d
dw_die_ref subr_die
= new_die (DW_TAG_inlined_subroutine, context_die, stmt);
+ subr_die->decl_id = -1;
+ if (block_map)
+ {
+ gcc_assert (BLOCK_NUMBER (stmt) >= lowest_blocknum
+ && BLOCK_NUMBER (stmt) <= highest_blocknum);
+ subr_die->decl_id = BLOCK_NUMBER (stmt) - lowest_blocknum;
+ block_map[subr_die->decl_id].die = subr_die;
+ }
add_abstract_origin_attribute (subr_die, decl);
if (TREE_ASM_WRITTEN (stmt))
add_high_low_attributes (stmt, subr_die);
@@ -19087,9 +19193,29 @@ gen_block_die (tree stmt, dw_die_ref con
if (BLOCK_FRAGMENT_ORIGIN (stmt))
{
tree sub;
+ dw_die_ref ctx_die = context_die;
+
+ if (block_map && BLOCK_SUBBLOCKS (stmt))
+ {
+ tree block = BLOCK_FRAGMENT_ORIGIN (stmt);
+ while (block != DECL_INITIAL (current_function_decl))
+ {
+ gcc_assert (BLOCK_NUMBER (block) >= lowest_blocknum
+ && BLOCK_NUMBER (block) <= highest_blocknum);
+ if (block_map[BLOCK_NUMBER (block) - lowest_blocknum].die)
+ {
+ ctx_die
+ = block_map[BLOCK_NUMBER (block) - lowest_blocknum].die;
+ break;
+ }
+ block = BLOCK_SUPERCONTEXT (block);
+ if (BLOCK_FRAGMENT_ORIGIN (block))
+ block = BLOCK_FRAGMENT_ORIGIN (block);
+ }
+ }
for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub))
- gen_block_die (sub, context_die, depth + 1);
+ gen_block_die (sub, ctx_die, depth + 1);
return;
}
@@ -19906,25 +20032,91 @@ dwarf2out_decl (tree decl)
gen_decl_die (decl, NULL, context_die);
}
+/* Write the debugging output for function DECL. */
+
+static void
+dwarf2out_function_decl (tree decl)
+{
+ dwarf2out_decl (decl);
+ lowest_blocknum = 0;
+ highest_blocknum = 0;
+ XDELETE (block_map);
+ block_map = NULL;
+ block_evcntr = 0;
+}
+
+/* Update block_evcntr when needed. */
+
+static void
+update_block_evcntr (rtx note)
+{
+ rtx next;
+ static rtx last_note_with_same_counter;
+ if (block_evcntr == 0)
+ {
+ tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (current_function_decl));
+ lowest_blocknum = BLOCK_NUMBER (block);
+ while (1)
+ {
+ while (BLOCK_CHAIN (block))
+ block = BLOCK_CHAIN (block);
+ if (!BLOCK_SUBBLOCKS (block))
+ break;
+ block = BLOCK_SUBBLOCKS (block);
+ }
+ highest_blocknum = BLOCK_NUMBER (block);
+ block_map = XCNEWVEC (struct block_map_struct,
+ highest_blocknum - lowest_blocknum + 1);
+ if (prev_real_insn (note))
+ block_evcntr = 2;
+ last_note_with_same_counter = NULL_RTX;
+ }
+ else if (last_note_with_same_counter)
+ {
+ if (note == last_note_with_same_counter)
+ last_note_with_same_counter = NULL_RTX;
+ return;
+ }
+ else
+ block_evcntr += 2;
+ for (next = NEXT_INSN (note); next; next = NEXT_INSN (next))
+ if (INSN_P (next))
+ break;
+ else if (NOTE_P (next)
+ && (NOTE_KIND (next) == NOTE_INSN_BLOCK_BEG
+ || NOTE_KIND (next) == NOTE_INSN_BLOCK_END))
+ last_note_with_same_counter = next;
+}
+
/* Output a marker (i.e. a label) for the beginning of the generated code for
a lexical block. */
static void
-dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
- unsigned int blocknum)
+dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED, rtx note)
{
+ unsigned int blocknum = BLOCK_NUMBER (NOTE_BLOCK (note));
switch_to_section (current_function_section ());
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
+ update_block_evcntr (note);
+ gcc_assert (blocknum - lowest_blocknum <= highest_blocknum);
+ block_map[blocknum - lowest_blocknum].block = NOTE_BLOCK (note);
+ block_map[blocknum - lowest_blocknum].entry_block_evcntr
+ = block_evcntr;
}
/* Output a marker (i.e. a label) for the end of the generated code for a
lexical block. */
static void
-dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
+dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, rtx note)
{
+ unsigned int blocknum = BLOCK_NUMBER (NOTE_BLOCK (note));
switch_to_section (current_function_section ());
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
+ update_block_evcntr (note);
+ gcc_assert (blocknum - lowest_blocknum <= highest_blocknum);
+ block_map[blocknum - lowest_blocknum].exit_block_evcntr
+ = block_evcntr;
}
/* Returns nonzero if it is appropriate not to emit any debugging
@@ -20255,6 +20447,7 @@ dwarf2out_var_location (rtx loc_note)
static const char *last_label;
static const char *last_postcall_label;
static bool last_in_cold_section_p;
+ static unsigned int last_block_evcntr;
tree decl;
if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
@@ -20277,14 +20470,45 @@ dwarf2out_var_location (rtx loc_note)
|| last_var_location_insn != next_real
|| last_in_cold_section_p != in_cold_section_p)
{
+ rtx prev, next;
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
loclabel_num++;
last_label = ggc_strdup (loclabel);
last_postcall_label = NULL;
+ /* Find out if there are any real insns between LOC_NOTE and
+ last resp. next group of NOTE_INSN_BLOCK_{BEG,END} notes. */
+ for (prev = PREV_INSN (loc_note); prev; prev = PREV_INSN (prev))
+ if (INSN_P (prev))
+ {
+ prev = NULL_RTX;
+ break;
+ }
+ else if (NOTE_P (prev)
+ && (NOTE_KIND (prev) == NOTE_INSN_BLOCK_BEG
+ || NOTE_KIND (prev) == NOTE_INSN_BLOCK_END))
+ break;
+ if (prev)
+ last_block_evcntr = block_evcntr;
+ else
+ {
+ for (next = NEXT_INSN (loc_note); next; next = NEXT_INSN (next))
+ if (INSN_P (next))
+ {
+ next = NULL_RTX;
+ break;
+ }
+ else if (NOTE_P (next)
+ && (NOTE_KIND (next) == NOTE_INSN_BLOCK_BEG
+ || NOTE_KIND (next) == NOTE_INSN_BLOCK_END))
+ break;
+ last_block_evcntr
+ = block_evcntr + 1 + (next != NULL_RTX);
+ }
}
newloc->var_loc_note = loc_note;
newloc->next = NULL;
+ newloc->block_evcntr = last_block_evcntr;
if (!NOTE_DURING_CALL_P (loc_note))
newloc->label = last_label;
@@ -20296,6 +20520,12 @@ dwarf2out_var_location (rtx loc_note)
last_postcall_label = ggc_strdup (loclabel);
}
newloc->label = last_postcall_label;
+ /* last_postcall_label is one real insn byte before
+ current location, so even if LOC_NOTE is on the
+ block begin/end boundary, last_postcall_label is
+ before that boundary. */
+ if ((last_block_evcntr & 1) == 0)
+ newloc->block_evcntr--;
}
if (cfun && in_cold_section_p)
--- gcc/final.c.jj 2010-01-18 17:14:17.000000000 +0100
+++ gcc/final.c 2010-03-19 18:19:45.000000000 +0100
@@ -1928,15 +1928,13 @@ final_scan_insn (rtx insn, FILE *file, i
|| write_symbols == VMS_AND_DWARF2_DEBUG
|| write_symbols == VMS_DEBUG)
{
- int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
-
app_disable ();
++block_depth;
high_block_linenum = last_linenum;
/* Output debugging info about the symbol-block beginning. */
if (!DECL_IGNORED_P (current_function_decl))
- debug_hooks->begin_block (last_linenum, n);
+ debug_hooks->begin_block (last_linenum, insn);
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
@@ -1962,8 +1960,6 @@ final_scan_insn (rtx insn, FILE *file, i
|| write_symbols == VMS_AND_DWARF2_DEBUG
|| write_symbols == VMS_DEBUG)
{
- int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
-
app_disable ();
/* End of a symbol-block. */
@@ -1971,7 +1967,7 @@ final_scan_insn (rtx insn, FILE *file, i
gcc_assert (block_depth >= 0);
if (!DECL_IGNORED_P (current_function_decl))
- debug_hooks->end_block (high_block_linenum, n);
+ debug_hooks->end_block (high_block_linenum, insn);
}
if (write_symbols == DBX_DEBUG
|| write_symbols == SDB_DEBUG)
--- gcc/vmsdbgout.c.jj 2010-01-18 17:14:17.000000000 +0100
+++ gcc/vmsdbgout.c 2010-03-19 18:19:45.000000000 +0100
@@ -173,8 +173,8 @@ static void vmsdbgout_define (unsigned i
static void vmsdbgout_undef (unsigned int, const char *);
static void vmsdbgout_start_source_file (unsigned int, const char *);
static void vmsdbgout_end_source_file (unsigned int);
-static void vmsdbgout_begin_block (unsigned int, unsigned int);
-static void vmsdbgout_end_block (unsigned int, unsigned int);
+static void vmsdbgout_begin_block (unsigned int, rtx);
+static void vmsdbgout_end_block (unsigned int, rtx);
static bool vmsdbgout_ignore_block (const_tree);
static void vmsdbgout_source_line (unsigned int, const char *, int, bool);
static void vmsdbgout_begin_prologue (unsigned int, const char *);
@@ -1347,10 +1347,11 @@ vmsdbgout_end_epilogue (unsigned int lin
a lexical block. */
static void
-vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
+vmsdbgout_begin_block (register unsigned line, rtx note)
{
+ unsigned blocknum = BLOCK_NUMBER (NOTE_BLOCK (note));
if (write_symbols == VMS_AND_DWARF2_DEBUG)
- (*dwarf2_debug_hooks.begin_block) (line, blocknum);
+ (*dwarf2_debug_hooks.begin_block) (line, note);
if (debug_info_level > DINFO_LEVEL_TERSE)
targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
@@ -1360,10 +1361,11 @@ vmsdbgout_begin_block (register unsigned
lexical block. */
static void
-vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
+vmsdbgout_end_block (register unsigned line, rtx note)
{
+ unsigned blocknum = BLOCK_NUMBER (NOTE_BLOCK (note));
if (write_symbols == VMS_AND_DWARF2_DEBUG)
- (*dwarf2_debug_hooks.end_block) (line, blocknum);
+ (*dwarf2_debug_hooks.end_block) (line, note);
if (debug_info_level > DINFO_LEVEL_TERSE)
targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
--- gcc/dbxout.c.jj 2010-01-18 17:14:17.000000000 +0100
+++ gcc/dbxout.c 2010-03-19 18:19:46.000000000 +0100
@@ -338,8 +338,8 @@ static void dbxout_begin_prologue (unsig
static void dbxout_source_file (const char *);
static void dbxout_function_end (tree);
static void dbxout_begin_function (tree);
-static void dbxout_begin_block (unsigned, unsigned);
-static void dbxout_end_block (unsigned, unsigned);
+static void dbxout_begin_block (unsigned, rtx);
+static void dbxout_end_block (unsigned, rtx);
static void dbxout_function_decl (tree);
const struct gcc_debug_hooks dbx_debug_hooks =
@@ -1311,8 +1311,9 @@ dbxout_source_line (unsigned int lineno,
/* Describe the beginning of an internal block within a function. */
static void
-dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
+dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, rtx note)
{
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
emit_pending_bincls_if_required ();
targetm.asm_out.internal_label (asm_out_file, "LBB", n);
}
@@ -1320,8 +1321,9 @@ dbxout_begin_block (unsigned int line AT
/* Describe the end line-number of an internal block within a function. */
static void
-dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
+dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, rtx note)
{
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
emit_pending_bincls_if_required ();
targetm.asm_out.internal_label (asm_out_file, "LBE", n);
}
--- gcc/xcoffout.h.jj 2009-06-18 21:20:31.000000000 +0200
+++ gcc/xcoffout.h 2010-03-19 18:19:46.000000000 +0100
@@ -176,10 +176,10 @@ do { \
extern int stab_to_sclass (int);
extern void xcoffout_begin_prologue (unsigned int, const char *);
-extern void xcoffout_begin_block (unsigned, unsigned);
+extern void xcoffout_begin_block (unsigned, rtx);
extern void xcoffout_end_epilogue (unsigned int, const char *);
extern void xcoffout_end_function (unsigned int);
-extern void xcoffout_end_block (unsigned, unsigned);
+extern void xcoffout_end_block (unsigned, rtx);
extern int xcoff_assign_fundamental_type_number (tree);
extern void xcoffout_declare_function (FILE *, tree, const char *);
extern void xcoffout_source_line (unsigned int, const char *, int, bool);
--- gcc/xcoffout.c.jj 2010-01-18 17:14:17.000000000 +0100
+++ gcc/xcoffout.c 2010-03-19 18:19:46.000000000 +0100
@@ -380,9 +380,10 @@ xcoffout_block (tree block, int depth, t
if the count starts at 0 for the outermost one. */
void
-xcoffout_begin_block (unsigned int line, unsigned int n)
+xcoffout_begin_block (unsigned int line, rtx note)
{
tree decl = current_function_decl;
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
/* The IBM AIX compiler does not emit a .bb for the function level scope,
so we avoid it here also. */
@@ -396,8 +397,9 @@ xcoffout_begin_block (unsigned int line,
/* Describe the end line-number of an internal block within a function. */
void
-xcoffout_end_block (unsigned int line, unsigned int n)
+xcoffout_end_block (unsigned int line, rtx note)
{
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
if (n != 1)
ASM_OUTPUT_LBE (asm_out_file, line, n);
}
--- gcc/sdbout.c.jj 2010-01-18 17:14:17.000000000 +0100
+++ gcc/sdbout.c 2010-03-19 18:19:47.000000000 +0100
@@ -115,8 +115,8 @@ static void sdbout_init (const char *)
static void sdbout_finish (const char *);
static void sdbout_start_source_file (unsigned int, const char *);
static void sdbout_end_source_file (unsigned int);
-static void sdbout_begin_block (unsigned int, unsigned int);
-static void sdbout_end_block (unsigned int, unsigned int);
+static void sdbout_begin_block (unsigned int, rtx);
+static void sdbout_end_block (unsigned int, rtx);
static void sdbout_source_line (unsigned int, const char *, int, bool);
static void sdbout_end_epilogue (unsigned int, const char *);
static void sdbout_global_decl (tree);
@@ -1494,9 +1494,10 @@ sdbout_finish (const char *main_filename
if the count starts at 0 for the outermost one. */
static void
-sdbout_begin_block (unsigned int line, unsigned int n)
+sdbout_begin_block (unsigned int line, rtx note)
{
tree decl = current_function_decl;
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
MAKE_LINE_SAFE (line);
/* The SCO compiler does not emit a separate block for the function level
@@ -1529,8 +1530,11 @@ sdbout_begin_block (unsigned int line, u
/* Describe the end line-number of an internal block within a function. */
static void
-sdbout_end_block (unsigned int line, unsigned int n ATTRIBUTE_UNUSED)
+sdbout_end_block (unsigned int line, rtx note ATTRIBUTE_UNUSED)
{
+#ifndef MIPS_DEBUGGING_INFO
+ unsigned int n = BLOCK_NUMBER (NOTE_BLOCK (note));
+#endif
MAKE_LINE_SAFE (line);
/* The SCO compiler does not emit a separate block for the function level
--- gcc/function.c.jj 2010-02-26 16:58:08.000000000 +0100
+++ gcc/function.c 2010-03-21 17:41:29.000000000 +0100
@@ -3808,6 +3808,46 @@ 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). */
+
+static tree
+block_fragments_nreverse (tree t)
+{
+ tree prev = 0, decl, next;
+ for (decl = t; decl; decl = next)
+ {
+ next = BLOCK_FRAGMENT_CHAIN (decl);
+ BLOCK_FRAGMENT_CHAIN (decl) = prev;
+ prev = decl;
+ }
+ return prev;
+}
+
+/* Reverse the order of elements in the chain T of blocks,
+ and return the new head of the chain (old last element).
+ Also do the same on subblocks and reverse the order of elements
+ in BLOCK_FRAGMENT_CHAIN as well. */
+
+static tree
+blocks_nreverse_all (tree t)
+{
+ tree prev = 0, decl, next;
+ for (decl = t; decl; decl = next)
+ {
+ next = BLOCK_CHAIN (decl);
+ BLOCK_CHAIN (decl) = prev;
+ BLOCK_SUBBLOCKS (decl) = blocks_nreverse_all (BLOCK_SUBBLOCKS (decl));
+ if (BLOCK_FRAGMENT_CHAIN (decl)
+ && BLOCK_FRAGMENT_ORIGIN (decl) == NULL_TREE)
+ BLOCK_FRAGMENT_CHAIN (decl)
+ = block_fragments_nreverse (BLOCK_FRAGMENT_CHAIN (decl));
+ prev = decl;
+ }
+ return prev;
+}
+
+
/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
and create duplicate blocks. */
/* ??? Need an option to either create block fragments or to create
@@ -3834,7 +3874,7 @@ reorder_blocks (void)
/* Recreate the block tree from the note nesting. */
reorder_blocks_1 (get_insns (), block, &block_stack);
- BLOCK_SUBBLOCKS (block) = blocks_nreverse (BLOCK_SUBBLOCKS (block));
+ BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block));
VEC_free (tree, heap, block_stack);
}
@@ -3866,9 +3906,8 @@ reorder_blocks_1 (rtx insns, tree curren
tree block = NOTE_BLOCK (insn);
tree origin;
- origin = (BLOCK_FRAGMENT_ORIGIN (block)
- ? BLOCK_FRAGMENT_ORIGIN (block)
- : block);
+ gcc_assert (BLOCK_FRAGMENT_ORIGIN (block) == NULL_TREE);
+ origin = block;
/* If we have seen this block before, that means it now
spans multiple address regions. Create a new fragment. */
@@ -3905,8 +3944,6 @@ reorder_blocks_1 (rtx insns, tree curren
else if (NOTE_KIND (insn) == NOTE_INSN_BLOCK_END)
{
NOTE_BLOCK (insn) = VEC_pop (tree, *p_block_stack);
- BLOCK_SUBBLOCKS (current_block)
- = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
current_block = BLOCK_SUPERCONTEXT (current_block);
}
}
-------------- next part --------------
Examples of the ~ 3500 DIEs that lost DW_AT_location attribute:
<2><1c2d0>: Abbrev Number: 73 (DW_TAG_lexical_block)
<1c2d1> DW_AT_ranges : 0x200
<1c2d5> DW_AT_sibling : <0x1c300>
<3><1c2d9>: Abbrev Number: 69 (DW_TAG_variable)
<1c2da> DW_AT_name : __t
<1c2de> DW_AT_decl_file : 1
<1c2df> DW_AT_decl_line : 4549
<1c2e1> DW_AT_type : <0x1b753>
<1c2e5> DW_AT_location : 0x14fc (location list) <- Dropped with the patch
00000200 080bdf29 080bdf38
00000200 080bdf97 080bdfcf
00000200 <End of list>
000014fc 080bdf38 080bdf3e (DW_OP_breg3: 12; DW_OP_deref; DW_OP_plus_uconst: 16)
000014fc 080bdf3e 080bdf53 (DW_OP_reg0)
000014fc 080bdf8f 080bdf95 (DW_OP_reg0)
000014fc <End of list>
<6><138f043>: Abbrev Number: 38 (DW_TAG_lexical_block)
<138f044> DW_AT_ranges : 0x3c0880
<7><138f048>: Abbrev Number: 46 (DW_TAG_variable)
<138f049> DW_AT_abstract_origin: <0x138e4ec>
<138f04d> DW_AT_location : 0xf60994 (location list) <- Dropped with the patch
<7><138f051>: Abbrev Number: 46 (DW_TAG_variable)
<138f052> DW_AT_abstract_origin: <0x138e4f6>
<138f056> DW_AT_location : 0xf609c1 (location list) <- Dropped with the patch
<7><138f05a>: Abbrev Number: 46 (DW_TAG_variable)
<138f05b> DW_AT_abstract_origin: <0x138e500>
<138f05f> DW_AT_location : 0xf60a00 (location list) <- Dropped with the patch
<7><138f063>: Abbrev Number: 46 (DW_TAG_variable)
<138f064> DW_AT_abstract_origin: <0x138e50a>
<138f068> DW_AT_location : 0xf60a13 (location list) <- Dropped with the patch
003c0880 08dfb422 08dfb433
003c0880 08dfb437 08dfb43f
003c0880 <End of list>
00f60994 08dfb43f 08dfb454 (DW_OP_reg2)
00f60994 08dfb454 08dfb4c1 (DW_OP_fbreg: -68)
00f60994 08dfb516 08dfb52b (DW_OP_fbreg: -68)
00f60994 <End of list>
00f609c1 08dfb43f 08dfb454 (DW_OP_fbreg: 8; DW_OP_deref; DW_OP_breg2: 0; DW_OP_minus; DW_OP_stack_value)
00f609c1 08dfb454 08dfb4c1 (DW_OP_fbreg: 8; DW_OP_deref; DW_OP_fbreg: -68; DW_OP_deref; DW_OP_minus; DW_OP_stack_value)
00f609c1 08dfb516 08dfb52b (DW_OP_fbreg: 8; DW_OP_deref; DW_OP_fbreg: -68; DW_OP_deref; DW_OP_minus; DW_OP_stack_value)
00f609c1 <End of list>
00f60a00 08dfb44e 08dfb450 (DW_OP_reg0)
00f60a00 <End of list>
00f60a13 08dfb450 08dfb456 (DW_OP_reg0)
00f60a13 <End of list>
<2><61e21b>: Abbrev Number: 70 (DW_TAG_inlined_subroutine)
<61e21c> DW_AT_abstract_origin: <0x61d6cb>
<61e220> DW_AT_entry_pc : 0x84cd660
<61e224> DW_AT_ranges : 0x15bd68
<61e228> DW_AT_call_file : 1
<61e229> DW_AT_call_line : 181
<61e22a> DW_AT_sibling : <0x61e263>
<3><61e22e>: Abbrev Number: 71 (DW_TAG_formal_parameter)
<61e22f> DW_AT_abstract_origin: <0x61d6e1>
<61e233> DW_AT_location : 0x4c79b8 (location list) <- Dropped with the patch
<3><61e237>: Abbrev Number: 71 (DW_TAG_formal_parameter)
<61e238> DW_AT_abstract_origin: <0x61d6d8>
<61e23c> DW_AT_location : 0x4c79c0 (location list) <- Dropped with the patch
0015bd68 084cd660 084cd666
0015bd68 084cd66c 084cd66e
0015bd68 084cd674 084cd678
0015bd68 <End of list>
004c79b8 <End of list>
004c79c0 <End of list>
<3><46cb4>: Abbrev Number: 82 (DW_TAG_lexical_block)
<46cb5> DW_AT_ranges : 0x147f8
<46cb9> DW_AT_sibling : <0x46cf9>
<4><46cbd>: Abbrev Number: 79 (DW_TAG_variable)
<46cbe> DW_AT_name : lt
<46cc1> DW_AT_decl_file : 1
<46cc2> DW_AT_decl_line : 8754
<46cc4> DW_AT_type : <0x2c2de>
<46cc8> DW_AT_location : 0x46f1e (location list) <- Dropped with the patch
000147f8 080fc588 080fc595
000147f8 080fd6d6 080fd716
000147f8 <End of list>
00046f1e 080fc595 080fc5ad (DW_OP_reg0)
00046f1e 080fdb16 080fdb45 (DW_OP_breg5: 92)
00046f1e 080ff076 080ff09d (DW_OP_breg5: 92)
00046f1e 080ff09e 080ff0cd (DW_OP_reg0)
00046f1e <End of list>
<2><7f89e7>: Abbrev Number: 68 (DW_TAG_lexical_block)
<7f89e8> DW_AT_low_pc : 0x85ae0cf
<7f89ec> DW_AT_high_pc : 0x85ae107
<3><7f89f0>: Abbrev Number: 79 (DW_TAG_variable)
<7f89f1> DW_AT_name : (indirect string, offset: 0x71bba): spec_val
<7f89f5> DW_AT_decl_file : 2
<7f89f6> DW_AT_decl_line : 2281
<7f89f8> DW_AT_type : <0x7ecd76>
<7f89fc> DW_AT_location : 0x5c8b55 (location list)
<3><7f8a00>: Abbrev Number: 79 (DW_TAG_variable)
<7f8a01> DW_AT_name : (indirect string, offset: 0xd1b2f): prob_val
<7f8a05> DW_AT_decl_file : 2
<7f8a06> DW_AT_decl_line : 2281
<7f8a08> DW_AT_type : <0x7ecd76>
<7f8a0c> DW_AT_location : 0x5c8b78 (location list) <- Dropped with the patch
005c8b55 085ae0fd 085ae0ff (DW_OP_breg0: 0; DW_OP_breg2: 0; DW_OP_minus; DW_OP_stack_value)
005c8b55 085ae0ff 085ae104 (DW_OP_reg0)
005c8b55 <End of list>
005c8b78 <End of list>
Examples of shorter location lists:
<2><9b7f>: Abbrev Number: 56 (DW_TAG_lexical_block)
<9b80> DW_AT_ranges : 0x38
<9b84> DW_AT_sibling : <0x9b98>
<3><9b88>: Abbrev Number: 53 (DW_TAG_variable)
<9b89> DW_AT_name : __t
<9b8d> DW_AT_decl_file : 1
<9b8e> DW_AT_decl_line : 140
<9b8f> DW_AT_type : <0x9b34>
<9b93> DW_AT_location : 0x13e (location list)
00000038 080bcd38 080bcd48
00000038 080bcdf0 080bce18
00000038 <End of list>
0000013e 080bcd38 080bcdd4 (DW_OP_fbreg: 0)
0000013e 080bcdf0 080bce48 (DW_OP_fbreg: 0)
0000013e <End of list>
change:
- XXXXXXXX 080bcd38 080bcdd4 (DW_OP_fbreg: 0)
- XXXXXXXX 080bcdf0 080bce48 (DW_OP_fbreg: 0)
+ XXXXXXXX 080bcd38 080bce48 (DW_OP_fbreg: 0)
XXXXXXXX <End of list>
<2><1c9dd>: Abbrev Number: 73 (DW_TAG_lexical_block)
<1c9de> DW_AT_ranges : 0x5a8
<1c9e2> DW_AT_sibling : <0x1c9f7>
<3><1c9e6>: Abbrev Number: 69 (DW_TAG_variable)
<1c9e7> DW_AT_name : __t
<1c9eb> DW_AT_decl_file : 1
<1c9ec> DW_AT_decl_line : 357
<1c9ee> DW_AT_type : <0x1b753>
<1c9f2> DW_AT_location : 0x2173 (location list)
000005a8 080be8cb 080be8cf
000005a8 080be8d3 080be8df
000005a8 080bed69 080bed99
000005a8 <End of list>
00002173 080be8d3 080be8ee (DW_OP_reg5)
00002173 080bea3a 080bea4a (DW_OP_reg5)
00002173 080bed69 080bed99 (DW_OP_reg5)
00002173 <End of list>
change:
- XXXXXXXX 080be8d3 080be8ee (DW_OP_reg5)
- XXXXXXXX 080bea3a 080bea4a (DW_OP_reg5)
- XXXXXXXX 080bed69 080bed99 (DW_OP_reg5)
+ XXXXXXXX 080be8d3 080bee8d (DW_OP_reg5)
XXXXXXXX <End of list>
<3><1d653>: Abbrev Number: 73 (DW_TAG_lexical_block)
<1d654> DW_AT_ranges : 0xbc8
<1d658> DW_AT_sibling : <0x1d683>
<4><1d65c>: Abbrev Number: 69 (DW_TAG_variable)
<1d65d> DW_AT_name : __t
<1d661> DW_AT_decl_file : 1
<1d662> DW_AT_decl_line : 4702
<1d664> DW_AT_type : <0x1b753>
<1d668> DW_AT_location : 0x3cb2 (location list)
00000bc8 080c0143 080c0161
00000bc8 080c062e 080c0656
00000bc8 080c07ef 080c081f
00000bc8 <End of list>
00003cb2 080c0157 080c0164 (DW_OP_reg0)
00003cb2 080c01b7 080c020c (DW_OP_breg3: 24)
00003cb2 080c02d8 080c02e2 (DW_OP_breg3: 24)
00003cb2 080c04e7 080c050a (DW_OP_breg3: 24)
00003cb2 080c050b 080c053a (DW_OP_breg3: 24)
00003cb2 080c053b 080c0562 (DW_OP_breg3: 24)
00003cb2 080c059b 080c05ca (DW_OP_breg3: 24)
00003cb2 080c07ef 080c081f (DW_OP_reg0)
00003cb2 <End of list>
change:
- XXXXXXXX 080c0157 080c0164 (DW_OP_reg0)
- XXXXXXXX 080c01b7 080c020c (DW_OP_breg3: 24)
- XXXXXXXX 080c02d8 080c02e2 (DW_OP_breg3: 24)
- XXXXXXXX 080c04e7 080c050a (DW_OP_breg3: 24)
- XXXXXXXX 080c050b 080c053a (DW_OP_breg3: 24)
- XXXXXXXX 080c053b 080c0562 (DW_OP_breg3: 24)
- XXXXXXXX 080c059b 080c05ca (DW_OP_breg3: 24)
+ XXXXXXXX 080c0157 080c05ca (DW_OP_reg0)
XXXXXXXX 080c07ef 080c081f (DW_OP_reg0)
XXXXXXXX <End of list>
More information about the Gcc-patches
mailing list