From patchwork Thu Oct 26 08:18:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 830518 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-465171-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Hwz8UCvy"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yN0KW5Mh2z9t3J for ; Thu, 26 Oct 2017 19:19:26 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=Fc2GV/CLG5L+JU5tmO99vrCRUkFik gSIxzOpsqSaedVI0laKdCjCmv1p1RmnjDrNTdZ/A1tyhgDAyWFS7Lmj1qpSUBHev BhUAnjtMVa0EEkhqlt/TXULPzG/9/DdivNaPQDVtonoaDdr19LiEcYpRe7EJ1saU dBvbTYbeJmQL4I= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=qUu9pd4mNaFmk1aI4WpBA7tXIuM=; b=Hwz 8UCvy/eresmUAwhIN0L1LOoOBSk8x28clcq4bdeQ8LUWAHYV4xGTejw/kBQU/UAy tRqzf0DiKDSwyr5HTkWsPnra7lOIazNM+Dl2de7AHknKYgrx7b2Gd25ibYs9X7tO W0pWjPMKiys41HNUusmj/OIrWrfiHregVHIU9yfU= Received: (qmail 52130 invoked by alias); 26 Oct 2017 08:19:13 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 52071 invoked by uid 89); 26 Oct 2017 08:19:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.9 required=5.0 tests=BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 26 Oct 2017 08:19:03 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 33DE77E38D for ; Thu, 26 Oct 2017 08:19:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 33DE77E38D Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=jakub@redhat.com Received: from tucnak.zalov.cz (ovpn-116-247.ams2.redhat.com [10.36.116.247]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 827EF7B8F2; Thu, 26 Oct 2017 08:18:57 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id v9Q8Is24017376; Thu, 26 Oct 2017 10:18:55 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id v9Q8IrZ4017375; Thu, 26 Oct 2017 10:18:53 +0200 Date: Thu, 26 Oct 2017 10:18:53 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org, Mark Wielaard Subject: [PATCH] Fix DWARF5 .debug_loclist handling with hot/cold partitioning (PR debug/82718) Message-ID: <20171026081853.GS14653@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) X-IsSubscribed: yes Hi! The code in output_loc_list for DWARF5 relies on dw_loc_list_node's section field accuracy, in particular that nodes with labels in the hot subsection have one section (label) and nodes with labels in the cold subsection have another one. But that is actually not the case, so we end up with cross-section symbol difference which assembler doesn't assemble. The following patch fixes that by making sure that section in the nodes is accurate. We already have loc_list->last_before_switch which points to the last node in the first partition or NULL if either no section switch was seen (if !crtl->has_bb_partition) or if the first node is after the section switch (if crtl->has_bb_partition) and use it for the regions that need to be split among the two. The patch has lots of reindentation, so I'm including here also diff -upbd output of the dwarf2out.c changes. The first if ensures that secname is correct for the first node and the other changes update it in the loop after processing node equal to last_before_switch (or, if doing range_across_switch, after emitting first partition's entry and before emitting second partition's entry). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Jakub diff -upbd here, patch afterwards: --- gcc/dwarf2out.c.jj 2017-10-23 22:39:27.000000000 +0200 +++ gcc/dwarf2out.c 2017-10-25 21:01:13.237929750 +0200 @@ -16333,21 +16333,31 @@ dw_loc_list (var_loc_list *loc_list, tre This means we have to special case the last node, and generate a range of [last location start, end of function label]. */ + 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) + { + 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) - continue; + if (want_address == 2) descr = dw_sra_loc_expr (decl, node->loc); - if (descr == NULL) - continue; } else { @@ -16357,7 +16367,6 @@ dw_loc_list (var_loc_list *loc_list, tre } 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, @@ -16393,6 +16402,18 @@ dw_loc_list (var_loc_list *loc_list, tre && strcmp (node->label, endname) == 0) (*listp)->force = true; 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) { @@ -16412,13 +16433,11 @@ dw_loc_list (var_loc_list *loc_list, tre endname = node->next->label; else endname = cfun->fde->dw_fde_second_end; - *listp = new_loc_list (descr, - cfun->fde->dw_fde_second_begin, + *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 2017-10-26 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. * gcc.dg/debug/dwarf2/pr82718.c: New test. --- gcc/dwarf2out.c.jj 2017-10-23 22:39:27.000000000 +0200 +++ gcc/dwarf2out.c 2017-10-25 21:01:13.237929750 +0200 @@ -16333,92 +16333,111 @@ dw_loc_list (var_loc_list *loc_list, tre 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; + { + 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; + } + } + + 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); - 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); - } - - *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; - } - } - } + 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 --- gcc/testsuite/gcc.dg/debug/dwarf2/pr82718.c.jj 2017-10-25 21:10:53.324920386 +0200 +++ gcc/testsuite/gcc.dg/debug/dwarf2/pr82718.c 2017-10-25 21:10:25.000000000 +0200 @@ -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; +}