From patchwork Sat Nov 9 13:45:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 289994 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)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A5DC02C00C2 for ; Sun, 10 Nov 2013 00:46:20 +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:subject:content-type; q= dns; s=default; b=XbvOiELsCeh6fIRkfHzw6US6dYOqpPTmDWhsL+SI0YIN4W +JShZY1VUU87Mx9lXmb9sUZTtaDBkkYDiBaQRqcdx16i9NqtxZvgpbO+qSWi5qqA FOAssZN4G6CHCexIVaiku40yxCho6qVf0WvbxmWz9t5AGsQm8mNKAqBul4BdQ= 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:subject:content-type; s= default; bh=RHJM+LQXfzo0GIv97ZA1N9jviN4=; b=RQzu9kzTwZlMQOlICqJS arKGMgfxLgQcWRoKNNp69o0AojcZI5LVKsCeVdvP9DWGt2lk2nwkB1O0KDF/+wcV We9PcjQfOy9bPh8fej0XVrMNBNfBfQjUoVfQrVS6+iWGUDE0eMaXwe/5vmOSCG9v fOeyDcKQ8kYA01bGTLrzvHw= Received: (qmail 4054 invoked by alias); 9 Nov 2013 13:46:11 -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 4035 invoked by uid 89); 9 Nov 2013 13:46:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=4.0 required=5.0 tests=AWL, BAYES_50, GARBLED_SUBJECT, RDNS_NONE, URIBL_BLOCKED autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx02.qsc.de Received: from Unknown (HELO mx02.qsc.de) (213.148.130.14) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Sat, 09 Nov 2013 13:46:08 +0000 Received: from archimedes.net-b.de (port-92-194-51-140.dynamic.qsc.de [92.194.51.140]) by mx02.qsc.de (Postfix) with ESMTP id A0ED525340; Sat, 9 Nov 2013 14:45:58 +0100 (CET) Message-ID: <527E3C96.8030908@net-b.de> Date: Sat, 09 Nov 2013 14:45:58 +0100 From: Tobias Burnus User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0 MIME-Version: 1.0 To: gcc patches , gfortran , Jakub Jelinek , Tom Tromey Subject: PR37132 =?UTF-8?B?4oCTIFJGQyBwYXRjaCBmb3IgZ2VuZXJhdGlvbiBvZiBEV0E=?= =?UTF-8?B?UkYgc3ltYm9sIGZvciBGb3J0cmFuJ3MgbmFtZWxpc3RzIChEV19UQUdfbmFtZWw=?= =?UTF-8?B?aXN0KQ==?= Hi all, I have a problem generating DW_TAG_namelist dies in conjunction with USE-only association. For a NAMELIST in a module on in a procedure (subroutine, function), one generates a DW_TAG_namelist which contains a list of DW_TAG_namelist_item. (Works, except that gdb doesn't support DW_TAG_namelist at all, cf. Sourceware/gdb PR fortran/15353.) For "USE mod_name", one just generates DW_TAG_imported_module – and the debugger has to find the variables/namelists itself. (Also works.) But for "USE mod_name, only: nml", one is supposed to generate a DW_TAG_imported_declaration. And there I am stuck. For normal variables, the DW_TAG_imported_declaration refers to a DW_TAG_variable die. Analogously, for a namelist one would have to refer to a DW_TAG_namelist die. But such DW_TAG_namelist comes with a DW_TAG_namelist_item list. And for the latter, one needs to have the die of all variables in the namelist. But with use-only the symbols aren't use associate and no decl or die exists. (Failing call tree with the patch: gfc_trans_use_stmts -> dwarf2out_imported_module_or_decl_1 -> force_decl_die.) What's the proper DWARF way of handling this? Creating a DW_TAG_namelist without any DW_TAG_namelist_items, relying on the debugger to pick those from the module? Or how is one supposed to handle it? Would as a first step the patch be acceptable without the change in gfc_trans_use_stmts? Without those bits, the patch works and just doesn't attempt to generate the DW_TAG_imported_declaration for use-only. * * * Regarding the attached patch: It is based on http://gcc.gnu.org/ml/gcc-patches/2013-06/msg00534.html and handles - Namelists in subroutines/functions - Namelists in modules - USE association without ONLY It doesn't handle (see above) USE association with ONLY. (Side note: Namelists may not be renamed. [The namelist name appears in the file when doing I/O, thus, renaming doesn't make sense.]) For integer :: i, real :: r NAMELIST /nml/ i, r GCC now generates the output: <2><238>: Abbrev Number: 11 (DW_TAG_namelist) <239> DW_AT_name : nml <23d> DW_AT_sibling : <0x24c> <3><241>: Abbrev Number: 12 (DW_TAG_namelist_item) <242> DW_AT_namelist_items: <0x24c> <3><246>: Abbrev Number: 12 (DW_TAG_namelist_item) <247> DW_AT_namelist_items: <0x255> <2><24c>: Abbrev Number: 13 (DW_TAG_variable) <24d> DW_AT_name : i ... Test case would be (e.g. file1.f90): module m implicit none integer :: ii real :: rr namelist /nml/ ii, rr end module m subroutine bar() complex :: xyz namelist /nml/ xyz write(*,nml=nml) end subroutine bar and as USE-er for "m" (e.g. file2.f90): use m, only: nml ! Or: "use m" implicit none write(*,nml=nml) ! ii = 5 end Tobias gcc/ 2013-11-09 Tobias Burnus PR debug/37132 * lto-streamer.h (LTO_tags): Add LTO_namelist_decl_ref. * tree.def (NAMELIST_DECL): Add. * tree.h (NAMELIST_DECL_ASSOCIATED_DECL): New macro. * tree.c (initialize_tree_contains_struct): Add asserts for it. * dwarf2out.c (gen_namelist_decl): New function. (gen_decl_die, dwarf2out_decl): Call it. * lto-streamer-in.c (lto_input_tree_ref): Handle NAMELIST_DECL. (lto_input_tree_ref, lto_input_tree_1): Update lto_tag_check_range call. * lto-streamer-out.c (lto_output_tree_ref): Handle NAMELIST_DECL. gcc/fortran 2013-11-09 Tobias Burnus PR debug/37132 * trans-decl.c (generate_namelist_decl, create_module_nml_decl): New static functions. (gfc_generate_module_vars, generate_local_vars): Call them. (gfc_trans_use_stmts): Handle namelists for debug genertion. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5ef7bd2..67bf631 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3182,6 +3182,7 @@ static inline int is_redundant_typedef (const_tree); static bool is_naming_typedef_decl (const_tree); static inline dw_die_ref get_context_die (tree); static void gen_namespace_die (tree, dw_die_ref); +static void gen_namelist_decl (tree, dw_die_ref, tree); static dw_die_ref gen_decl_die (tree, tree, dw_die_ref); static dw_die_ref force_decl_die (tree); static dw_die_ref force_type_die (tree); @@ -20420,6 +20421,11 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die) gen_namespace_die (decl, context_die); break; + case NAMELIST_DECL: + gen_namelist_decl (DECL_NAME (decl), context_die, + NAMELIST_DECL_ASSOCIATED_DECL (decl)); + break; + default: /* Probably some frontend-internal decl. Assume we don't care. */ gcc_assert ((int)TREE_CODE (decl) > NUM_TREE_CODES); @@ -20581,6 +20587,34 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, } +/* Output debug information for namelists. */ + +static void +gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls) +{ + dw_die_ref nml_die, nml_item_die, nml_item_ref_die; + tree value; + unsigned i; + + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + + gcc_assert (scope_die != NULL); + nml_die = new_die (DW_TAG_namelist, scope_die, NULL); + add_AT_string (nml_die, DW_AT_name, IDENTIFIER_POINTER (name)); + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (item_decls), i, value) + { + nml_item_ref_die = lookup_decl_die (value); + if (!nml_item_ref_die) + nml_item_ref_die = force_decl_die (value); + + nml_item_die = new_die (DW_TAG_namelist_item, nml_die, NULL); + add_AT_die_ref (nml_item_die, DW_AT_namelist_items, nml_item_ref_die); + } +} + + /* Write the debugging output for DECL. */ void @@ -20701,6 +20735,9 @@ dwarf2out_decl (tree decl) break; + case NAMELIST_DECL: + break; + default: return; } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index c2c736e..b615ff6 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -4140,6 +4140,37 @@ gfc_module_add_decl (struct module_htab_entry *entry, tree decl) static struct module_htab_entry *cur_module; + +/* Generate debugging symbols for namelists. This function must come after + generate_local_decl to ensure that the variables in the namelist are + already declared. */ + +static tree +generate_namelist_decl (gfc_symbol * sym) +{ + gfc_namelist *nml; + tree decl; + vec *nml_decls = NULL; + + gcc_assert (sym->attr.flavor == FL_NAMELIST); + for (nml = sym->namelist; nml; nml = nml->next) + { + if (nml->sym->backend_decl == NULL_TREE) + { + nml->sym->attr.referenced = 1; + nml->sym->backend_decl = gfc_get_symbol_decl (nml->sym); + } + CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, nml->sym->backend_decl); + } + + decl = make_node (NAMELIST_DECL); + TREE_TYPE (decl) = void_type_node; + NAMELIST_DECL_ASSOCIATED_DECL (decl) = build_constructor (NULL_TREE, nml_decls); + DECL_NAME (decl) = get_identifier (sym->name); + return decl; +} + + /* Output an initialized decl for a module variable. */ static void @@ -4329,6 +4360,18 @@ gfc_trans_use_stmts (gfc_namespace * ns) DECL_IGNORED_P (decl) = 0; DECL_INITIAL (decl) = NULL_TREE; } + else if (st->n.sym->attr.flavor == FL_NAMELIST + && st->n.sym->attr.use_only + && st->n.sym->module + && strcmp (st->n.sym->module, use_stmt->module_name) + == 0) + { + decl = generate_namelist_decl (st->n.sym); + DECL_CONTEXT (decl) = entry->namespace_decl; + DECL_EXTERNAL (decl) = 1; + DECL_IGNORED_P (decl) = 0; + DECL_INITIAL (decl) = NULL_TREE; + } else { *slot = error_mark_node; @@ -4606,6 +4649,21 @@ generate_coarray_init (gfc_namespace * ns __attribute((unused))) } +static void +create_module_nml_decl (gfc_symbol *sym) +{ + if (sym->attr.flavor == FL_NAMELIST) + { + tree decl = generate_namelist_decl (sym); + pushdecl (decl); + gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE); + DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl; + rest_of_decl_compilation (decl, 1, 0); + gfc_module_add_decl (cur_module, decl); + } +} + + /* Generate all the required code for module variables. */ void @@ -4624,6 +4682,7 @@ gfc_generate_module_vars (gfc_namespace * ns) /* Create decls for all the module variables. */ gfc_traverse_ns (ns, gfc_create_module_variable); + gfc_traverse_ns (ns, create_module_nml_decl); if (gfc_option.coarray == GFC_FCOARRAY_LIB && has_coarray_vars) generate_coarray_init (ns); @@ -4889,10 +4948,23 @@ generate_local_decl (gfc_symbol * sym) sym->backend_decl = gfc_typenode_for_spec (&(sym->ts)); } + +static void +generate_local_nml_decl (gfc_symbol * sym) +{ + if (sym->attr.flavor == FL_NAMELIST && !sym->attr.use_assoc) + { + tree decl = generate_namelist_decl (sym); + pushdecl (decl); + } +} + + static void generate_local_vars (gfc_namespace * ns) { gfc_traverse_ns (ns, generate_local_decl); + gfc_traverse_ns (ns, generate_local_nml_decl); } diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index d4a52a7..138852a 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -200,7 +200,7 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, unsigned HOST_WIDE_INT ix_u; tree result = NULL_TREE; - lto_tag_check_range (tag, LTO_field_decl_ref, LTO_global_decl_ref); + lto_tag_check_range (tag, LTO_field_decl_ref, LTO_namelist_decl_ref); switch (tag) { @@ -244,6 +244,28 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u); break; + case LTO_namelist_decl_ref: + { + tree tmp; + vec *nml_decls = NULL; + unsigned i, n; + + result = make_node (NAMELIST_DECL); + TREE_TYPE (result) = void_type_node; + DECL_NAME (result) = stream_read_tree (ib, data_in); + n = streamer_read_uhwi (ib); + for (i = 0; i < n; i++) + { + ix_u = streamer_read_uhwi (ib); + tmp = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u); + gcc_assert (tmp != NULL_TREE); + CONSTRUCTOR_APPEND_ELT (nml_decls, NULL_TREE, tmp); + } + NAMELIST_DECL_ASSOCIATED_DECL (result) = build_constructor (NULL_TREE, + nml_decls); + break; + } + default: gcc_unreachable (); } @@ -1234,7 +1256,7 @@ lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in, if (tag == LTO_null) result = NULL_TREE; - else if (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref) + else if (tag >= LTO_field_decl_ref && tag <= LTO_namelist_decl_ref) { /* If TAG is a reference to an indexable tree, the next value in IB is the index into the table where we expect to find diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 5518623..2032e3b 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -49,6 +49,8 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" +static void lto_write_tree (struct output_block*, tree, bool); + /* Clear the line info stored in DATA_IN. */ static void @@ -245,6 +247,21 @@ lto_output_tree_ref (struct output_block *ob, tree expr) lto_output_type_decl_index (ob->decl_state, ob->main_stream, expr); break; + case NAMELIST_DECL: + { + unsigned i; + tree value, tmp; + + streamer_write_record_start (ob, LTO_namelist_decl_ref); + stream_write_tree (ob, DECL_NAME (expr), true); + tmp = NAMELIST_DECL_ASSOCIATED_DECL (expr); + gcc_assert (tmp != NULL_TREE); + streamer_write_uhwi (ob, CONSTRUCTOR_ELTS (tmp)->length()); + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (tmp), i, value) + lto_output_var_decl_index (ob->decl_state, ob->main_stream, value); + break; + } + case NAMESPACE_DECL: streamer_write_record_start (ob, LTO_namespace_decl_ref); lto_output_namespace_decl_index (ob->decl_state, ob->main_stream, expr); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 797e92e..fb3a947 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -222,7 +222,8 @@ enum LTO_tags LTO_const_decl_ref, LTO_imported_decl_ref, LTO_translation_unit_decl_ref, - LTO_global_decl_ref, /* Do not change. */ + LTO_global_decl_ref, + LTO_namelist_decl_ref, /* Do not change. */ /* This tag must always be last. */ LTO_NUM_TAGS diff --git a/gcc/tree.c b/gcc/tree.c index 686a680..f5a2f44 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -540,6 +540,8 @@ initialize_tree_contains_struct (void) gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]); gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]); gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]); + gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_MINIMAL]); + gcc_assert (tree_contains_struct[NAMELIST_DECL][TS_DECL_COMMON]); } diff --git a/gcc/tree.def b/gcc/tree.def index 399b5af..8514f7d 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -377,6 +377,16 @@ DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0) IMPORTED_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */ DEFTREECODE (IMPORTED_DECL, "imported_decl", tcc_declaration, 0) +/* A namelist declaration. + The Fortran FE uses this to represent a namelist statement, e.g.: + NAMELIST /namelist-group-name/ namelist-group-object-list. + Whenever a declaration import appears in a lexical block, the BLOCK node + representing that lexical block in GIMPLE will contain an NAMELIST_DECL + node, linked via BLOCK_VARS accessor of the said BLOCK. + For a given NODE which code is NAMELIST_DECL, + NAMELIST_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */ +DEFTREECODE (NAMELIST_DECL, "namelist_decl", tcc_declaration, 0) + /* A translation unit. This is not technically a declaration, since it can't be looked up, but it's close enough. */ DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl",\ diff --git a/gcc/tree.h b/gcc/tree.h index c4b23d0..5e16b57 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2664,6 +2664,11 @@ extern vec **decl_debug_args_insert (tree); #define IMPORTED_DECL_ASSOCIATED_DECL(NODE) \ (DECL_INITIAL (IMPORTED_DECL_CHECK (NODE))) +/* Getter of the symbol declaration associated with the + NAMELIST_DECL node. */ +#define NAMELIST_DECL_ASSOCIATED_DECL(NODE) \ + (DECL_INITIAL (NODE)) + /* A STATEMENT_LIST chains statements together in GENERIC and GIMPLE. To reduce overhead, the nodes containing the statements are not trees. This avoids the overhead of tree_common on all linked list elements.