From: Jakub Jelinek Date: Tue, 21 Nov 2017 07:59:03 +0000 (+0100) Subject: re PR debug/82718 (Bad DWARF5 .debug_loclists generation) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8b87e0d12576318e2ae02284e767b4d083cc4149;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1c3aaede5ec..207e6f32b2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2017-11-21 Jakub Jelinek + 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 7fd6ae37fd2..89e119c3dca 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 32fce8c4421..ca2206c575c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2017-11-21 Jakub Jelinek + 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 00000000000..1ed92bfe90f --- /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 00000000000..85279e15bd0 --- /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 (); +}