diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-07 14:48:39 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-07 14:48:39 +0000 |
commit | 67a3424104feee6bd9d60ab2c85ab17819090dd0 (patch) | |
tree | a4ce57d3fa3394419c28e38309ee4f749ee5cf2f /gcc/dwarf2out.c | |
parent | 9d8eb68081f898e225727d69da8212813f27e199 (diff) | |
download | gcc-67a3424104feee6bd9d60ab2c85ab17819090dd0.tar.gz |
PR debug/56154
* dwarf2out.c (dwarf2_debug_hooks): Set end_function hook to
dwarf2out_end_function.
(in_first_function_p, maybe_at_text_label_p,
first_loclabel_num_not_at_text_label): New variables.
(dwarf2out_var_location): In the first function find out
lowest loclabel_num N where .LVLN is known not to be equal
to .Ltext0.
(find_empty_loc_ranges_at_text_label, dwarf2out_end_function): New
functions.
* gcc.dg/guality/pr56154-1.c: New test.
* gcc.dg/guality/pr56154-2.c: New test.
* gcc.dg/guality/pr56154-3.c: New test.
* gcc.dg/guality/pr56154-4.c: New test.
* gcc.dg/guality/pr56154-aux.c: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@195850 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 103 |
1 files changed, 102 insertions, 1 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 06cfb18a0ce..13c31ad005f 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2351,6 +2351,7 @@ static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx); static void dwarf2out_begin_function (tree); +static void dwarf2out_end_function (unsigned int); static void dwarf2out_set_name (tree, tree); /* The debug hooks structure. */ @@ -2378,7 +2379,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = #endif dwarf2out_end_epilogue, dwarf2out_begin_function, - debug_nothing_int, /* end_function */ + dwarf2out_end_function, /* end_function */ dwarf2out_function_decl, /* function_decl */ dwarf2out_global_decl, dwarf2out_type_decl, /* type_decl */ @@ -20627,6 +20628,14 @@ dwarf2out_set_name (tree decl, tree name) add_name_attribute (die, dname); } +/* True if before or during processing of the first function being emitted. */ +static bool in_first_function_p = true; +/* True if loc_note during dwarf2out_var_location call might still be + before first real instruction at address equal to .Ltext0. */ +static bool maybe_at_text_label_p = true; +/* One above highest N where .LVLN label might be equal to .Ltext0 label. */ +static unsigned int first_loclabel_num_not_at_text_label; + /* Called by the final INSN scan whenever we see a var location. We use it to drop labels in the right places, and throw the location in our lookup table. */ @@ -20734,6 +20743,45 @@ dwarf2out_var_location (rtx loc_note) ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num); loclabel_num++; last_label = ggc_strdup (loclabel); + /* See if loclabel might be equal to .Ltext0. If yes, + bump first_loclabel_num_not_at_text_label. */ + if (!have_multiple_function_sections + && in_first_function_p + && maybe_at_text_label_p) + { + static rtx last_start; + rtx insn; + for (insn = loc_note; insn; insn = previous_insn (insn)) + if (insn == last_start) + break; + else if (!NONDEBUG_INSN_P (insn)) + continue; + else + { + rtx body = PATTERN (insn); + if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) + continue; + /* Inline asm could occupy zero bytes. */ + else if (GET_CODE (body) == ASM_INPUT + || asm_noperands (body) >= 0) + continue; +#ifdef HAVE_attr_length + else if (get_attr_min_length (insn) == 0) + continue; +#endif + else + { + /* Assume insn has non-zero length. */ + maybe_at_text_label_p = false; + break; + } + } + if (maybe_at_text_label_p) + { + last_start = loc_note; + first_loclabel_num_not_at_text_label = loclabel_num; + } + } } if (!var_loc_p) @@ -20903,6 +20951,59 @@ dwarf2out_begin_function (tree fun) set_cur_line_info_table (sec); } +/* Helper function of dwarf2out_end_function, called only after emitting + the very first function into assembly. Check if some .debug_loc range + might end with a .LVL* label that could be equal to .Ltext0. + In that case we must force using absolute addresses in .debug_loc ranges, + because this range could be .LVLN-.Ltext0 .. .LVLM-.Ltext0 for + .LVLN == .LVLM == .Ltext0, thus 0 .. 0, which is a .debug_loc + list terminator. + Set have_multiple_function_sections to true in that case and + terminate htab traversal. */ + +static int +find_empty_loc_ranges_at_text_label (void **slot, void *) +{ + var_loc_list *entry; + struct var_loc_node *node; + + entry = (var_loc_list *) *slot; + node = entry->first; + if (node && node->next && node->next->label) + { + unsigned int i; + const char *label = node->next->label; + char loclabel[MAX_ARTIFICIAL_LABEL_BYTES]; + + for (i = 0; i < first_loclabel_num_not_at_text_label; i++) + { + ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", i); + if (strcmp (label, loclabel) == 0) + { + have_multiple_function_sections = true; + return 0; + } + } + } + return 1; +} + +/* Hook called after emitting a function into assembly. + This does something only for the very first function emitted. */ + +static void +dwarf2out_end_function (unsigned int) +{ + if (in_first_function_p + && !have_multiple_function_sections + && first_loclabel_num_not_at_text_label + && decl_loc_table) + htab_traverse (decl_loc_table, find_empty_loc_ranges_at_text_label, + NULL); + in_first_function_p = false; + maybe_at_text_label_p = false; +} + /* Add OPCODE+VAL as an entry at the end of the opcode array in TABLE. */ static void |