From patchwork Wed Oct 8 19:05:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre-Marie de Rodat X-Patchwork-Id: 397692 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 9E3FC1400DE for ; Thu, 9 Oct 2014 06:05:48 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=GgxfLpJATeMyh6QVM nC8ii3xdb1/BBy+ZdniZMfKVXLz9r+bJgl9NO95G7LSe2q989ELdxJY+OFn4X7Bl JFZii8mX7eFodofV8lJ/iW27iLi0+7QZHX46yKYsj3YucIpkIUAaBu5xzujQrvpd i4ZQf1VFbQIGbntm2Lfc7urZ98= 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 :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=Ljt41pldDPEecOter1jhjYg km8I=; b=BfIUruzHLxLA8D6CyPiwpY/ROadpnyX9jC69IdyJS119EG8Ihu5uDth 96+IjQOhiUa0JSXYJL31OKh61BD+Z29mLisroY0V70PHU4EGHZhOvi7UddLvChCI S9hK/mHc2Eh7uNdmekbL7NEpAtSkY682yqNg1gczLBfdfpMngiRk= Received: (qmail 2028 invoked by alias); 8 Oct 2014 19:05:40 -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 2017 invoked by uid 89); 8 Oct 2014 19:05:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham version=3.3.2 X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 08 Oct 2014 19:05:36 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 2651327554D9; Wed, 8 Oct 2014 21:05:32 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zfPqpgG1PPaA; Wed, 8 Oct 2014 21:05:32 +0200 (CEST) Received: from [192.168.0.6] (unknown [78.193.84.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id AEF0E27501ED; Wed, 8 Oct 2014 21:05:31 +0200 (CEST) Message-ID: <54358AFA.5020201@adacore.com> Date: Wed, 08 Oct 2014 21:05:30 +0200 From: Pierre-Marie de Rodat User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.1.1 MIME-Version: 1.0 To: Jakub Jelinek CC: GCC Patches Subject: Re: [PATCH] Enhance array types debug info. for Ada References: <5406D305.1060905@adacore.com> <20141003091848.GN1986@tucnak.redhat.com> <54339F77.7050300@adacore.com> <20141007082926.GF1986@tucnak.redhat.com> In-Reply-To: <20141007082926.GF1986@tucnak.redhat.com> X-IsSubscribed: yes On 10/07/2014 10:29 AM, Jakub Jelinek wrote: > But isn't there a risk that you will have PLACEHOLDER_EXPRs (likely for Ada > only) in some trees not constructed by the langhook? > I mean, DW_OP_push_object_address isn't meaningful in all DWARF contexts, > in some it is forbidden, in others there is really no object to push, and as > implemented, you emit DW_OP_push_object_address (which emits the address of > a context related particular object) for any kind of PLACEHOLDER_EXPR with > RECORD_TYPE. Even with GNAT, this is not _supposed_ to happen. However during the development (for instance with LTO) I noticed cases where PLACEHOLDER_EXPR nodes were incorrectly used. Thanks to current work on the early debug info pass, such cases are doomed to disappear, but I completely agree with your point, so thank you for raising it. :-) > Thus, I'd feel safer, even if you decide to use a PLACEHOLDER_EXPR, that > the translation of that to DW_OP_push_object_address would be done only > if the PLACEHOLDER_EXPR is equal to some global variable, normally NULL, > and only changed temporarily while emitting loc for the array descriptor. This is what the updated (and attached) patch does. Note that upcoming patches will enhance loc_list_from_tree (adding another parameter to loc_list_from_tree) and make it recurse to generate sub-expressions as DWARF procedures. Because of this kind recursion, I added a composite argument instead of relying on a global variable (so that "nested" contexts can exist at the same time). > But then IMHO a DEBUG_EXPR_DECL is better. > [...] > Also, please verify that with your patch the generated debug info for some > Fortran arrays is the same. It's fortunate that you asked this since I wrongly assumed there was the corresponding testing in the GDB testsuite. As a matter of fact, support for Fortran's variable length arrays in GDB is still a work in progress so tests are not commited yet. So I used the Fortran example I could find there instead and discovered that my patch did break debugging information for Fortran array types. Fixing it while keeping a PLACEHOLDER_EXPR-based implementation seems a too heavy task for my little experience in the Fortran front-end and after having a closer look I agree with you: it seems less adapted to how things are currently done, there. So I finally leveraged this new composite argument to re-introduce the base_decl mechanism. DEBUG_EXPR_DECL is back in the Fortran front-end. ;-) Now, the same example keeps the same debugging information. The latest patches bootstrapped well and passed successfully the GCC testsuite on x86_64-pc-linux-gnu. From 794cafffae7202cd9ea8156bb7f7433a4e109e6c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Jun 2014 15:13:45 +0200 Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in array descr. lang-hook gcc/ * dwarf2out.h (struct array_descr_info): Remove the base_decl field. * dwarf2out.c (enum dw_scalar_form): New. (struct loc_descr_context): New. (add_scalar_info): New. (add_bound_info): Add a context parameter. Use add_scalar_info. (loc_list_from_tree): Add a context parameter. Handle PLACEHOLDER_EXPR nodes for type-related expressions. Likewise for base declarations. (loc_descriptor_from_tree): Add a context parameter. (subrange_type_die): Update calls to add_bound_info. (tls_mem_loc_descriptor): Likewise. (loc_list_for_address_of_addr_expr_of_indirect_ref): Add a context parameter. Update calls to loc_list_from_tree. (add_subscript_info): Update calls to add_bound_info. (gen_array_type_die): Update calls to loc_list_from_tree and to add_bound_info. (descr_info_loc): Remove. (add_descr_info_field): Remove. (gen_descr_array_type_die): Switch add_descr_info_field calls into add_scalar_info/add_bound_info ones. (gen_subprogram_die): Update calls to loc_list_from_tree. (gen_variable_die): Likewise. --- gcc/dwarf2out.c | 569 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 294 insertions(+), 275 deletions(-) diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 3f3bdbb..30f429e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid; static vec base_types; +/* Flags to represent a set of attribute classes for attributes that represent + a scalar value (bounds, pointers, ...). */ +enum dw_scalar_form +{ + dw_scalar_form_constant = 0x01, + dw_scalar_form_exprloc = 0x02, + dw_scalar_form_reference = 0x04 +}; + /* Forward declarations for functions defined in this file. */ static int is_pseudo_reg (const_rtx); @@ -3163,8 +3172,11 @@ static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx, enum var_init_status); static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode, enum var_init_status); -static dw_loc_list_ref loc_list_from_tree (tree, int); -static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); +struct loc_descr_context; +static dw_loc_list_ref loc_list_from_tree (tree, int, + const struct loc_descr_context *); +static dw_loc_descr_ref loc_descriptor_from_tree (tree, int, + const struct loc_descr_context *); static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); static tree field_type (const_tree); static unsigned int simple_type_align_in_bits (const_tree); @@ -3186,7 +3198,10 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree); static void add_name_attribute (dw_die_ref, const char *); static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref); static void add_comp_dir_attribute (dw_die_ref); -static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree); +static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int, + const struct loc_descr_context *); +static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree, + const struct loc_descr_context *); static void add_subscript_info (dw_die_ref, tree, bool); static void add_byte_size_attribute (dw_die_ref, tree); static void add_bit_offset_attribute (dw_die_ref, tree); @@ -10515,9 +10530,9 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die) } if (low) - add_bound_info (subrange_die, DW_AT_lower_bound, low); + add_bound_info (subrange_die, DW_AT_lower_bound, low, NULL); if (high) - add_bound_info (subrange_die, DW_AT_upper_bound, high); + add_bound_info (subrange_die, DW_AT_upper_bound, high, NULL); return subrange_die; } @@ -11493,7 +11508,7 @@ tls_mem_loc_descriptor (rtx mem) || !DECL_THREAD_LOCAL_P (base)) return NULL; - loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1); + loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1, NULL); if (loc_result == NULL) return NULL; @@ -14231,10 +14246,13 @@ cst_pool_loc_descr (tree loc) /* Return dw_loc_list representing address of addr_expr LOC by looking for inner INDIRECT_REF expression and turning - it into simple arithmetics. */ + it into simple arithmetics. + + See loc_list_from_tree for the meaning of CONTEXT. */ static dw_loc_list_ref -loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev) +loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev, + const loc_descr_context *context) { tree obj, offset; HOST_WIDE_INT bitsize, bitpos, bytepos; @@ -14258,18 +14276,19 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev) return 0; } if (!offset && !bitpos) - list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1); + list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1, + context); else if (toplev && int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE && (dwarf_version >= 4 || !dwarf_strict)) { - list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0, context); if (!list_ret) return 0; if (offset) { /* Variable offset. */ - list_ret1 = loc_list_from_tree (offset, 0); + list_ret1 = loc_list_from_tree (offset, 0, context); if (list_ret1 == 0) return 0; add_loc_list (&list_ret, list_ret1); @@ -14292,15 +14311,36 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev) } +/* Helper structure for location descriptions generation. */ +struct loc_descr_context +{ + /* The type that is implicitely referenced by DW_OP_push_object_address, or + NULL_TREE if DW_OP_push_object_address in invalid for this location + description. This is used when processing PLACEHOLDER_EXPR nodes. */ + tree context_type; + /* The ..._DECL node that should be translated as a + DW_OP_push_object_address operation. */ + tree base_decl; +}; + /* Generate Dwarf location list representing LOC. If WANT_ADDRESS is false, expression computing LOC will be computed If WANT_ADDRESS is 1, expression computing address of LOC will be returned if WANT_ADDRESS is 2, expression computing address useable in location will be returned (i.e. DW_OP_reg can be used - to refer to register values). */ + to refer to register values). + + CONTEXT provides information to customize the location descriptions + generation. Its context_type field specifies what type is implicitely + referenced by DW_OP_push_object_address. If it is NULL_TREE, this operation + will not be generated. + + If CONTEXT is NULL, the behavior is the same as if the context_type field + was NULL_TREE. */ static dw_loc_list_ref -loc_list_from_tree (tree loc, int want_address) +loc_list_from_tree (tree loc, int want_address, + const struct loc_descr_context *context) { dw_loc_descr_ref ret = NULL, ret1 = NULL; dw_loc_list_ref list_ret = NULL, list_ret1 = NULL; @@ -14311,6 +14351,12 @@ loc_list_from_tree (tree loc, int want_address) extending the values properly. Hopefully this won't be a real problem... */ + if (context != NULL + && context->base_decl == loc + && want_address == 0) + return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0), + NULL, NULL, NULL); + switch (TREE_CODE (loc)) { case ERROR_MARK: @@ -14319,11 +14365,26 @@ loc_list_from_tree (tree loc, int want_address) case PLACEHOLDER_EXPR: /* This case involves extracting fields from an object to determine the - position of other fields. We don't try to encode this here. The - only user of this is Ada, which encodes the needed information using - the names of types. */ - expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR"); - return 0; + position of other fields. It is supposed to appear only as the first + operand of COMPONENT_REF nodes and to reference precisely the type + that the context allows. */ + if (context != NULL + && TREE_TYPE (loc) == context->context_type + && want_address >= 1) + { + if (dwarf_version >= 3 || !dwarf_strict) + { + ret = new_loc_descr (DW_OP_push_object_address, 0, 0); + have_address = 1; + break; + } + else + return NULL; + } + else + expansion_failed (loc, NULL_RTX, + "PLACEHOLDER_EXPR for a unexpected type"); + break; case CALL_EXPR: expansion_failed (loc, NULL_RTX, "CALL_EXPR"); @@ -14344,7 +14405,7 @@ loc_list_from_tree (tree loc, int want_address) if (want_address) { list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref - (loc, want_address == 2); + (loc, want_address == 2, context); if (list_ret) have_address = 1; else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0)) @@ -14353,7 +14414,7 @@ loc_list_from_tree (tree loc, int want_address) } /* Otherwise, process the argument and look for the address. */ if (!list_ret && !ret) - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1, context); else { if (want_address) @@ -14423,7 +14484,7 @@ loc_list_from_tree (tree loc, int want_address) case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (loc)) return loc_list_from_tree (DECL_VALUE_EXPR (loc), - want_address); + want_address, context); /* FALLTHRU */ case FUNCTION_DECL: @@ -14497,7 +14558,7 @@ loc_list_from_tree (tree loc, int want_address) } /* Fallthru. */ case INDIRECT_REF: - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); have_address = 1; break; @@ -14506,13 +14567,13 @@ loc_list_from_tree (tree loc, int want_address) return NULL; case COMPOUND_EXPR: - return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address); + return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address, context); CASE_CONVERT: case VIEW_CONVERT_EXPR: case SAVE_EXPR: case MODIFY_EXPR: - return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address); + return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address, context); case COMPONENT_REF: case BIT_FIELD_REF: @@ -14533,7 +14594,8 @@ loc_list_from_tree (tree loc, int want_address) list_ret = loc_list_from_tree (obj, want_address == 2 - && !bitpos && !offset ? 2 : 1); + && !bitpos && !offset ? 2 : 1, + context); /* TODO: We can extract value of the small expression via shifting even for nonzero bitpos. */ if (list_ret == 0) @@ -14548,7 +14610,7 @@ loc_list_from_tree (tree loc, int want_address) if (offset != NULL_TREE) { /* Variable offset. */ - list_ret1 = loc_list_from_tree (offset, 0); + list_ret1 = loc_list_from_tree (offset, 0, context); if (list_ret1 == 0) return 0; add_loc_list (&list_ret, list_ret1); @@ -14638,8 +14700,8 @@ loc_list_from_tree (tree loc, int want_address) op = DW_OP_mod; goto do_binop; } - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); - list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); + list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context); if (list_ret == 0 || list_ret1 == 0) return 0; @@ -14670,7 +14732,7 @@ loc_list_from_tree (tree loc, int want_address) do_plus: if (tree_fits_shwi_p (TREE_OPERAND (loc, 1))) { - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); if (list_ret == 0) return 0; @@ -14718,8 +14780,8 @@ loc_list_from_tree (tree loc, int want_address) goto do_binop; do_binop: - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); - list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); + list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context); if (list_ret == 0 || list_ret1 == 0) return 0; @@ -14743,7 +14805,7 @@ loc_list_from_tree (tree loc, int want_address) goto do_unop; do_unop: - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); if (list_ret == 0) return 0; @@ -14767,12 +14829,12 @@ loc_list_from_tree (tree loc, int want_address) case COND_EXPR: { dw_loc_descr_ref lhs - = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); + = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0, context); dw_loc_list_ref rhs - = loc_list_from_tree (TREE_OPERAND (loc, 2), 0); + = loc_list_from_tree (TREE_OPERAND (loc, 2), 0, context); dw_loc_descr_ref bra_node, jump_node, tmp; - list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); if (list_ret == 0 || lhs == 0 || rhs == 0) return 0; @@ -14878,9 +14940,10 @@ loc_list_from_tree (tree loc, int want_address) /* Same as above but return only single location expression. */ static dw_loc_descr_ref -loc_descriptor_from_tree (tree loc, int want_address) +loc_descriptor_from_tree (tree loc, int want_address, + const struct loc_descr_context *context) { - dw_loc_list_ref ret = loc_list_from_tree (loc, want_address); + dw_loc_list_ref ret = loc_list_from_tree (loc, want_address, context); if (!ret) return NULL; if (ret->dw_loc_next) @@ -15940,7 +16003,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p, } if (list == NULL) { - list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2); + list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2, + NULL); /* It is usually worth caching this result if the decl is from BLOCK_NONLOCALIZED_VARS and if the list has at least two elements. */ if (cache_p && list && list->dw_loc_next) @@ -16432,6 +16496,142 @@ add_comp_dir_attribute (dw_die_ref die) add_AT_string (die, DW_AT_comp_dir, wd); } +/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a + pointer computation, ...), output a representation for that bound according + to the accepted FORMS (see enum dw_scalar_form) and add it to DIE. See + loc_list_from_tree for the meaning of CONTEXT. */ + +static void +add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value, + int forms, const struct loc_descr_context *context) +{ + dw_die_ref ctx, decl_die; + dw_loc_list_ref list; + + bool strip_conversions = true; + + while (strip_conversions) + switch (TREE_CODE (value)) + { + case ERROR_MARK: + case SAVE_EXPR: + return; + + CASE_CONVERT: + case VIEW_CONVERT_EXPR: + value = TREE_OPERAND (value, 0); + break; + + default: + strip_conversions = false; + break; + } + + /* If possible and permitted, output the attribute as a constant. */ + if ((forms & dw_scalar_form_constant) != 0 + && TREE_CODE (value) == INTEGER_CST) + { + unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value)); + + /* If HOST_WIDE_INT is big enough then represent the bound as + a constant value. We need to choose a form based on + whether the type is signed or unsigned. We cannot just + call add_AT_unsigned if the value itself is positive + (add_AT_unsigned might add the unsigned value encoded as + DW_FORM_data[1248]). Some DWARF consumers will lookup the + bounds type and then sign extend any unsigned values found + for signed types. This is needed only for + DW_AT_{lower,upper}_bound, since for most other attributes, + consumers will treat DW_FORM_data[1248] as unsigned values, + regardless of the underlying type. */ + if (prec <= HOST_BITS_PER_WIDE_INT + || tree_fits_uhwi_p (value)) + { + if (TYPE_UNSIGNED (TREE_TYPE (value))) + add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value)); + else + add_AT_int (die, attr, TREE_INT_CST_LOW (value)); + } + else + /* Otherwise represent the bound as an unsigned value with + the precision of its type. The precision and signedness + of the type will be necessary to re-interpret it + unambiguously. */ + add_AT_wide (die, attr, value); + } + + /* Otherwise, if it's possible and permitted too, output a reference to + another DIE. */ + if ((forms & dw_scalar_form_reference) != 0) + { + tree decl = NULL_TREE; + + /* Some type attributes reference an outer type. For instance, the upper + bound of an array may reference an embedding record (this happens in + Ada). */ + if (TREE_CODE (value) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR + && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL) + decl = TREE_OPERAND (value, 1); + + else if (TREE_CODE (value) == VAR_DECL + || TREE_CODE (value) == PARM_DECL + || TREE_CODE (value) == RESULT_DECL) + decl = value; + + if (decl != NULL_TREE) + { + dw_die_ref decl_die = lookup_decl_die (decl); + + /* ??? Can this happen, or should the variable have been bound + first? Probably it can, since I imagine that we try to create + the types of parameters in the order in which they exist in + the list, and won't have created a forward reference to a + later parameter. */ + if (decl_die != NULL) + { + add_AT_die_ref (die, attr, decl_die); + return; + } + } + } + + /* Last chance: try to create a stack operation procedure to evaluate the + value. Do nothing if even that is not possible or permitted. */ + if ((forms & dw_scalar_form_exprloc) == 0) + return; + + list = loc_list_from_tree (value, 2, context); + if (list == NULL || single_element_loc_list_p (list)) + { + /* If this attribute is not a reference nor constant, it is + a DWARF expression rather than location description. For that + loc_list_from_tree (value, 0, &context) is needed. */ + dw_loc_list_ref list2 = loc_list_from_tree (value, 0, context); + if (list2 && single_element_loc_list_p (list2)) + { + add_AT_loc (die, attr, list2->expr); + return; + } + } + + /* If that failed to give a single element location list, fall back to + outputting this as a reference... still if permitted. */ + if (list == NULL || (forms & dw_scalar_form_reference) == 0) + return; + + if (current_function_decl == 0) + ctx = comp_unit_die (); + else + ctx = lookup_decl_die (current_function_decl); + + decl_die = new_die (DW_TAG_variable, ctx, value); + add_AT_flag (decl_die, DW_AT_artificial, 1); + add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx); + add_AT_location_description (decl_die, DW_AT_location, list); + add_AT_die_ref (die, attr, decl_die); +} + /* Return the default for DW_AT_lower_bound, or -1 if there is not any default. */ @@ -16473,121 +16673,41 @@ lower_bound_default (void) a representation for that bound. */ static void -add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound) +add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, + tree bound, const struct loc_descr_context *context) { - switch (TREE_CODE (bound)) - { - case ERROR_MARK: - return; + int dflt; - /* All fixed-bounds are represented by INTEGER_CST nodes. */ - case INTEGER_CST: + while (1) + switch (TREE_CODE (bound)) { - unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound)); - int dflt; + /* Strip all conversions. */ + CASE_CONVERT: + case VIEW_CONVERT_EXPR: + bound = TREE_OPERAND (bound, 0); + break; - /* Use the default if possible. */ + /* All fixed-bounds are represented by INTEGER_CST nodes. Lower bounds + are even omitted when they are the default. */ + case INTEGER_CST: + /* If the value for this bound is the default one, we can even omit the + attribute. */ if (bound_attr == DW_AT_lower_bound && tree_fits_shwi_p (bound) && (dflt = lower_bound_default ()) != -1 && tree_to_shwi (bound) == dflt) - ; - - /* If HOST_WIDE_INT is big enough then represent the bound as - a constant value. We need to choose a form based on - whether the type is signed or unsigned. We cannot just - call add_AT_unsigned if the value itself is positive - (add_AT_unsigned might add the unsigned value encoded as - DW_FORM_data[1248]). Some DWARF consumers will lookup the - bounds type and then sign extend any unsigned values found - for signed types. This is needed only for - DW_AT_{lower,upper}_bound, since for most other attributes, - consumers will treat DW_FORM_data[1248] as unsigned values, - regardless of the underlying type. */ - else if (prec <= HOST_BITS_PER_WIDE_INT - || tree_fits_uhwi_p (bound)) - { - if (TYPE_UNSIGNED (TREE_TYPE (bound))) - add_AT_unsigned (subrange_die, bound_attr, - TREE_INT_CST_LOW (bound)); - else - add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound)); - } - else - /* Otherwise represent the bound as an unsigned value with - the precision of its type. The precision and signedness - of the type will be necessary to re-interpret it - unambiguously. */ - add_AT_wide (subrange_die, bound_attr, bound); - } - break; - - CASE_CONVERT: - case VIEW_CONVERT_EXPR: - add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); - break; - - case SAVE_EXPR: - break; - - case VAR_DECL: - case PARM_DECL: - case RESULT_DECL: - { - dw_die_ref decl_die = lookup_decl_die (bound); - - /* ??? Can this happen, or should the variable have been bound - first? Probably it can, since I imagine that we try to create - the types of parameters in the order in which they exist in - the list, and won't have created a forward reference to a - later parameter. */ - if (decl_die != NULL) - { - add_AT_die_ref (subrange_die, bound_attr, decl_die); - break; - } - } - /* FALLTHRU */ - - default: - { - /* Otherwise try to create a stack operation procedure to - evaluate the value of the array bound. */ - - dw_die_ref ctx, decl_die; - dw_loc_list_ref list; - - list = loc_list_from_tree (bound, 2); - if (list == NULL || single_element_loc_list_p (list)) - { - /* If DW_AT_*bound is not a reference nor constant, it is - a DWARF expression rather than location description. - For that loc_list_from_tree (bound, 0) is needed. - If that fails to give a single element list, - fall back to outputting this as a reference anyway. */ - dw_loc_list_ref list2 = loc_list_from_tree (bound, 0); - if (list2 && single_element_loc_list_p (list2)) - { - add_AT_loc (subrange_die, bound_attr, list2->expr); - break; - } - } - if (list == NULL) - break; + return; - if (current_function_decl == 0) - ctx = comp_unit_die (); - else - ctx = lookup_decl_die (current_function_decl); + /* FALLTHRU */ - decl_die = new_die (DW_TAG_variable, ctx, bound); - add_AT_flag (decl_die, DW_AT_artificial, 1); - add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx); - add_AT_location_description (decl_die, DW_AT_location, list); - add_AT_die_ref (subrange_die, bound_attr, decl_die); - break; + default: + add_scalar_info (subrange_die, bound_attr, bound, + dw_scalar_form_constant + | dw_scalar_form_exprloc + | dw_scalar_form_reference, + context); + return; } - } } /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing @@ -16644,9 +16764,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p) to produce useful results, go ahead and output the lower bound solo, and hope the debugger can cope. */ - add_bound_info (subrange_die, DW_AT_lower_bound, lower); + add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL); if (upper) - add_bound_info (subrange_die, DW_AT_upper_bound, upper); + add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL); } /* Otherwise we have an array type with an unspecified length. The @@ -17305,7 +17425,7 @@ gen_array_type_die (tree type, dw_die_ref context_die) && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) { tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); - dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2); + dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL); size = int_size_in_bytes (TREE_TYPE (szdecl)); if (loc && size > 0) @@ -17347,9 +17467,9 @@ gen_array_type_die (tree type, dw_die_ref context_die) { /* For VECTOR_TYPEs we use an array die with appropriate bounds. */ dw_die_ref subrange_die = new_die (DW_TAG_subrange_type, array_die, NULL); - add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node); + add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node, NULL); add_bound_info (subrange_die, DW_AT_upper_bound, - size_int (TYPE_VECTOR_SUBPARTS (type) - 1)); + size_int (TYPE_VECTOR_SUBPARTS (type) - 1), NULL); } else add_subscript_info (array_die, type, collapse_nested_arrays); @@ -17375,99 +17495,6 @@ gen_array_type_die (tree type, dw_die_ref context_die) add_pubtype (type, array_die); } -static dw_loc_descr_ref -descr_info_loc (tree val, tree base_decl) -{ - HOST_WIDE_INT size; - dw_loc_descr_ref loc, loc2; - enum dwarf_location_atom op; - - if (val == base_decl) - return new_loc_descr (DW_OP_push_object_address, 0, 0); - - switch (TREE_CODE (val)) - { - CASE_CONVERT: - return descr_info_loc (TREE_OPERAND (val, 0), base_decl); - case VAR_DECL: - return loc_descriptor_from_tree (val, 0); - case INTEGER_CST: - if (tree_fits_shwi_p (val)) - return int_loc_descriptor (tree_to_shwi (val)); - break; - case INDIRECT_REF: - size = int_size_in_bytes (TREE_TYPE (val)); - if (size < 0) - break; - loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); - if (!loc) - break; - if (size == DWARF2_ADDR_SIZE) - add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0)); - else - add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0)); - return loc; - case POINTER_PLUS_EXPR: - case PLUS_EXPR: - if (tree_fits_uhwi_p (TREE_OPERAND (val, 1)) - && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384) - { - loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); - if (!loc) - break; - loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1))); - } - else - { - op = DW_OP_plus; - do_binop: - loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); - if (!loc) - break; - loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl); - if (!loc2) - break; - add_loc_descr (&loc, loc2); - add_loc_descr (&loc2, new_loc_descr (op, 0, 0)); - } - return loc; - case MINUS_EXPR: - op = DW_OP_minus; - goto do_binop; - case MULT_EXPR: - op = DW_OP_mul; - goto do_binop; - case EQ_EXPR: - op = DW_OP_eq; - goto do_binop; - case NE_EXPR: - op = DW_OP_ne; - goto do_binop; - default: - break; - } - return NULL; -} - -static void -add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr, - tree val, tree base_decl) -{ - dw_loc_descr_ref loc; - - if (tree_fits_shwi_p (val)) - { - add_AT_unsigned (die, attr, tree_to_shwi (val)); - return; - } - - loc = descr_info_loc (val, base_decl); - if (!loc) - return; - - add_AT_loc (die, attr, loc); -} - /* This routine generates DIE for array with hidden descriptor, details are filled into *info by a langhook. */ @@ -17477,6 +17504,7 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info, { const dw_die_ref scope_die = scope_die_for (type, context_die); const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type); + const struct loc_descr_context context = { type, info->base_decl }; int dim; add_name_attribute (array_die, type_tag (type)); @@ -17498,15 +17526,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info, if (dwarf_version >= 3 || !dwarf_strict) { if (info->data_location) - add_descr_info_field (array_die, DW_AT_data_location, - info->data_location, - info->base_decl); + add_scalar_info (array_die, DW_AT_data_location, info->data_location, + dw_scalar_form_exprloc, &context); if (info->associated) - add_descr_info_field (array_die, DW_AT_associated, info->associated, - info->base_decl); + add_scalar_info (array_die, DW_AT_associated, info->associated, + dw_scalar_form_constant + | dw_scalar_form_exprloc + | dw_scalar_form_reference, &context); if (info->allocated) - add_descr_info_field (array_die, DW_AT_allocated, info->allocated, - info->base_decl); + add_scalar_info (array_die, DW_AT_allocated, info->allocated, + dw_scalar_form_constant + | dw_scalar_form_exprloc + | dw_scalar_form_reference, &context); } add_gnat_descriptive_type_attribute (array_die, type, context_die); @@ -17521,30 +17552,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info, info->dimen[dim].bounds_type, 0, context_die); if (info->dimen[dim].lower_bound) - { - /* If it is the default value, omit it. */ - int dflt; - - if (tree_fits_shwi_p (info->dimen[dim].lower_bound) - && (dflt = lower_bound_default ()) != -1 - && tree_to_shwi (info->dimen[dim].lower_bound) == dflt) - ; - else - add_descr_info_field (subrange_die, DW_AT_lower_bound, - info->dimen[dim].lower_bound, - info->base_decl); - } + add_bound_info (subrange_die, DW_AT_lower_bound, + info->dimen[dim].lower_bound, &context); if (info->dimen[dim].upper_bound) - add_descr_info_field (subrange_die, DW_AT_upper_bound, - info->dimen[dim].upper_bound, - info->base_decl); - if (dwarf_version >= 3 || !dwarf_strict) - { - if (info->dimen[dim].stride) - add_descr_info_field (subrange_die, DW_AT_byte_stride, - info->dimen[dim].stride, - info->base_decl); - } + add_bound_info (subrange_die, DW_AT_upper_bound, + info->dimen[dim].upper_bound, &context); + if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride) + add_scalar_info (subrange_die, DW_AT_byte_stride, + info->dimen[dim].stride, + dw_scalar_form_constant + | dw_scalar_form_exprloc + | dw_scalar_form_reference, + &context); } gen_type_die (info->element_type, context_die); @@ -18602,7 +18621,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) if (fun->static_chain_decl) add_AT_location_description (subr_die, DW_AT_static_link, - loc_list_from_tree (fun->static_chain_decl, 2)); + loc_list_from_tree (fun->static_chain_decl, 2, NULL)); } /* Generate child dies for template paramaters. */ @@ -18933,7 +18952,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) { if (get_AT (var_die, DW_AT_location) == NULL) { - loc = loc_list_from_tree (com_decl, off ? 1 : 2); + loc = loc_list_from_tree (com_decl, off ? 1 : 2, NULL); if (loc) { if (off) @@ -18967,7 +18986,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) com_die_arg.decl_id = DECL_UID (com_decl); com_die_arg.die_parent = context_die; com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg); - loc = loc_list_from_tree (com_decl, 2); + loc = loc_list_from_tree (com_decl, 2, NULL); if (com_die == NULL) { const char *cnam @@ -18981,7 +19000,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) add_AT_location_description (com_die, DW_AT_location, loc); /* Avoid sharing the same loc descriptor between DW_TAG_common_block and DW_TAG_variable. */ - loc = loc_list_from_tree (com_decl, 2); + loc = loc_list_from_tree (com_decl, 2, NULL); } else if (DECL_EXTERNAL (decl)) add_AT_flag (com_die, DW_AT_declaration, 1); @@ -18994,7 +19013,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) else if (get_AT (com_die, DW_AT_location) == NULL && loc) { add_AT_location_description (com_die, DW_AT_location, loc); - loc = loc_list_from_tree (com_decl, 2); + loc = loc_list_from_tree (com_decl, 2, NULL); remove_AT (com_die, DW_AT_declaration); } var_die = new_die (DW_TAG_variable, com_die, decl); -- 1.7.10.4