From patchwork Tue Dec 21 07:30:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 76265 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A5549B6F14 for ; Tue, 21 Dec 2010 18:30:32 +1100 (EST) Received: (qmail 3890 invoked by alias); 21 Dec 2010 07:30:30 -0000 Received: (qmail 3813 invoked by uid 22791); 21 Dec 2010 07:30:28 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 21 Dec 2010 07:30:22 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oBL7ULo5014760 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 21 Dec 2010 02:30:21 -0500 Received: from freie.oliva.athome.lsd.ic.unicamp.br (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oBL7UJOS009247 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 21 Dec 2010 02:30:20 -0500 Received: from livre.localdomain (livre-to-gw.oliva.athome.lsd.ic.unicamp.br [172.31.160.19]) by freie.oliva.athome.lsd.ic.unicamp.br (8.14.4/8.14.4) with ESMTP id oBL7UCv1031265 for ; Tue, 21 Dec 2010 05:30:12 -0200 Received: from livre.localdomain (aoliva@localhost [127.0.0.1]) by livre.localdomain (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id oBL7UBH9029654; Tue, 21 Dec 2010 05:30:11 -0200 Received: (from aoliva@localhost) by livre.localdomain (8.14.3/8.14.3/Submit) id oBL7UAVm029653; Tue, 21 Dec 2010 05:30:10 -0200 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR debug/46724] var-track address of RESULT_DECL Date: Tue, 21 Dec 2010 05:30:09 -0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 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 We curently don't emit debug info for RESULT_DECLs, but after NVR, we use the debug info we'd have emitted for them for VAR_DECLs mapped to the result, so we'd better make sure they're accurate. Unfortunately, the incoming address of the RESULT_DECL does not undergo var-tracking, and the address of the RESULT_DECL is permanently set to that of a copy of the incoming parameter, even though the copy may be optimized away within the function. This patch arranges for us to var-track (not necessarily at assignments) the nameless VAR_DECL that holds the address of the result, and sets the DECL_VALUE_EXPR of the RESULT_DECL so that the relationship between the RESULT_DECL and the nameless VAR_DECL is in the tree level, so that we use its var-tracked locations to emit debug info for any variable NVRed to the RESULT_DECL. It also introduces the needed support for DECL_VALUE_EXPR in RESULT_DECLs. Regstrapped on x86_64-linux-gnu. Ok to install? for gcc/ChangeLog from Alexandre Oliva PR debug/46724 * function.c (assign_parms_augmented_arg_list): Name and mark DECL of result address as NAMELESS rather than IGNORED. (assign_parms): Set DECL_VALUE_EXPR for indirect result. * tree.h (tree_decl_common::decl_flag_2): Document RESULT_DECL. (DECL_HAS_VALUE_EXPR_P): Accept RESULT_DECL. * dwarf2out.c (loc_list_from_tree) : Use DECL_VALUE_EXPR. * dbxout.c (dbxout_expand_expr) : Likewise. * var-tracking.c (vt_add_function_parameter): New, split out of... (vt_add_function_parameters): ... this. Handle incoming pointer to hold result. Index: gcc/function.c =================================================================== --- gcc/function.c.orig 2010-12-18 05:10:06.824255797 -0200 +++ gcc/function.c 2010-12-18 05:24:35.581505785 -0200 @@ -2253,10 +2253,11 @@ assign_parms_augmented_arg_list (struct tree decl; decl = build_decl (DECL_SOURCE_LOCATION (fndecl), - PARM_DECL, NULL_TREE, type); + PARM_DECL, get_identifier (".result_ptr"), type); DECL_ARG_TYPE (decl) = type; DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; + DECL_NAMELESS (decl) = 1; + TREE_CONSTANT (decl) = 1; DECL_CHAIN (decl) = all->orig_fnargs; all->orig_fnargs = decl; @@ -3418,13 +3419,22 @@ assign_parms (tree fndecl) rtx x; if (DECL_BY_REFERENCE (result)) - x = addr; + { + SET_DECL_VALUE_EXPR (result, all.function_result_decl); + x = addr; + } else { + SET_DECL_VALUE_EXPR (result, + build1 (INDIRECT_REF, TREE_TYPE (result), + all.function_result_decl)); addr = convert_memory_address (Pmode, addr); x = gen_rtx_MEM (DECL_MODE (result), addr); set_mem_attributes (x, result, 1); } + + DECL_HAS_VALUE_EXPR_P (result) = 1; + SET_DECL_RTL (result, x); } Index: gcc/tree.h =================================================================== --- gcc/tree.h.orig 2010-12-18 05:10:06.953255983 -0200 +++ gcc/tree.h 2010-12-18 05:20:29.812257147 -0200 @@ -2773,7 +2773,8 @@ struct GTY(()) tree_decl_common { In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */ unsigned decl_flag_1 : 1; /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P - In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR_P. */ + In VAR_DECL, PARM_DECL and RESULT_DECL, this is + DECL_HAS_VALUE_EXPR_P. */ unsigned decl_flag_2 : 1; /* Logically, these two would go in a theoretical base shared by var and parm decl. */ @@ -2818,7 +2819,8 @@ extern void decl_value_expr_insert (tree decl itself. This should only be used for debugging; once this field has been set, the decl itself may not legitimately appear in the function. */ #define DECL_HAS_VALUE_EXPR_P(NODE) \ - (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_flag_2) + (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, RESULT_DECL) \ + ->decl_common.decl_flag_2) #define DECL_VALUE_EXPR(NODE) \ (decl_value_expr_lookup (DECL_WRTL_CHECK (NODE))) #define SET_DECL_VALUE_EXPR(NODE, VAL) \ Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c.orig 2010-12-18 05:10:07.352256670 -0200 +++ gcc/dwarf2out.c 2010-12-18 05:20:29.989282017 -0200 @@ -15446,12 +15446,12 @@ loc_list_from_tree (tree loc, int want_a /* FALLTHRU */ case PARM_DECL: + case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (loc)) return loc_list_from_tree (DECL_VALUE_EXPR (loc), want_address); /* FALLTHRU */ - case RESULT_DECL: case FUNCTION_DECL: { rtx rtl; Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c.orig 2010-12-18 05:10:07.196562031 -0200 +++ gcc/dbxout.c 2010-12-18 05:20:30.095271325 -0200 @@ -2396,12 +2396,12 @@ dbxout_expand_expr (tree expr) /* FALLTHRU */ case PARM_DECL: + case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (expr)) return dbxout_expand_expr (DECL_VALUE_EXPR (expr)); /* FALLTHRU */ case CONST_DECL: - case RESULT_DECL: return DECL_RTL_IF_SET (expr); case INTEGER_CST: Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2010-12-18 05:10:07.073509808 -0200 +++ gcc/var-tracking.c 2010-12-18 05:44:50.633258275 -0200 @@ -7999,121 +7999,136 @@ vt_get_decl_and_offset (rtx rtl, tree *d return false; } -/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */ - static void -vt_add_function_parameters (void) +vt_add_function_parameter (tree parm) { - tree parm; + rtx decl_rtl = DECL_RTL_IF_SET (parm); + rtx incoming = DECL_INCOMING_RTL (parm); + tree decl; + enum machine_mode mode; + HOST_WIDE_INT offset; + dataflow_set *out; + decl_or_value dv; - for (parm = DECL_ARGUMENTS (current_function_decl); - parm; parm = DECL_CHAIN (parm)) - { - rtx decl_rtl = DECL_RTL_IF_SET (parm); - rtx incoming = DECL_INCOMING_RTL (parm); - tree decl; - enum machine_mode mode; - HOST_WIDE_INT offset; - dataflow_set *out; - decl_or_value dv; - - if (TREE_CODE (parm) != PARM_DECL) - continue; - - if (!DECL_NAME (parm)) - continue; + if (TREE_CODE (parm) != PARM_DECL) + return; - if (!decl_rtl || !incoming) - continue; + if (!decl_rtl || !incoming) + return; - if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) - continue; + if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) + return; - if (!vt_get_decl_and_offset (incoming, &decl, &offset)) + if (!vt_get_decl_and_offset (incoming, &decl, &offset)) + { + if (REG_P (incoming) || MEM_P (incoming)) { - if (REG_P (incoming) || MEM_P (incoming)) - { - /* This means argument is passed by invisible reference. */ - offset = 0; - decl = parm; - incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming); - } - else - { - if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) - continue; - offset += byte_lowpart_offset (GET_MODE (incoming), - GET_MODE (decl_rtl)); - } + /* This means argument is passed by invisible reference. */ + offset = 0; + decl = parm; + incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming); } - - if (!decl) - continue; - - if (parm != decl) + else { - /* Assume that DECL_RTL was a pseudo that got spilled to - memory. The spill slot sharing code will force the - memory to reference spill_slot_decl (%sfp), so we don't - match above. That's ok, the pseudo must have referenced - the entire parameter, so just reset OFFSET. */ - gcc_assert (decl == get_spill_slot_decl (false)); - offset = 0; + if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) + return; + offset += byte_lowpart_offset (GET_MODE (incoming), + GET_MODE (decl_rtl)); } + } - if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) - continue; + if (!decl) + return; - out = &VTI (ENTRY_BLOCK_PTR)->out; + if (parm != decl) + { + /* Assume that DECL_RTL was a pseudo that got spilled to + memory. The spill slot sharing code will force the + memory to reference spill_slot_decl (%sfp), so we don't + match above. That's ok, the pseudo must have referenced + the entire parameter, so just reset OFFSET. */ + gcc_assert (decl == get_spill_slot_decl (false)); + offset = 0; + } - dv = dv_from_decl (parm); + if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) + return; - if (target_for_debug_bind (parm) - /* We can't deal with these right now, because this kind of - variable is single-part. ??? We could handle parallels - that describe multiple locations for the same single - value, but ATM we don't. */ - && GET_CODE (incoming) != PARALLEL) - { - cselib_val *val; + out = &VTI (ENTRY_BLOCK_PTR)->out; - /* ??? We shouldn't ever hit this, but it may happen because - arguments passed by invisible reference aren't dealt with - above: incoming-rtl will have Pmode rather than the - expected mode for the type. */ - if (offset) - continue; - - val = cselib_lookup (var_lowpart (mode, incoming), mode, true); - - /* ??? Float-typed values in memory are not handled by - cselib. */ - if (val) - { - preserve_value (val); - set_variable_part (out, val->val_rtx, dv, offset, - VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); - dv = dv_from_value (val->val_rtx); - } - } + dv = dv_from_decl (parm); - if (REG_P (incoming)) + if (target_for_debug_bind (parm) + /* We can't deal with these right now, because this kind of + variable is single-part. ??? We could handle parallels + that describe multiple locations for the same single + value, but ATM we don't. */ + && GET_CODE (incoming) != PARALLEL) + { + cselib_val *val; + + /* ??? We shouldn't ever hit this, but it may happen because + arguments passed by invisible reference aren't dealt with + above: incoming-rtl will have Pmode rather than the + expected mode for the type. */ + if (offset) + return; + + val = cselib_lookup (var_lowpart (mode, incoming), mode, true); + + /* ??? Float-typed values in memory are not handled by + cselib. */ + if (val) { - incoming = var_lowpart (mode, incoming); - gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); - attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, - incoming); - set_variable_part (out, incoming, dv, offset, - VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); - } - else if (MEM_P (incoming)) - { - incoming = var_lowpart (mode, incoming); - set_variable_part (out, incoming, dv, offset, + preserve_value (val); + set_variable_part (out, val->val_rtx, dv, offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + dv = dv_from_value (val->val_rtx); } } + if (REG_P (incoming)) + { + incoming = var_lowpart (mode, incoming); + gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); + attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, + incoming); + set_variable_part (out, incoming, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + } + else if (MEM_P (incoming)) + { + incoming = var_lowpart (mode, incoming); + set_variable_part (out, incoming, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + } +} + +/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */ + +static void +vt_add_function_parameters (void) +{ + tree parm; + + for (parm = DECL_ARGUMENTS (current_function_decl); + parm; parm = DECL_CHAIN (parm)) + vt_add_function_parameter (parm); + + if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl))) + { + tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl)); + + if (TREE_CODE (vexpr) == INDIRECT_REF) + vexpr = TREE_OPERAND (vexpr, 0); + + if (TREE_CODE (vexpr) == PARM_DECL + && DECL_ARTIFICIAL (vexpr) + && !DECL_IGNORED_P (vexpr) + && DECL_NAMELESS (vexpr)) + vt_add_function_parameter (vexpr); + } + if (MAY_HAVE_DEBUG_INSNS) { cselib_preserve_only_values ();