319 lines
8.4 KiB
Diff
319 lines
8.4 KiB
Diff
2013-01-30 Jakub Jelinek <jakub@redhat.com>
|
|
|
|
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.
|
|
|
|
--- gcc/dwarf2out.c.jj 2013-01-11 09:02:48.000000000 +0100
|
|
+++ gcc/dwarf2out.c 2013-01-30 16:18:58.362552894 +0100
|
|
@@ -2351,6 +2351,7 @@ static void dwarf2out_imported_module_or
|
|
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_debu
|
|
#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
|
|
--- gcc/testsuite/gcc.dg/guality/pr56154-1.c.jj 2013-01-30 17:14:20.850820429 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr56154-1.c 2013-01-30 17:47:25.242537776 +0100
|
|
@@ -0,0 +1,29 @@
|
|
+/* PR debug/56154 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-g" } */
|
|
+/* { dg-additional-sources "pr56154-aux.c" } */
|
|
+
|
|
+#include "../nop.h"
|
|
+
|
|
+union U { int a, b; };
|
|
+volatile int z;
|
|
+
|
|
+__attribute__((noinline, noclone)) int
|
|
+foo (int fd, union U x)
|
|
+{
|
|
+ int result = x.a != 0;
|
|
+ if (fd != 0)
|
|
+ result = x.a == 0;
|
|
+ asm (NOP : : : "memory"); /* { dg-final { gdb-test pr56154-1.c:17 "x.a" "4" } } */
|
|
+ z = x.a;
|
|
+ x.a = 6;
|
|
+ asm (NOP : : : "memory"); /* { dg-final { gdb-test pr56154-1.c:20 "x.a" "6" } } */
|
|
+ return result;
|
|
+}
|
|
+
|
|
+void
|
|
+test_main (void)
|
|
+{
|
|
+ union U u = { .a = 4 };
|
|
+ foo (0, u);
|
|
+}
|
|
--- gcc/testsuite/gcc.dg/guality/pr56154-2.c.jj 2013-01-30 17:58:28.229799607 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr56154-2.c 2013-01-30 18:06:38.306982101 +0100
|
|
@@ -0,0 +1,39 @@
|
|
+/* PR debug/56154 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-g" } */
|
|
+/* { dg-additional-sources "pr56154-aux.c" } */
|
|
+
|
|
+#include "../nop.h"
|
|
+
|
|
+extern void abort (void);
|
|
+
|
|
+__attribute__((noinline, noclone)) int
|
|
+foo (int x)
|
|
+{
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm ("");
|
|
+ x++;
|
|
+ asm (NOP : : : "memory");
|
|
+ asm (NOP : : : "memory"); /* { dg-final { gdb-test pr56154-2.c:30 "x" "28" } } */
|
|
+ return x;
|
|
+}
|
|
+
|
|
+void
|
|
+test_main (void)
|
|
+{
|
|
+ if (foo (20) != 28)
|
|
+ abort ();
|
|
+}
|
|
--- gcc/testsuite/gcc.dg/guality/pr56154-3.c.jj 2013-01-30 18:04:47.531604188 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr56154-3.c 2013-01-30 18:06:25.031055514 +0100
|
|
@@ -0,0 +1,31 @@
|
|
+/* PR debug/56154 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-g" } */
|
|
+/* { dg-additional-sources "pr56154-aux.c" } */
|
|
+
|
|
+#include "../nop.h"
|
|
+
|
|
+extern void abort (void);
|
|
+
|
|
+__attribute__((noinline, noclone)) int
|
|
+foo (int x)
|
|
+{
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ asm (NOP : : : "memory");
|
|
+ asm (NOP : : : "memory"); /* { dg-final { gdb-test pr56154-3.c:22 "x" "28" } } */
|
|
+ return x;
|
|
+}
|
|
+
|
|
+void
|
|
+test_main (void)
|
|
+{
|
|
+ if (foo (20) != 28)
|
|
+ abort ();
|
|
+}
|
|
--- gcc/testsuite/gcc.dg/guality/pr56154-4.c.jj 2013-01-30 18:05:45.959280837 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr56154-4.c 2013-01-30 18:07:50.457602221 +0100
|
|
@@ -0,0 +1,34 @@
|
|
+/* PR debug/56154 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-g" } */
|
|
+/* { dg-additional-sources "pr56154-aux.c" } */
|
|
+
|
|
+#include "../nop.h"
|
|
+
|
|
+extern void abort (void);
|
|
+
|
|
+volatile int z;
|
|
+
|
|
+__attribute__((noinline, noclone)) int
|
|
+foo (int x)
|
|
+{
|
|
+ z = 6;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ x++;
|
|
+ asm (NOP : : : "memory");
|
|
+ asm (NOP : : : "memory"); /* { dg-final { gdb-test pr56154-4.c:25 "x" "28" } } */
|
|
+ return x;
|
|
+}
|
|
+
|
|
+void
|
|
+test_main (void)
|
|
+{
|
|
+ if (foo (20) != 28)
|
|
+ abort ();
|
|
+}
|
|
--- gcc/testsuite/gcc.dg/guality/pr56154-aux.c.jj 2013-01-30 17:47:08.467632262 +0100
|
|
+++ gcc/testsuite/gcc.dg/guality/pr56154-aux.c 2013-01-30 17:14:28.000000000 +0100
|
|
@@ -0,0 +1,11 @@
|
|
+/* PR debug/56154 */
|
|
+/* { dg-do compile } */
|
|
+
|
|
+extern void test_main (void);
|
|
+
|
|
+int
|
|
+main ()
|
|
+{
|
|
+ test_main ();
|
|
+ return 0;
|
|
+}
|