aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-11-21 08:59:03 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-11-21 08:59:03 +0100
commit8b87e0d12576318e2ae02284e767b4d083cc4149 (patch)
treecb8105420b51b50135fc21ae493584d22fba72ab
parent83087d6521689c6200065537640b953972fbd76b (diff)
downloadgcc-8b87e0d12576318e2ae02284e767b4d083cc4149.zip
gcc-8b87e0d12576318e2ae02284e767b4d083cc4149.tar.gz
gcc-8b87e0d12576318e2ae02284e767b4d083cc4149.tar.bz2
re PR debug/82718 (Bad DWARF5 .debug_loclists generation)
PR debug/82718 * dwarf2out.c (dw_loc_list): If crtl->has_bb_partition, temporarily set in_cold_section_p to the partition containing loc_list->first. When seeing loc_list->last_before_switch node, update secname and perform range_across_switch second partition handling only after that. * gcc.dg/debug/dwarf2/pr82718-1.c: New test. * gcc.dg/debug/dwarf2/pr82718-2.c: New test. From-SVN: r254989
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/dwarf2out.c183
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c12
5 files changed, 164 insertions, 82 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1c3aaed..207e6f3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2017-11-21 Jakub Jelinek <jakub@redhat.com>
+ PR debug/82718
+ * dwarf2out.c (dw_loc_list): If crtl->has_bb_partition, temporarily
+ set in_cold_section_p to the partition containing loc_list->first.
+ When seeing loc_list->last_before_switch node, update secname and
+ perform range_across_switch second partition handling only after that.
+
PR debug/82933
* run-rtl-passes.c: Include debug.h.
(run_rtl_passes): Call debug_hooks->assembly_start.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7fd6ae3..89e119c 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -16366,92 +16366,111 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
This means we have to special case the last node, and generate
a range of [last location start, end of function label]. */
- secname = secname_for_decl (decl);
+ if (cfun && crtl->has_bb_partition)
+ {
+ bool save_in_cold_section_p = in_cold_section_p;
+ in_cold_section_p = first_function_block_is_cold;
+ if (loc_list->last_before_switch == NULL)
+ in_cold_section_p = !in_cold_section_p;
+ secname = secname_for_decl (decl);
+ in_cold_section_p = save_in_cold_section_p;
+ }
+ else
+ secname = secname_for_decl (decl);
for (node = loc_list->first; node; node = node->next)
- if (GET_CODE (node->loc) == EXPR_LIST
- || NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
- {
- if (GET_CODE (node->loc) == EXPR_LIST)
- {
- /* This requires DW_OP_{,bit_}piece, which is not usable
- inside DWARF expressions. */
- if (want_address != 2)
- continue;
- descr = dw_sra_loc_expr (decl, node->loc);
- if (descr == NULL)
- continue;
- }
- else
- {
- initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
- varloc = NOTE_VAR_LOCATION (node->loc);
- descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
- }
- if (descr)
- {
- bool range_across_switch = false;
- /* If section switch happens in between node->label
- and node->next->label (or end of function) and
- we can't emit it as a single entry list,
- emit two ranges, first one ending at the end
- of first partition and second one starting at the
- beginning of second partition. */
- if (node == loc_list->last_before_switch
- && (node != loc_list->first || loc_list->first->next)
- && current_function_decl)
- {
- endname = cfun->fde->dw_fde_end;
- range_across_switch = true;
- }
- /* The variable has a location between NODE->LABEL and
- NODE->NEXT->LABEL. */
- else if (node->next)
- endname = node->next->label;
- /* If the variable has a location at the last label
- it keeps its location until the end of function. */
- 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);
- }
+ {
+ bool range_across_switch = false;
+ if (GET_CODE (node->loc) == EXPR_LIST
+ || NOTE_VAR_LOCATION_LOC (node->loc) != NULL_RTX)
+ {
+ if (GET_CODE (node->loc) == EXPR_LIST)
+ {
+ descr = NULL;
+ /* This requires DW_OP_{,bit_}piece, which is not usable
+ inside DWARF expressions. */
+ if (want_address == 2)
+ descr = dw_sra_loc_expr (decl, node->loc);
+ }
+ else
+ {
+ initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
+ varloc = NOTE_VAR_LOCATION (node->loc);
+ descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
+ }
+ if (descr)
+ {
+ /* If section switch happens in between node->label
+ and node->next->label (or end of function) and
+ we can't emit it as a single entry list,
+ emit two ranges, first one ending at the end
+ of first partition and second one starting at the
+ beginning of second partition. */
+ if (node == loc_list->last_before_switch
+ && (node != loc_list->first || loc_list->first->next)
+ && current_function_decl)
+ {
+ endname = cfun->fde->dw_fde_end;
+ range_across_switch = true;
+ }
+ /* The variable has a location between NODE->LABEL and
+ NODE->NEXT->LABEL. */
+ else if (node->next)
+ endname = node->next->label;
+ /* If the variable has a location at the last label
+ it keeps its location until the end of function. */
+ 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);
- if (TREE_CODE (decl) == PARM_DECL
- && node == loc_list->first
- && NOTE_P (node->loc)
- && strcmp (node->label, endname) == 0)
- (*listp)->force = true;
- listp = &(*listp)->dw_loc_next;
+ *listp = new_loc_list (descr, node->label, endname, secname);
+ if (TREE_CODE (decl) == PARM_DECL
+ && node == loc_list->first
+ && NOTE_P (node->loc)
+ && strcmp (node->label, endname) == 0)
+ (*listp)->force = true;
+ listp = &(*listp)->dw_loc_next;
+ }
+ }
- if (range_across_switch)
- {
- if (GET_CODE (node->loc) == EXPR_LIST)
- descr = dw_sra_loc_expr (decl, node->loc);
- else
- {
- initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
- varloc = NOTE_VAR_LOCATION (node->loc);
- descr = dw_loc_list_1 (decl, varloc, want_address,
- initialized);
- }
- gcc_assert (descr);
- /* The variable has a location between NODE->LABEL and
- NODE->NEXT->LABEL. */
- if (node->next)
- endname = node->next->label;
- else
- endname = cfun->fde->dw_fde_second_end;
- *listp = new_loc_list (descr,
- cfun->fde->dw_fde_second_begin,
- endname, secname);
- listp = &(*listp)->dw_loc_next;
- }
- }
- }
+ if (cfun
+ && crtl->has_bb_partition
+ && node == loc_list->last_before_switch)
+ {
+ bool save_in_cold_section_p = in_cold_section_p;
+ in_cold_section_p = !first_function_block_is_cold;
+ secname = secname_for_decl (decl);
+ in_cold_section_p = save_in_cold_section_p;
+ }
+
+ if (range_across_switch)
+ {
+ if (GET_CODE (node->loc) == EXPR_LIST)
+ descr = dw_sra_loc_expr (decl, node->loc);
+ else
+ {
+ initialized = NOTE_VAR_LOCATION_STATUS (node->loc);
+ varloc = NOTE_VAR_LOCATION (node->loc);
+ descr = dw_loc_list_1 (decl, varloc, want_address,
+ initialized);
+ }
+ gcc_assert (descr);
+ /* The variable has a location between NODE->LABEL and
+ NODE->NEXT->LABEL. */
+ if (node->next)
+ endname = node->next->label;
+ else
+ endname = cfun->fde->dw_fde_second_end;
+ *listp = new_loc_list (descr, cfun->fde->dw_fde_second_begin,
+ endname, secname);
+ listp = &(*listp)->dw_loc_next;
+ }
+ }
/* Try to avoid the overhead of a location list emitting a location
expression instead, but only if we didn't have more than one
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 32fce8c..ca2206c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2017-11-21 Jakub Jelinek <jakub@redhat.com>
+ PR debug/82718
+ * gcc.dg/debug/dwarf2/pr82718-1.c: New test.
+ * gcc.dg/debug/dwarf2/pr82718-2.c: New test.
+
PR debug/82933
* gcc.dg/rtl/x86_64/pr82933.c: New test.
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c
new file mode 100644
index 0000000..1ed92bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-1.c
@@ -0,0 +1,41 @@
+/* PR debug/82718 */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -gdwarf-5" } */
+
+extern int e;
+extern long foo (int, void *, unsigned long, unsigned long);
+struct S
+{
+ int f;
+ unsigned long t, s;
+};
+
+static inline long
+bv (int x, void *y, unsigned long z, unsigned long w)
+{
+ long a = 0;
+ do
+ {
+ long g;
+ do
+ g = (long int) (foo (x, y + a, z - a, w + a));
+ while (g == -1L && e == 9959);
+ if (g <= 0)
+ return g < 0 ? g : a;
+ a += g;
+ }
+ while ((unsigned long) a < z);
+ return a;
+}
+
+const char *
+baz (struct S *x)
+{
+ unsigned long h = 8;
+ char *j = 0;
+ unsigned long z = x->f;
+ if (__builtin_expect (!!((unsigned long) bv (x->f, j, z, x->t + h + 10) != z), 0))
+ return 0;
+ x->s = z;
+ return j;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c
new file mode 100644
index 0000000..85279e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr82718-2.c
@@ -0,0 +1,12 @@
+/* PR debug/82718 */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -gdwarf-5" } */
+
+extern int bar (void);
+
+int
+foo (int x)
+{
+ if (bar ())
+ __builtin_abort ();
+}