summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-07 14:48:39 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-07 14:48:39 +0000
commit67a3424104feee6bd9d60ab2c85ab17819090dd0 (patch)
treea4ce57d3fa3394419c28e38309ee4f749ee5cf2f /gcc/dwarf2out.c
parent9d8eb68081f898e225727d69da8212813f27e199 (diff)
downloadgcc-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.c103
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