* [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions @ 2017-05-29 7:50 Pierre-Marie de Rodat 2017-05-29 8:05 ` [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only Pierre-Marie de Rodat 2017-05-30 11:59 ` [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Richard Biener 0 siblings, 2 replies; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-29 7:50 UTC (permalink / raw) To: gcc-patches; +Cc: Pierre-Marie de Rodat Hello, An upcoming patch exposes a bug in gimplify_modify_expr. There, we try not to create DECL_DEBUG_EXPR links across functions, however we don't check that *FROM_P actually belongs to the current function before modifying it. This patch fixes this oversight. Bootstrapped and regtested on x86_64-linux. Ok to commit? Thank you in advance! gcc/ * gimplify.c (gimplify_modify_expr): Don't create a DECL_DEBUG_EXPR link if *FROM_P does not belong to the current function. --- gcc/gimplify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 455a6993e15..2c7fc9fabd1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5580,7 +5580,8 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && DECL_IGNORED_P (*from_p) && DECL_P (*to_p) && !DECL_IGNORED_P (*to_p) - && decl_function_context (*to_p) == current_function_decl) + && decl_function_context (*to_p) == current_function_decl + && decl_function_context (*from_p) == current_function_decl) { if (!DECL_NAME (*from_p) && DECL_NAME (*to_p)) DECL_NAME (*from_p) -- 2.13.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-29 7:50 [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Pierre-Marie de Rodat @ 2017-05-29 8:05 ` Pierre-Marie de Rodat 2017-05-29 13:39 ` Pierre-Marie de Rodat 2017-05-30 12:11 ` Richard Biener 2017-05-30 11:59 ` [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Richard Biener 1 sibling, 2 replies; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-29 8:05 UTC (permalink / raw) To: gcc-patches; +Cc: Pierre-Marie de Rodat Hello, The DWARF back-end used to systematically ignore file-scope function and variable declarations. While this is justified in language like C/C++, where such declarations can appear in several translation units and thus bloat uselessly the debug info, this behavior is counter-productive in languages with a well-defined module system. Specifically, it prevents the description of imported entities, that belong to foreign languages, making them unavailable from debuggers. Take for instance: package C_Binding is function My_C_Function (I : Integer) return Integer; pragma Import (C, My_C_Function, "my_c_function"); end C_Binding; This makes available for Ada programs the C function "my_c_function" under the following name: C_Binding.My_C_Function. When GCC compiles it, though, it is represented as a FUNCTION_DECL node with DECL_EXTERNAL set and a null DECL_INITIAL, which used to be discarded unconditionally in the DWARF back-end. This patch introduces a new DECL language hook: emit_debug_info_for_decl_p, which the DWARF back-end uses to determine whether it should emit debug info for some declaration. This makes it possible for front-ends to decide the appropriate behavior. This patch also updates the Ada front-end to override this hook, so that declarations such as the above do generate debugging information. Bootstrapped and reg-tested on x86_64-linux. Ok to commit? Thank you in advance! gcc/ * langhooks.h (lang_hooks_for_decls::emit_debug_info_for_decl_p): New field. * langhooks-def.h (LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P): New macro. * dwarf2out.c (gen_decl_die): Use the new hook to determine whether to ignore file-scope declarations. (dwarf2out_early_global_decl): Likewise. (dwaf2out_decl): Likewise. gcc/ada * gcc-interface/ada-tree.h (DECL_FUNCTION_IS_DEF): New macro. * gcc-interface/misc.c (gnat_emit_debug_info_for_decl_p): New function. (LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P): Override macro. * gcc-interface/trans.c (Compilation_Unit_to_gnu): Tag the elaboration procedure as a definition. (Subprogram_Body_to_gnu): Tag the subprogram as a definition. * gcc-interface/decl.c (gnat_to_gnu_entity): Tag declarations of imported subprograms for the current compilation unit as definitions. Disable debug info for references to variables. * gcc-interface/utils.c (create_subprog_decl): Add a DEFINITION parameter. If it is true, tag the function as a definition. Update all callers. (gnat_pushdecl): Add external DECLs that are not built-in functions to their binding scope. (gnat_write_global_declarations): Emit debug info for imported functions. Filter out external variables for which debug info is disabled. * gcc-interface/gigi.c (create_subprog_decl): Update declaration. git-svn-id: svn+ssh://svn.us.adacore.com/Dev/trunk/gcc-interfaces@328405 f8352e7e-cb20-0410-8ce7-b5d9e71c585c --- gcc/ada/gcc-interface/ada-tree.h | 7 +++++- gcc/ada/gcc-interface/decl.c | 19 +++++++++------ gcc/ada/gcc-interface/gigi.h | 5 +++- gcc/ada/gcc-interface/misc.c | 11 +++++++++ gcc/ada/gcc-interface/trans.c | 52 ++++++++++++++++++++++++---------------- gcc/ada/gcc-interface/utils.c | 34 +++++++++++++++++++------- gcc/dwarf2out.c | 13 ++++++---- gcc/langhooks-def.h | 2 ++ gcc/langhooks.h | 9 +++++++ 9 files changed, 109 insertions(+), 43 deletions(-) diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h index a3d38b1b22e..511a0bd8173 100644 --- a/gcc/ada/gcc-interface/ada-tree.h +++ b/gcc/ada/gcc-interface/ada-tree.h @@ -6,7 +6,7 @@ * * * C Header File * * * - * Copyright (C) 1992-2016, Free Software Foundation, Inc. * + * Copyright (C) 1992-2017, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -463,6 +463,11 @@ do { \ a discriminant of a discriminated type without default expression. */ #define DECL_INVARIANT_P(NODE) DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) +/* Nonzero in a FUNCTION_DECL if this is a definition, i.e. if it was created + by a call to gnat_to_gnu_entity with definition set to True. */ +#define DECL_FUNCTION_IS_DEF(NODE) \ + DECL_LANG_FLAG_4 (FUNCTION_DECL_CHECK (NODE)) + /* Nonzero in a VAR_DECL if it is a temporary created to hold the return value of a function call or 'reference to a function call. */ #define DECL_RETURN_VALUE_P(NODE) DECL_LANG_FLAG_5 (VAR_DECL_CHECK (NODE)) diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index eab244e910c..83b9d0749fe 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1392,7 +1392,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (create_concat_name (gnat_entity, "ALIGN"), NULL_TREE, gnu_new_type, NULL_TREE, false, false, false, false, false, - true, debug_info_p, NULL, gnat_entity); + true, debug_info_p && definition, NULL, + gnat_entity); /* Initialize the aligned field if we have an initializer. */ if (gnu_expr) @@ -1441,7 +1442,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) NULL_TREE, gnu_type, gnu_expr, const_flag, Is_Public (gnat_entity), imported_p || !definition, static_flag, - volatile_flag, true, debug_info_p, + volatile_flag, true, + debug_info_p && definition, NULL, gnat_entity); gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_unc_var); TREE_CONSTANT (gnu_expr) = 1; @@ -1492,8 +1494,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, gnu_expr, const_flag, Is_Public (gnat_entity), imported_p || !definition, static_flag, - volatile_flag, artificial_p, debug_info_p, - attr_list, gnat_entity, !renamed_obj); + volatile_flag, artificial_p, + debug_info_p && definition, attr_list, + gnat_entity, !renamed_obj); DECL_BY_REF_P (gnu_decl) = used_by_ref; DECL_POINTS_TO_READONLY_P (gnu_decl) = used_by_ref && inner_const_flag; DECL_CAN_NEVER_BE_NULL_P (gnu_decl) = Can_Never_Be_Null (gnat_entity); @@ -1545,8 +1548,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, gnu_expr, true, Is_Public (gnat_entity), !definition, static_flag, volatile_flag, - artificial_p, debug_info_p, attr_list, - gnat_entity, false); + artificial_p, debug_info_p && definition, + attr_list, gnat_entity, false); SET_DECL_CONST_CORRESPONDING_VAR (gnu_decl, gnu_corr_var); } @@ -4083,7 +4086,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) gnu_type, gnu_param_list, inline_status, public_flag, extern_flag, artificial_p, - debug_info_p, attr_list, gnat_entity); + debug_info_p, + definition && imported_p, attr_list, + gnat_entity); DECL_STUBBED_P (gnu_decl) = (Convention (gnat_entity) == Convention_Stubbed); diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index b1fb34ad620..0e25b6129a3 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -720,6 +720,8 @@ extern tree create_label_decl (tree name, Node_Id gnat_node); DEBUG_INFO_P is true if we need to write debug information for it. + DEFINITION is true if the subprogram is to be considered as a definition. + ATTR_LIST is the list of attributes to be attached to the subprogram. GNAT_NODE is used for the position of the decl. */ @@ -728,7 +730,8 @@ extern tree create_subprog_decl (tree name, tree asm_name, tree type, enum inline_status_t inline_status, bool public_flag, bool extern_flag, bool artificial_p, bool debug_info_p, - struct attrib *attr_list, Node_Id gnat_node); + bool definition, struct attrib *attr_list, + Node_Id gnat_node); /* Given a subprogram declaration DECL, its assembler name and its type, finish constructing the subprogram declaration from ASM_NAME and TYPE. */ diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 18c825ca13e..cd0467ef8d9 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -1348,6 +1348,15 @@ gnat_eh_personality (void) return gnat_eh_personality_decl; } +/* Given DECL, which is a reference (we don't have a definition for it in this + compilation unit), return whether we should emit debug info for it. */ + +static bool +gnat_emit_debug_info_for_decl_p (tree decl) +{ + return TREE_CODE (decl) != FUNCTION_DECL || DECL_FUNCTION_IS_DEF (decl); +} + /* Initialize language-specific bits of tree_contains_struct. */ static void @@ -1451,6 +1460,8 @@ get_lang_specific (tree node) #define LANG_HOOKS_DEEP_UNSHARING true #undef LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS #define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS true +#undef LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P +#define LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P gnat_emit_debug_info_for_decl_p struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 2542626d0ca..79d099538c9 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -398,7 +398,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_malloc"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); DECL_IS_MALLOC (malloc_decl) = 1; ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); @@ -406,7 +406,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_free"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); ftype = build_function_type_list (ptr_type_node, ptr_type_node, sizetype, NULL_TREE); @@ -414,7 +414,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_realloc"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); /* This is used for 64-bit multiplication with overflow checking. */ int64_type = gnat_type_for_size (64, 0); @@ -423,7 +423,7 @@ gigi (Node_Id gnat_root, build_function_type_list (int64_type, int64_type, int64_type, NULL_TREE), NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); /* Name of the _Parent field in tagged record types. */ parent_name_id = get_identifier (Get_Name_String (Name_uParent)); @@ -446,21 +446,21 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("system__soft_links__get_jmpbuf_address_soft"), NULL_TREE, build_function_type_list (jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); set_jmpbuf_decl = create_subprog_decl (get_identifier ("system__soft_links__set_jmpbuf_address_soft"), NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); get_excptr_decl = create_subprog_decl (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE, build_function_type_list (build_pointer_type (except_type_node), NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); not_handled_by_others_decl = get_identifier ("not_handled_by_others"); for (t = TYPE_FIELDS (except_type_node); t; t = DECL_CHAIN (t)) @@ -478,7 +478,7 @@ gigi (Node_Id gnat_root, (get_identifier ("__builtin_setjmp"), NULL_TREE, build_function_type_list (integer_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); DECL_BUILT_IN_CLASS (setjmp_decl) = BUILT_IN_NORMAL; DECL_FUNCTION_CODE (setjmp_decl) = BUILT_IN_SETJMP; @@ -488,7 +488,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__builtin_update_setjmp_buf"), NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); DECL_BUILT_IN_CLASS (update_setjmp_buf_decl) = BUILT_IN_NORMAL; DECL_FUNCTION_CODE (update_setjmp_buf_decl) = BUILT_IN_UPDATE_SETJMP_BUF; @@ -500,14 +500,14 @@ gigi (Node_Id gnat_root, raise_nodefer_decl = create_subprog_decl (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE, ftype, - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); set_exception_parameter_decl = create_subprog_decl (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE, build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); /* Hooks to call when entering/leaving an exception handler. */ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); @@ -515,26 +515,30 @@ gigi (Node_Id gnat_root, begin_handler_decl = create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* __gnat_begin_handler is a dummy procedure. */ TREE_NOTHROW (begin_handler_decl) = 1; end_handler_decl = create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); unhandled_except_decl = create_subprog_decl (get_identifier ("__gnat_unhandled_except_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* Indicate that it never returns. */ ftype = build_qualified_type (ftype, TYPE_QUAL_VOLATILE); reraise_zcx_decl = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* Dummy objects to materialize "others" and "all others" in the exception tables. These are exported by a-exexpr-gcc.adb, so see this unit for @@ -573,7 +577,8 @@ gigi (Node_Id gnat_root, tree decl = create_subprog_decl (get_identifier ("__gnat_last_chance_handler"), NULL_TREE, ftype, - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, + Empty); for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++) gnat_raise_decls[i] = decl; } @@ -739,7 +744,7 @@ build_raise_check (int check, enum exception_info_kind kind) result = create_subprog_decl (get_identifier (Name_Buffer), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); return result; } @@ -3745,6 +3750,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) = gnat_to_gnu_entity (gnat_subprog_id, NULL_TREE, Acts_As_Spec (gnat_node) && !present_gnu_tree (gnat_subprog_id)); + DECL_FUNCTION_IS_DEF (gnu_subprog_decl) = true; gnu_result_decl = DECL_RESULT (gnu_subprog_decl); gnu_subprog_type = TREE_TYPE (gnu_subprog_decl); gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type); @@ -5417,12 +5423,15 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) const Entity_Id gnat_unit_entity = Defining_Entity (gnat_unit); Entity_Id gnat_entity; Node_Id gnat_pragma; - /* Make the decl for the elaboration procedure. */ + /* Make the decl for the elaboration procedure. Emit debug info for it, so + that users can break into their elaboration code in debuggers. Kludge: + don't consider it as a definition so that we have a line map for its body, + but no subprogram description in debug info. */ tree gnu_elab_proc_decl = create_subprog_decl (create_concat_name (gnat_unit_entity, body_p ? "elabb" : "elabs"), NULL_TREE, void_ftype, NULL_TREE, - is_disabled, true, false, true, true, NULL, gnat_unit); + is_disabled, true, false, true, true, false, NULL, gnat_unit); struct elab_info *info; vec_safe_push (gnu_elab_proc_stack, gnu_elab_proc_decl); @@ -6453,7 +6462,7 @@ gnat_to_gnu (Node_Id gnat_node) gnu_prefix = gnat_to_gnu (gnat_prefix); gnu_prefix = maybe_implicit_deref (gnu_prefix); } - + gnu_result = build_component_ref (gnu_prefix, gnu_field, (Nkind (Parent (gnat_node)) @@ -6484,7 +6493,8 @@ gnat_to_gnu (Node_Id gnat_node) (Entity (Prefix (gnat_node)), attr == Attr_Elab_Body ? "elabb" : "elabs"), NULL_TREE, void_ftype, NULL_TREE, is_disabled, - true, true, true, true, NULL, gnat_node); + true, true, true, true, false, NULL, + gnat_node); gnu_result = Attribute_to_gnu (gnat_node, &gnu_result_type, attr); } diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index b8c5d3d31f6..af53edcfa3f 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -763,11 +763,13 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) if (!(TREE_CODE (decl) == TYPE_DECL && TREE_CODE (TREE_TYPE (decl)) == UNCONSTRAINED_ARRAY_TYPE)) { - if (DECL_EXTERNAL (decl)) - { - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) - vec_safe_push (builtin_decls, decl); - } + /* External declarations must go to the binding level they belong to. + This will make corresponding imported entities are available in the + debugger at the proper time. */ + if (DECL_EXTERNAL (decl) + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_BUILT_IN (decl)) + vec_safe_push (builtin_decls, decl); else if (global_bindings_p ()) vec_safe_push (global_decls, decl); else @@ -3189,6 +3191,8 @@ create_label_decl (tree name, Node_Id gnat_node) DEBUG_INFO_P is true if we need to write debug information for it. + DEFINITION is true if the subprogram is to be considered as a definition. + ATTR_LIST is the list of attributes to be attached to the subprogram. GNAT_NODE is used for the position of the decl. */ @@ -3197,7 +3201,8 @@ tree create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, enum inline_status_t inline_status, bool public_flag, bool extern_flag, bool artificial_p, bool debug_info_p, - struct attrib *attr_list, Node_Id gnat_node) + bool definition, struct attrib *attr_list, + Node_Id gnat_node) { tree subprog_decl = build_decl (input_location, FUNCTION_DECL, name, type); DECL_ARGUMENTS (subprog_decl) = param_decl_list; @@ -3208,6 +3213,8 @@ create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, if (!debug_info_p) DECL_IGNORED_P (subprog_decl) = 1; + if (definition) + DECL_FUNCTION_IS_DEF (subprog_decl) = 1; switch (inline_status) { @@ -5523,10 +5530,21 @@ gnat_write_global_declarations (void) if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter)) debug_hooks->type_decl (iter, false); + /* Output imported functions. */ + FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) + if (TREE_CODE (iter) == FUNCTION_DECL + && DECL_EXTERNAL (iter) + && DECL_INITIAL (iter) == NULL + && !DECL_IGNORED_P (iter)) + debug_hooks->early_global_decl (iter); + /* Then output the global variables. We need to do that after the debug - information for global types is emitted so that they are finalized. */ + information for global types is emitted so that they are finalized. Skip + external global variables, unless we need to emit debug info for them: + this is useful for imported variables, for instance. */ FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) - if (TREE_CODE (iter) == VAR_DECL) + if (TREE_CODE (iter) == VAR_DECL + && (!DECL_EXTERNAL (iter) || !DECL_IGNORED_P (iter))) rest_of_decl_compilation (iter, true, 0); /* Output the imported modules/declarations. In GNAT, these are only diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5ff45eb4efd..e2a7f546034 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -25271,7 +25271,8 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, if (DECL_INITIAL (decl_or_origin) == NULL_TREE && DECL_FILE_SCOPE_P (decl_or_origin) && (current_function_decl == NULL_TREE - || DECL_ARTIFICIAL (decl_or_origin))) + || DECL_ARTIFICIAL (decl_or_origin)) + && !lang_hooks.decls.emit_debug_info_for_decl_p (decl_or_origin)) break; #if 0 @@ -25478,9 +25479,10 @@ dwarf2out_early_global_decl (tree decl) tree save_fndecl = current_function_decl; if (TREE_CODE (decl) == FUNCTION_DECL) { - /* No cfun means the symbol has no body, so there's nothing - to emit. */ - if (!DECL_STRUCT_FUNCTION (decl)) + /* Unless we are asked to emit debug info for declarations, no cfun + means the symbol has no body, so there's nothing to emit. */ + if (!DECL_STRUCT_FUNCTION (decl) + && !lang_hooks.decls.emit_debug_info_for_decl_p (decl)) goto early_decl_exit; /* For nested functions, make sure we have DIEs for the parents first @@ -25770,7 +25772,8 @@ dwarf2out_decl (tree decl) where the inlined function is output in a different LTRANS unit or not at all. */ if (DECL_INITIAL (decl) == NULL_TREE - && ! DECL_ABSTRACT_P (decl)) + && ! DECL_ABSTRACT_P (decl) + && ! lang_hooks.decls.emit_debug_info_for_decl_p (decl)) return; /* If we're a nested function, initially use a parent of NULL; if we're diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index ea2006ccec5..e210e9e61ca 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -225,6 +225,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); /* Declaration hooks. */ #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p +#define LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P hook_bool_tree_false #define LANG_HOOKS_PUSHDECL pushdecl #define LANG_HOOKS_GETDECLS getdecls #define LANG_HOOKS_DECL_DWARF_ATTRIBUTE lhd_decl_dwarf_attribute @@ -247,6 +248,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); #define LANG_HOOKS_DECLS { \ LANG_HOOKS_GLOBAL_BINDINGS_P, \ + LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P, \ LANG_HOOKS_PUSHDECL, \ LANG_HOOKS_GETDECLS, \ LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index b2f0f922b89..27fd5638d21 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -181,6 +181,15 @@ struct lang_hooks_for_decls level, i.e. declared outside subprograms. */ bool (*global_bindings_p) (void); + /* Given some declaration, if this returns true, we should produce debug info + for it. We should not do this for languages with poor modules definition + like C/C++ because translation units make us process a lot of declarations + that are common to a lot of translation units, bloating the debug info. + However this is desirable in languages like Ada, where we know we must not + produce debug info for the declaration of functions that come from other + units (unless in special cases, like cross-unit inlining). */ + bool (*emit_debug_info_for_decl_p) (tree); + /* Function to add a decl to the current scope level. Takes one argument, a decl to add. Returns that decl, or, if the same symbol is already declared, may return a different decl for that -- 2.13.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-29 8:05 ` [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only Pierre-Marie de Rodat @ 2017-05-29 13:39 ` Pierre-Marie de Rodat 2017-05-30 12:11 ` Richard Biener 1 sibling, 0 replies; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-29 13:39 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 237 bytes --] On 05/29/2017 09:50 AM, Pierre-Marie de Rodat wrote: > Bootstrapped and reg-tested on x86_64-linux. Ok to commit? Thank you in > advance! I just realized that I forgot to add the testcase: here it is, sorry! -- Pierre-Marie de Rodat [-- Attachment #2: debug11_pkg.adb --] [-- Type: text/x-adasrc, Size: 914 bytes --] -- { dg-options "-cargs -g -dA -margs" } -- { dg-final { scan-assembler "local_imported_func" } } -- { dg-final { scan-assembler "local_imported_var" } } -- { dg-final { scan-assembler "global_imported_func" } } -- { dg-final { scan-assembler "global_imported_var" } } -- { dg-final { scan-assembler-not "foreign_imported_func" } } -- { dg-final { scan-assembler-not "foreign_imported_var" } } with Debug11_Pkg2; package body Debug11_Pkg is procedure Dummy is Local_Imported_Var : Integer; pragma Import (C, Local_Imported_Var, "imported_var"); function Local_Imported_Func return Integer; pragma Import (C, Local_Imported_Func, "imported_func"); begin Local_Imported_Var := Local_Imported_Func; Global_Imported_Var := Global_Imported_Func; Debug11_Pkg2.Foreign_Imported_Var := Debug11_Pkg2.Foreign_Imported_Func; end Dummy; end Debug11_Pkg; [-- Attachment #3: debug11_pkg.ads --] [-- Type: text/x-adasrc, Size: 267 bytes --] package Debug11_Pkg is Global_Imported_Var : Integer; pragma Import (C, Global_Imported_Var, "imported_var"); function Global_Imported_Func return Integer; pragma Import (C, Global_Imported_Func, "imported_func"); procedure Dummy; end Debug11_Pkg; [-- Attachment #4: debug11_pkg2.ads --] [-- Type: text/x-adasrc, Size: 252 bytes --] package Debug11_Pkg2 is Foreign_Imported_Var : Integer; pragma Import (C, Foreign_Imported_Var, "imported_var"); function Foreign_Imported_Func return Integer; pragma Import (C, Foreign_Imported_Func, "imported_func"); end Debug11_Pkg2; ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-29 8:05 ` [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only Pierre-Marie de Rodat 2017-05-29 13:39 ` Pierre-Marie de Rodat @ 2017-05-30 12:11 ` Richard Biener 2017-05-30 15:51 ` Pierre-Marie de Rodat 1 sibling, 1 reply; 14+ messages in thread From: Richard Biener @ 2017-05-30 12:11 UTC (permalink / raw) To: Pierre-Marie de Rodat; +Cc: GCC Patches On Mon, May 29, 2017 at 9:50 AM, Pierre-Marie de Rodat <derodat@adacore.com> wrote: > Hello, > > The DWARF back-end used to systematically ignore file-scope function and > variable declarations. While this is justified in language like C/C++, > where such declarations can appear in several translation units and thus > bloat uselessly the debug info, this behavior is counter-productive in > languages with a well-defined module system. Specifically, it prevents > the description of imported entities, that belong to foreign languages, > making them unavailable from debuggers. > > Take for instance: > > package C_Binding is > function My_C_Function (I : Integer) return Integer; > pragma Import (C, My_C_Function, "my_c_function"); > end C_Binding; > > This makes available for Ada programs the C function "my_c_function" > under the following name: C_Binding.My_C_Function. When GCC compiles > it, though, it is represented as a FUNCTION_DECL node with DECL_EXTERNAL > set and a null DECL_INITIAL, which used to be discarded unconditionally > in the DWARF back-end. > > This patch introduces a new DECL language hook: > emit_debug_info_for_decl_p, which the DWARF back-end uses to determine > whether it should emit debug info for some declaration. This makes it > possible for front-ends to decide the appropriate behavior. > > This patch also updates the Ada front-end to override this hook, so that > declarations such as the above do generate debugging information. > > Bootstrapped and reg-tested on x86_64-linux. Ok to commit? Thank you in > advance! I think the issue is unfortunate in the C frontend as well. So I believe we can go without a new langhook and instead make sure dwarf2out_early_global_decl is not called for uninteresting decls (which means eventually pushing the call(s) of that hook more towards the FEs). For C/C++ it would be reasonable to output debug info for external declarations that end up being used for example. Richard. > gcc/ > * langhooks.h > (lang_hooks_for_decls::emit_debug_info_for_decl_p): New field. > * langhooks-def.h > (LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P): New macro. > * dwarf2out.c (gen_decl_die): Use the new hook to determine > whether to ignore file-scope declarations. > (dwarf2out_early_global_decl): Likewise. > (dwaf2out_decl): Likewise. > > gcc/ada > * gcc-interface/ada-tree.h (DECL_FUNCTION_IS_DEF): New macro. > * gcc-interface/misc.c (gnat_emit_debug_info_for_decl_p): New > function. > (LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P): Override macro. > * gcc-interface/trans.c (Compilation_Unit_to_gnu): Tag the > elaboration procedure as a definition. > (Subprogram_Body_to_gnu): Tag the subprogram as a definition. > * gcc-interface/decl.c (gnat_to_gnu_entity): Tag declarations of > imported subprograms for the current compilation unit as > definitions. Disable debug info for references to variables. > * gcc-interface/utils.c (create_subprog_decl): Add a DEFINITION > parameter. If it is true, tag the function as a definition. > Update all callers. > (gnat_pushdecl): Add external DECLs that are not built-in > functions to their binding scope. > (gnat_write_global_declarations): Emit debug info for imported > functions. Filter out external variables for which debug info > is disabled. > * gcc-interface/gigi.c (create_subprog_decl): Update > declaration. > > git-svn-id: svn+ssh://svn.us.adacore.com/Dev/trunk/gcc-interfaces@328405 f8352e7e-cb20-0410-8ce7-b5d9e71c585c > --- > gcc/ada/gcc-interface/ada-tree.h | 7 +++++- > gcc/ada/gcc-interface/decl.c | 19 +++++++++------ > gcc/ada/gcc-interface/gigi.h | 5 +++- > gcc/ada/gcc-interface/misc.c | 11 +++++++++ > gcc/ada/gcc-interface/trans.c | 52 ++++++++++++++++++++++++---------------- > gcc/ada/gcc-interface/utils.c | 34 +++++++++++++++++++------- > gcc/dwarf2out.c | 13 ++++++---- > gcc/langhooks-def.h | 2 ++ > gcc/langhooks.h | 9 +++++++ > 9 files changed, 109 insertions(+), 43 deletions(-) > > diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h > index a3d38b1b22e..511a0bd8173 100644 > --- a/gcc/ada/gcc-interface/ada-tree.h > +++ b/gcc/ada/gcc-interface/ada-tree.h > @@ -6,7 +6,7 @@ > * * > * C Header File * > * * > - * Copyright (C) 1992-2016, Free Software Foundation, Inc. * > + * Copyright (C) 1992-2017, Free Software Foundation, Inc. * > * * > * GNAT is free software; you can redistribute it and/or modify it under * > * terms of the GNU General Public License as published by the Free Soft- * > @@ -463,6 +463,11 @@ do { \ > a discriminant of a discriminated type without default expression. */ > #define DECL_INVARIANT_P(NODE) DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) > > +/* Nonzero in a FUNCTION_DECL if this is a definition, i.e. if it was created > + by a call to gnat_to_gnu_entity with definition set to True. */ > +#define DECL_FUNCTION_IS_DEF(NODE) \ > + DECL_LANG_FLAG_4 (FUNCTION_DECL_CHECK (NODE)) > + > /* Nonzero in a VAR_DECL if it is a temporary created to hold the return > value of a function call or 'reference to a function call. */ > #define DECL_RETURN_VALUE_P(NODE) DECL_LANG_FLAG_5 (VAR_DECL_CHECK (NODE)) > diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c > index eab244e910c..83b9d0749fe 100644 > --- a/gcc/ada/gcc-interface/decl.c > +++ b/gcc/ada/gcc-interface/decl.c > @@ -1392,7 +1392,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) > = create_var_decl (create_concat_name (gnat_entity, "ALIGN"), > NULL_TREE, gnu_new_type, NULL_TREE, > false, false, false, false, false, > - true, debug_info_p, NULL, gnat_entity); > + true, debug_info_p && definition, NULL, > + gnat_entity); > > /* Initialize the aligned field if we have an initializer. */ > if (gnu_expr) > @@ -1441,7 +1442,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) > NULL_TREE, gnu_type, gnu_expr, > const_flag, Is_Public (gnat_entity), > imported_p || !definition, static_flag, > - volatile_flag, true, debug_info_p, > + volatile_flag, true, > + debug_info_p && definition, > NULL, gnat_entity); > gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_unc_var); > TREE_CONSTANT (gnu_expr) = 1; > @@ -1492,8 +1494,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) > = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, > gnu_expr, const_flag, Is_Public (gnat_entity), > imported_p || !definition, static_flag, > - volatile_flag, artificial_p, debug_info_p, > - attr_list, gnat_entity, !renamed_obj); > + volatile_flag, artificial_p, > + debug_info_p && definition, attr_list, > + gnat_entity, !renamed_obj); > DECL_BY_REF_P (gnu_decl) = used_by_ref; > DECL_POINTS_TO_READONLY_P (gnu_decl) = used_by_ref && inner_const_flag; > DECL_CAN_NEVER_BE_NULL_P (gnu_decl) = Can_Never_Be_Null (gnat_entity); > @@ -1545,8 +1548,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) > = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, > gnu_expr, true, Is_Public (gnat_entity), > !definition, static_flag, volatile_flag, > - artificial_p, debug_info_p, attr_list, > - gnat_entity, false); > + artificial_p, debug_info_p && definition, > + attr_list, gnat_entity, false); > > SET_DECL_CONST_CORRESPONDING_VAR (gnu_decl, gnu_corr_var); > } > @@ -4083,7 +4086,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) > gnu_type, gnu_param_list, > inline_status, public_flag, > extern_flag, artificial_p, > - debug_info_p, attr_list, gnat_entity); > + debug_info_p, > + definition && imported_p, attr_list, > + gnat_entity); > > DECL_STUBBED_P (gnu_decl) > = (Convention (gnat_entity) == Convention_Stubbed); > diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h > index b1fb34ad620..0e25b6129a3 100644 > --- a/gcc/ada/gcc-interface/gigi.h > +++ b/gcc/ada/gcc-interface/gigi.h > @@ -720,6 +720,8 @@ extern tree create_label_decl (tree name, Node_Id gnat_node); > > DEBUG_INFO_P is true if we need to write debug information for it. > > + DEFINITION is true if the subprogram is to be considered as a definition. > + > ATTR_LIST is the list of attributes to be attached to the subprogram. > > GNAT_NODE is used for the position of the decl. */ > @@ -728,7 +730,8 @@ extern tree create_subprog_decl (tree name, tree asm_name, tree type, > enum inline_status_t inline_status, > bool public_flag, bool extern_flag, > bool artificial_p, bool debug_info_p, > - struct attrib *attr_list, Node_Id gnat_node); > + bool definition, struct attrib *attr_list, > + Node_Id gnat_node); > > /* Given a subprogram declaration DECL, its assembler name and its type, > finish constructing the subprogram declaration from ASM_NAME and TYPE. */ > diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c > index 18c825ca13e..cd0467ef8d9 100644 > --- a/gcc/ada/gcc-interface/misc.c > +++ b/gcc/ada/gcc-interface/misc.c > @@ -1348,6 +1348,15 @@ gnat_eh_personality (void) > return gnat_eh_personality_decl; > } > > +/* Given DECL, which is a reference (we don't have a definition for it in this > + compilation unit), return whether we should emit debug info for it. */ > + > +static bool > +gnat_emit_debug_info_for_decl_p (tree decl) > +{ > + return TREE_CODE (decl) != FUNCTION_DECL || DECL_FUNCTION_IS_DEF (decl); > +} > + > /* Initialize language-specific bits of tree_contains_struct. */ > > static void > @@ -1451,6 +1460,8 @@ get_lang_specific (tree node) > #define LANG_HOOKS_DEEP_UNSHARING true > #undef LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS > #define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS true > +#undef LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P > +#define LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P gnat_emit_debug_info_for_decl_p > > struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; > > diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c > index 2542626d0ca..79d099538c9 100644 > --- a/gcc/ada/gcc-interface/trans.c > +++ b/gcc/ada/gcc-interface/trans.c > @@ -398,7 +398,7 @@ gigi (Node_Id gnat_root, > = create_subprog_decl (get_identifier ("__gnat_malloc"), NULL_TREE, > ftype, > NULL_TREE, is_disabled, true, true, true, false, > - NULL, Empty); > + false, NULL, Empty); > DECL_IS_MALLOC (malloc_decl) = 1; > > ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); > @@ -406,7 +406,7 @@ gigi (Node_Id gnat_root, > = create_subprog_decl (get_identifier ("__gnat_free"), NULL_TREE, > ftype, > NULL_TREE, is_disabled, true, true, true, false, > - NULL, Empty); > + false, NULL, Empty); > > ftype = build_function_type_list (ptr_type_node, ptr_type_node, sizetype, > NULL_TREE); > @@ -414,7 +414,7 @@ gigi (Node_Id gnat_root, > = create_subprog_decl (get_identifier ("__gnat_realloc"), NULL_TREE, > ftype, > NULL_TREE, is_disabled, true, true, true, false, > - NULL, Empty); > + false, NULL, Empty); > > /* This is used for 64-bit multiplication with overflow checking. */ > int64_type = gnat_type_for_size (64, 0); > @@ -423,7 +423,7 @@ gigi (Node_Id gnat_root, > build_function_type_list (int64_type, int64_type, > int64_type, NULL_TREE), > NULL_TREE, is_disabled, true, true, true, false, > - NULL, Empty); > + false, NULL, Empty); > > /* Name of the _Parent field in tagged record types. */ > parent_name_id = get_identifier (Get_Name_String (Name_uParent)); > @@ -446,21 +446,21 @@ gigi (Node_Id gnat_root, > = create_subprog_decl > (get_identifier ("system__soft_links__get_jmpbuf_address_soft"), > NULL_TREE, build_function_type_list (jmpbuf_ptr_type, NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > > set_jmpbuf_decl > = create_subprog_decl > (get_identifier ("system__soft_links__set_jmpbuf_address_soft"), > NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type, > NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > > get_excptr_decl > = create_subprog_decl > (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE, > build_function_type_list (build_pointer_type (except_type_node), > NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > > not_handled_by_others_decl = get_identifier ("not_handled_by_others"); > for (t = TYPE_FIELDS (except_type_node); t; t = DECL_CHAIN (t)) > @@ -478,7 +478,7 @@ gigi (Node_Id gnat_root, > (get_identifier ("__builtin_setjmp"), NULL_TREE, > build_function_type_list (integer_type_node, jmpbuf_ptr_type, > NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > DECL_BUILT_IN_CLASS (setjmp_decl) = BUILT_IN_NORMAL; > DECL_FUNCTION_CODE (setjmp_decl) = BUILT_IN_SETJMP; > > @@ -488,7 +488,7 @@ gigi (Node_Id gnat_root, > = create_subprog_decl > (get_identifier ("__builtin_update_setjmp_buf"), NULL_TREE, > build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > DECL_BUILT_IN_CLASS (update_setjmp_buf_decl) = BUILT_IN_NORMAL; > DECL_FUNCTION_CODE (update_setjmp_buf_decl) = BUILT_IN_UPDATE_SETJMP_BUF; > > @@ -500,14 +500,14 @@ gigi (Node_Id gnat_root, > raise_nodefer_decl > = create_subprog_decl > (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE, ftype, > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > > set_exception_parameter_decl > = create_subprog_decl > (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE, > build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, > NULL_TREE), > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); > > /* Hooks to call when entering/leaving an exception handler. */ > ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); > @@ -515,26 +515,30 @@ gigi (Node_Id gnat_root, > begin_handler_decl > = create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE, > ftype, NULL_TREE, > - is_disabled, true, true, true, false, NULL, Empty); > + is_disabled, true, true, true, false, false, NULL, > + Empty); > /* __gnat_begin_handler is a dummy procedure. */ > TREE_NOTHROW (begin_handler_decl) = 1; > > end_handler_decl > = create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE, > ftype, NULL_TREE, > - is_disabled, true, true, true, false, NULL, Empty); > + is_disabled, true, true, true, false, false, NULL, > + Empty); > > unhandled_except_decl > = create_subprog_decl (get_identifier ("__gnat_unhandled_except_handler"), > NULL_TREE, ftype, NULL_TREE, > - is_disabled, true, true, true, false, NULL, Empty); > + is_disabled, true, true, true, false, false, NULL, > + Empty); > > /* Indicate that it never returns. */ > ftype = build_qualified_type (ftype, TYPE_QUAL_VOLATILE); > reraise_zcx_decl > = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE, > ftype, NULL_TREE, > - is_disabled, true, true, true, false, NULL, Empty); > + is_disabled, true, true, true, false, false, NULL, > + Empty); > > /* Dummy objects to materialize "others" and "all others" in the exception > tables. These are exported by a-exexpr-gcc.adb, so see this unit for > @@ -573,7 +577,8 @@ gigi (Node_Id gnat_root, > tree decl > = create_subprog_decl > (get_identifier ("__gnat_last_chance_handler"), NULL_TREE, ftype, > - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); > + NULL_TREE, is_disabled, true, true, true, false, false, NULL, > + Empty); > for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++) > gnat_raise_decls[i] = decl; > } > @@ -739,7 +744,7 @@ build_raise_check (int check, enum exception_info_kind kind) > result > = create_subprog_decl (get_identifier (Name_Buffer), NULL_TREE, ftype, > NULL_TREE, is_disabled, true, true, true, false, > - NULL, Empty); > + false, NULL, Empty); > > return result; > } > @@ -3745,6 +3750,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) > = gnat_to_gnu_entity (gnat_subprog_id, NULL_TREE, > Acts_As_Spec (gnat_node) > && !present_gnu_tree (gnat_subprog_id)); > + DECL_FUNCTION_IS_DEF (gnu_subprog_decl) = true; > gnu_result_decl = DECL_RESULT (gnu_subprog_decl); > gnu_subprog_type = TREE_TYPE (gnu_subprog_decl); > gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type); > @@ -5417,12 +5423,15 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) > const Entity_Id gnat_unit_entity = Defining_Entity (gnat_unit); > Entity_Id gnat_entity; > Node_Id gnat_pragma; > - /* Make the decl for the elaboration procedure. */ > + /* Make the decl for the elaboration procedure. Emit debug info for it, so > + that users can break into their elaboration code in debuggers. Kludge: > + don't consider it as a definition so that we have a line map for its body, > + but no subprogram description in debug info. */ > tree gnu_elab_proc_decl > = create_subprog_decl > (create_concat_name (gnat_unit_entity, body_p ? "elabb" : "elabs"), > NULL_TREE, void_ftype, NULL_TREE, > - is_disabled, true, false, true, true, NULL, gnat_unit); > + is_disabled, true, false, true, true, false, NULL, gnat_unit); > struct elab_info *info; > > vec_safe_push (gnu_elab_proc_stack, gnu_elab_proc_decl); > @@ -6453,7 +6462,7 @@ gnat_to_gnu (Node_Id gnat_node) > gnu_prefix = gnat_to_gnu (gnat_prefix); > gnu_prefix = maybe_implicit_deref (gnu_prefix); > } > - > + > gnu_result > = build_component_ref (gnu_prefix, gnu_field, > (Nkind (Parent (gnat_node)) > @@ -6484,7 +6493,8 @@ gnat_to_gnu (Node_Id gnat_node) > (Entity (Prefix (gnat_node)), > attr == Attr_Elab_Body ? "elabb" : "elabs"), > NULL_TREE, void_ftype, NULL_TREE, is_disabled, > - true, true, true, true, NULL, gnat_node); > + true, true, true, true, false, NULL, > + gnat_node); > > gnu_result = Attribute_to_gnu (gnat_node, &gnu_result_type, attr); > } > diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c > index b8c5d3d31f6..af53edcfa3f 100644 > --- a/gcc/ada/gcc-interface/utils.c > +++ b/gcc/ada/gcc-interface/utils.c > @@ -763,11 +763,13 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) > if (!(TREE_CODE (decl) == TYPE_DECL > && TREE_CODE (TREE_TYPE (decl)) == UNCONSTRAINED_ARRAY_TYPE)) > { > - if (DECL_EXTERNAL (decl)) > - { > - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) > - vec_safe_push (builtin_decls, decl); > - } > + /* External declarations must go to the binding level they belong to. > + This will make corresponding imported entities are available in the > + debugger at the proper time. */ > + if (DECL_EXTERNAL (decl) > + && TREE_CODE (decl) == FUNCTION_DECL > + && DECL_BUILT_IN (decl)) > + vec_safe_push (builtin_decls, decl); > else if (global_bindings_p ()) > vec_safe_push (global_decls, decl); > else > @@ -3189,6 +3191,8 @@ create_label_decl (tree name, Node_Id gnat_node) > > DEBUG_INFO_P is true if we need to write debug information for it. > > + DEFINITION is true if the subprogram is to be considered as a definition. > + > ATTR_LIST is the list of attributes to be attached to the subprogram. > > GNAT_NODE is used for the position of the decl. */ > @@ -3197,7 +3201,8 @@ tree > create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, > enum inline_status_t inline_status, bool public_flag, > bool extern_flag, bool artificial_p, bool debug_info_p, > - struct attrib *attr_list, Node_Id gnat_node) > + bool definition, struct attrib *attr_list, > + Node_Id gnat_node) > { > tree subprog_decl = build_decl (input_location, FUNCTION_DECL, name, type); > DECL_ARGUMENTS (subprog_decl) = param_decl_list; > @@ -3208,6 +3213,8 @@ create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, > > if (!debug_info_p) > DECL_IGNORED_P (subprog_decl) = 1; > + if (definition) > + DECL_FUNCTION_IS_DEF (subprog_decl) = 1; > > switch (inline_status) > { > @@ -5523,10 +5530,21 @@ gnat_write_global_declarations (void) > if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter)) > debug_hooks->type_decl (iter, false); > > + /* Output imported functions. */ > + FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) > + if (TREE_CODE (iter) == FUNCTION_DECL > + && DECL_EXTERNAL (iter) > + && DECL_INITIAL (iter) == NULL > + && !DECL_IGNORED_P (iter)) > + debug_hooks->early_global_decl (iter); > + > /* Then output the global variables. We need to do that after the debug > - information for global types is emitted so that they are finalized. */ > + information for global types is emitted so that they are finalized. Skip > + external global variables, unless we need to emit debug info for them: > + this is useful for imported variables, for instance. */ > FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) > - if (TREE_CODE (iter) == VAR_DECL) > + if (TREE_CODE (iter) == VAR_DECL > + && (!DECL_EXTERNAL (iter) || !DECL_IGNORED_P (iter))) > rest_of_decl_compilation (iter, true, 0); > > /* Output the imported modules/declarations. In GNAT, these are only > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c > index 5ff45eb4efd..e2a7f546034 100644 > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -25271,7 +25271,8 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, > if (DECL_INITIAL (decl_or_origin) == NULL_TREE > && DECL_FILE_SCOPE_P (decl_or_origin) > && (current_function_decl == NULL_TREE > - || DECL_ARTIFICIAL (decl_or_origin))) > + || DECL_ARTIFICIAL (decl_or_origin)) > + && !lang_hooks.decls.emit_debug_info_for_decl_p (decl_or_origin)) > break; > > #if 0 > @@ -25478,9 +25479,10 @@ dwarf2out_early_global_decl (tree decl) > tree save_fndecl = current_function_decl; > if (TREE_CODE (decl) == FUNCTION_DECL) > { > - /* No cfun means the symbol has no body, so there's nothing > - to emit. */ > - if (!DECL_STRUCT_FUNCTION (decl)) > + /* Unless we are asked to emit debug info for declarations, no cfun > + means the symbol has no body, so there's nothing to emit. */ > + if (!DECL_STRUCT_FUNCTION (decl) > + && !lang_hooks.decls.emit_debug_info_for_decl_p (decl)) > goto early_decl_exit; > > /* For nested functions, make sure we have DIEs for the parents first > @@ -25770,7 +25772,8 @@ dwarf2out_decl (tree decl) > where the inlined function is output in a different LTRANS unit > or not at all. */ > if (DECL_INITIAL (decl) == NULL_TREE > - && ! DECL_ABSTRACT_P (decl)) > + && ! DECL_ABSTRACT_P (decl) > + && ! lang_hooks.decls.emit_debug_info_for_decl_p (decl)) > return; > > /* If we're a nested function, initially use a parent of NULL; if we're > diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h > index ea2006ccec5..e210e9e61ca 100644 > --- a/gcc/langhooks-def.h > +++ b/gcc/langhooks-def.h > @@ -225,6 +225,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); > > /* Declaration hooks. */ > #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p > +#define LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P hook_bool_tree_false > #define LANG_HOOKS_PUSHDECL pushdecl > #define LANG_HOOKS_GETDECLS getdecls > #define LANG_HOOKS_DECL_DWARF_ATTRIBUTE lhd_decl_dwarf_attribute > @@ -247,6 +248,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); > > #define LANG_HOOKS_DECLS { \ > LANG_HOOKS_GLOBAL_BINDINGS_P, \ > + LANG_HOOKS_EMIT_DEBUG_INFO_FOR_DECL_P, \ > LANG_HOOKS_PUSHDECL, \ > LANG_HOOKS_GETDECLS, \ > LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \ > diff --git a/gcc/langhooks.h b/gcc/langhooks.h > index b2f0f922b89..27fd5638d21 100644 > --- a/gcc/langhooks.h > +++ b/gcc/langhooks.h > @@ -181,6 +181,15 @@ struct lang_hooks_for_decls > level, i.e. declared outside subprograms. */ > bool (*global_bindings_p) (void); > > + /* Given some declaration, if this returns true, we should produce debug info > + for it. We should not do this for languages with poor modules definition > + like C/C++ because translation units make us process a lot of declarations > + that are common to a lot of translation units, bloating the debug info. > + However this is desirable in languages like Ada, where we know we must not > + produce debug info for the declaration of functions that come from other > + units (unless in special cases, like cross-unit inlining). */ > + bool (*emit_debug_info_for_decl_p) (tree); > + > /* Function to add a decl to the current scope level. Takes one > argument, a decl to add. Returns that decl, or, if the same > symbol is already declared, may return a different decl for that > -- > 2.13.0 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-30 12:11 ` Richard Biener @ 2017-05-30 15:51 ` Pierre-Marie de Rodat 2017-05-31 7:37 ` Richard Biener 0 siblings, 1 reply; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-30 15:51 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches Thank you for your review, Richard. On 05/30/2017 01:59 PM, Richard Biener wrote: > I think the issue is unfortunate in the C frontend as well. So I believe we can > go without a new langhook and instead make sure dwarf2out_early_global_decl > is not called for uninteresting decls (which means eventually pushing the > call(s) of that hook more towards the FEs). It is called by rest_of_decl_compilation, which seems itself to be called a lot on FUNCTION_DECL nodes. Before I dive into this consequent change: this would lead for instance to add a parameter to rest_of_compilation to control whether it must call the early_global_decl hook, and then to update all callers accordingly. Is this what you actually have in mind? > For C/C++ it would be reasonable to output debug info for external declarations > that end up being used for example. I guess that could be done indeed. :-) -- Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-30 15:51 ` Pierre-Marie de Rodat @ 2017-05-31 7:37 ` Richard Biener 2017-05-31 9:12 ` Pierre-Marie de Rodat 0 siblings, 1 reply; 14+ messages in thread From: Richard Biener @ 2017-05-31 7:37 UTC (permalink / raw) To: Pierre-Marie de Rodat; +Cc: GCC Patches On Tue, May 30, 2017 at 5:47 PM, Pierre-Marie de Rodat <derodat@adacore.com> wrote: > Thank you for your review, Richard. > > On 05/30/2017 01:59 PM, Richard Biener wrote: >> >> I think the issue is unfortunate in the C frontend as well. So I believe >> we can >> go without a new langhook and instead make sure >> dwarf2out_early_global_decl >> is not called for uninteresting decls (which means eventually pushing the >> call(s) of that hook more towards the FEs). > > > It is called by rest_of_decl_compilation, which seems itself to be called a > lot on FUNCTION_DECL nodes. Before I dive into this consequent change: this > would lead for instance to add a parameter to rest_of_compilation to control > whether it must call the early_global_decl hook, and then to update all > callers accordingly. Is this what you actually have in mind? Actually for the bigger picture I'd refactor rest_of_decl_compilation, not calling it from the frontends but rely on finalize_decl/function. The missing part would then be calling the dwarf hook which should eventually be done at some of the places the frontends now call rest_of_decl_compliation. > >> For C/C++ it would be reasonable to output debug info for external >> declarations >> that end up being used for example. > > > I guess that could be done indeed. :-) But for an easier way (you might still explore the above ;)) just remove the guards from dwarf2out.c and handle it more like types that we prune if they end up being unused (OTOH I guess we don't refer to the decl DIEs from "calls" because not all calls are refered to with standard DWARF -- the GNU callsite stuff refers them I think but those get generated too late). That said, when early_finish is called the cgraph and IPA references exists and thus you can sort-of see which functions are "used". Richard. > -- > Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-31 7:37 ` Richard Biener @ 2017-05-31 9:12 ` Pierre-Marie de Rodat 2017-06-16 16:35 ` Pierre-Marie de Rodat 0 siblings, 1 reply; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-31 9:12 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches On 05/31/2017 09:34 AM, Richard Biener wrote: > Actually for the bigger picture I'd refactor rest_of_decl_compilation, not > calling it from the frontends but rely on finalize_decl/function. The missing > part would then be calling the dwarf hook which should eventually be done > at some of the places the frontends now call rest_of_decl_compliation. > [â¦] > But for an easier way (you might still explore the above ;)) just remove > the guards from dwarf2out.c and handle it more like types that we > prune if they end up being unused (OTOH I guess we don't refer to > the decl DIEs from "calls" because not all calls are refered to with > standard DWARF -- the GNU callsite stuff refers them I think but those > get generated too late). > > That said, when early_finish is called the cgraph and IPA references > exists and thus you can > sort-of see which functions are "used". Ok, thanks. Iâll give a try to the first option, then. :-) -- Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-05-31 9:12 ` Pierre-Marie de Rodat @ 2017-06-16 16:35 ` Pierre-Marie de Rodat 2017-06-20 12:16 ` Richard Biener 0 siblings, 1 reply; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-06-16 16:35 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 2234 bytes --] On 05/31/2017 11:08 AM, Pierre-Marie de Rodat wrote: > On 05/31/2017 09:34 AM, Richard Biener wrote: >> Actually for the bigger picture I'd refactor >> rest_of_decl_compilation, not calling it from the frontends but >> rely on finalize_decl/function. The missing part would then be >> calling the dwarf hook which should eventually be done at some of >> the places the frontends now call rest_of_decl_compliation. I put some thought about this, but I suppose I donât yet understand well enough the relation between what rest_of_decl_compilation and finalize_decl/function do. So Iâve tried to go half-way: I moved the âspecification?â guard from the DWARF back-end to callers of the early_global_decl hook. In the end, this yielded a very small middle-end change: almost all hook calls in front-ends are for variables or namespaces, not for functions. >> But for an easier way (you might still explore the above ;)) just remove >> the guards from dwarf2out.c and handle it more like types that we >> prune if they end up being unused (OTOH I guess we don't refer to >> the decl DIEs from "calls" because not all calls are refered to with >> standard DWARF -- the GNU callsite stuff refers them I think but those >> get generated too late). >> >> That said, when early_finish is called the cgraph and IPA references >> exists and thus you can >> sort-of see which functions are "used". > > Ok, thanks. Iâll give a try to the first option, then. :-) I finally decided not to implement this scheme, as it does not give the same results for the case in Ada that motivated this change: it would generate potentially one DIE per âcalling unitâ per called function, which is quite suboptimal compared to one DIE per subprogram definition or subprogram import. This would look like a debug info bloat for debatable gain. So hereâs an updated patch, without the new debug hook. It boostrapped and regtested fine on x86_64-linux. After this change, I observed an increase of: * an increase of ~22KB for gnat1 (base is 210MB); * a decrease (?) of ~3KB for cc1 (base is 197MB); * a similar decrease of 3KB for cc1plus (base is 220MB). Ok to commit? -- Pierre-Marie de Rodat [-- Attachment #2: 0001-DWARF-make-it-possible-to-emit-debug-info-for-declar.patch --] [-- Type: text/x-patch, Size: 28664 bytes --] From 107f45b13334b5223004a3fb3cf251fd32c35055 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat <derodat@adacore.com> Date: Tue, 6 Jun 2017 10:52:51 +0200 Subject: [PATCH] DWARF: make it possible to emit debug info for declarations only The DWARF back-end used to systematically ignore file-scope function and variable declarations. While this is justified in language like C/C++, where such declarations can appear in several translation units and thus bloat uselessly the debug info, this behavior is counter-productive in languages with a well-defined module system. Specifically, it prevents the description of imported entities, that belong to foreign languages, making them unavailable from debuggers. Take for instance: package C_Binding is function My_C_Function (I : Integer) return Integer; pragma Import (C, My_C_Function, "my_c_function"); end C_Binding; This makes available for Ada programs the C function "my_c_function" under the following name: C_Binding.My_C_Function. When GCC compiles it, though, it is represented as a FUNCTION_DECL node with DECL_EXTERNAL set and a null DECL_INITIAL, which used to be discarded unconditionally in the DWARF back-end. This patch moves such filter from the DWARF back-end to the relevant callers: passes.c:rest_of_decl_compilation and godump.c:go_early_global_decl. It also This patch also updates the Ada front-end to call debug hooks for functions such as in the above example, so that we do generate debugging information for them. gcc/ * dwarf2out.c (gen_decl_die): Remove the guard to skip file-scope FUNCTION_DECL declarations. (dwarf2out_early_global_decl): Remove the guard to skip FUNCTION_DECL declarations. (dwaf2out_decl): Likewise. * godump.c (go_early_global_decl): Skip call to the real debug hook for FUNCTION_DECL declarations. * passes.c (rest_of_decl_compilation): Skip call to the early_global_decl debug hook for FUNCTION_DECL declarations, unless -fdump-go-spec is passed. gcc/ada/ * gcc-interface/ada-tree.h (DECL_FUNCTION_IS_DEF): Update copyright notice. New macro. * gcc-interface/trans.c (Subprogram_Body_to_gnu): Tag the subprogram as a definition. (Compilation_Unit_to_gnu): Tag the elaboration procedure as a definition. * gcc-interface/decl.c (gnat_to_gnu_entity): Tag declarations of imported subprograms for the current compilation unit as definitions. Disable debug info for references to variables. * gcc-interface/gigi.h (create_subprog_decl): Update declaration. * gcc-interface/utils.c (gnat_pushdecl): Add external DECLs that are not built-in functions to their binding scope. (create_subprog_decl): Add a DEFINITION parameter. If it is true, tag the function as a definition. Update all callers. (gnat_write_global_declarations): Emit debug info for imported functions. Filter out external variables for which debug info is disabled. gcc/testsuite/ * gnat.dg/debug11_pkg.adb, gnat.dg/debug11_pkg.ads, gnat.dg/debug11_pkg2.ads: New testcase. --- gcc/ada/gcc-interface/ada-tree.h | 7 ++++- gcc/ada/gcc-interface/decl.c | 19 ++++++++----- gcc/ada/gcc-interface/gigi.h | 5 +++- gcc/ada/gcc-interface/trans.c | 52 ++++++++++++++++++++-------------- gcc/ada/gcc-interface/utils.c | 35 +++++++++++++++++------ gcc/dwarf2out.c | 50 -------------------------------- gcc/godump.c | 3 +- gcc/passes.c | 11 +++---- gcc/testsuite/gnat.dg/debug11_pkg.adb | 26 +++++++++++++++++ gcc/testsuite/gnat.dg/debug11_pkg.ads | 11 +++++++ gcc/testsuite/gnat.dg/debug11_pkg2.ads | 9 ++++++ 11 files changed, 134 insertions(+), 94 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/debug11_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/debug11_pkg.ads create mode 100644 gcc/testsuite/gnat.dg/debug11_pkg2.ads diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h index a3d38b1b22e..511a0bd8173 100644 --- a/gcc/ada/gcc-interface/ada-tree.h +++ b/gcc/ada/gcc-interface/ada-tree.h @@ -6,7 +6,7 @@ * * * C Header File * * * - * Copyright (C) 1992-2016, Free Software Foundation, Inc. * + * Copyright (C) 1992-2017, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -463,6 +463,11 @@ do { \ a discriminant of a discriminated type without default expression. */ #define DECL_INVARIANT_P(NODE) DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) +/* Nonzero in a FUNCTION_DECL if this is a definition, i.e. if it was created + by a call to gnat_to_gnu_entity with definition set to True. */ +#define DECL_FUNCTION_IS_DEF(NODE) \ + DECL_LANG_FLAG_4 (FUNCTION_DECL_CHECK (NODE)) + /* Nonzero in a VAR_DECL if it is a temporary created to hold the return value of a function call or 'reference to a function call. */ #define DECL_RETURN_VALUE_P(NODE) DECL_LANG_FLAG_5 (VAR_DECL_CHECK (NODE)) diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index eab244e910c..83b9d0749fe 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1392,7 +1392,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (create_concat_name (gnat_entity, "ALIGN"), NULL_TREE, gnu_new_type, NULL_TREE, false, false, false, false, false, - true, debug_info_p, NULL, gnat_entity); + true, debug_info_p && definition, NULL, + gnat_entity); /* Initialize the aligned field if we have an initializer. */ if (gnu_expr) @@ -1441,7 +1442,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) NULL_TREE, gnu_type, gnu_expr, const_flag, Is_Public (gnat_entity), imported_p || !definition, static_flag, - volatile_flag, true, debug_info_p, + volatile_flag, true, + debug_info_p && definition, NULL, gnat_entity); gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_unc_var); TREE_CONSTANT (gnu_expr) = 1; @@ -1492,8 +1494,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, gnu_expr, const_flag, Is_Public (gnat_entity), imported_p || !definition, static_flag, - volatile_flag, artificial_p, debug_info_p, - attr_list, gnat_entity, !renamed_obj); + volatile_flag, artificial_p, + debug_info_p && definition, attr_list, + gnat_entity, !renamed_obj); DECL_BY_REF_P (gnu_decl) = used_by_ref; DECL_POINTS_TO_READONLY_P (gnu_decl) = used_by_ref && inner_const_flag; DECL_CAN_NEVER_BE_NULL_P (gnu_decl) = Can_Never_Be_Null (gnat_entity); @@ -1545,8 +1548,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) = create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type, gnu_expr, true, Is_Public (gnat_entity), !definition, static_flag, volatile_flag, - artificial_p, debug_info_p, attr_list, - gnat_entity, false); + artificial_p, debug_info_p && definition, + attr_list, gnat_entity, false); SET_DECL_CONST_CORRESPONDING_VAR (gnu_decl, gnu_corr_var); } @@ -4083,7 +4086,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) gnu_type, gnu_param_list, inline_status, public_flag, extern_flag, artificial_p, - debug_info_p, attr_list, gnat_entity); + debug_info_p, + definition && imported_p, attr_list, + gnat_entity); DECL_STUBBED_P (gnu_decl) = (Convention (gnat_entity) == Convention_Stubbed); diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index b1fb34ad620..0e25b6129a3 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -720,6 +720,8 @@ extern tree create_label_decl (tree name, Node_Id gnat_node); DEBUG_INFO_P is true if we need to write debug information for it. + DEFINITION is true if the subprogram is to be considered as a definition. + ATTR_LIST is the list of attributes to be attached to the subprogram. GNAT_NODE is used for the position of the decl. */ @@ -728,7 +730,8 @@ extern tree create_subprog_decl (tree name, tree asm_name, tree type, enum inline_status_t inline_status, bool public_flag, bool extern_flag, bool artificial_p, bool debug_info_p, - struct attrib *attr_list, Node_Id gnat_node); + bool definition, struct attrib *attr_list, + Node_Id gnat_node); /* Given a subprogram declaration DECL, its assembler name and its type, finish constructing the subprogram declaration from ASM_NAME and TYPE. */ diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 2542626d0ca..79d099538c9 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -398,7 +398,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_malloc"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); DECL_IS_MALLOC (malloc_decl) = 1; ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); @@ -406,7 +406,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_free"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); ftype = build_function_type_list (ptr_type_node, ptr_type_node, sizetype, NULL_TREE); @@ -414,7 +414,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__gnat_realloc"), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); /* This is used for 64-bit multiplication with overflow checking. */ int64_type = gnat_type_for_size (64, 0); @@ -423,7 +423,7 @@ gigi (Node_Id gnat_root, build_function_type_list (int64_type, int64_type, int64_type, NULL_TREE), NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); /* Name of the _Parent field in tagged record types. */ parent_name_id = get_identifier (Get_Name_String (Name_uParent)); @@ -446,21 +446,21 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("system__soft_links__get_jmpbuf_address_soft"), NULL_TREE, build_function_type_list (jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); set_jmpbuf_decl = create_subprog_decl (get_identifier ("system__soft_links__set_jmpbuf_address_soft"), NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); get_excptr_decl = create_subprog_decl (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE, build_function_type_list (build_pointer_type (except_type_node), NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); not_handled_by_others_decl = get_identifier ("not_handled_by_others"); for (t = TYPE_FIELDS (except_type_node); t; t = DECL_CHAIN (t)) @@ -478,7 +478,7 @@ gigi (Node_Id gnat_root, (get_identifier ("__builtin_setjmp"), NULL_TREE, build_function_type_list (integer_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); DECL_BUILT_IN_CLASS (setjmp_decl) = BUILT_IN_NORMAL; DECL_FUNCTION_CODE (setjmp_decl) = BUILT_IN_SETJMP; @@ -488,7 +488,7 @@ gigi (Node_Id gnat_root, = create_subprog_decl (get_identifier ("__builtin_update_setjmp_buf"), NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); DECL_BUILT_IN_CLASS (update_setjmp_buf_decl) = BUILT_IN_NORMAL; DECL_FUNCTION_CODE (update_setjmp_buf_decl) = BUILT_IN_UPDATE_SETJMP_BUF; @@ -500,14 +500,14 @@ gigi (Node_Id gnat_root, raise_nodefer_decl = create_subprog_decl (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE, ftype, - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); set_exception_parameter_decl = create_subprog_decl (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE, build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE), - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty); /* Hooks to call when entering/leaving an exception handler. */ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); @@ -515,26 +515,30 @@ gigi (Node_Id gnat_root, begin_handler_decl = create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* __gnat_begin_handler is a dummy procedure. */ TREE_NOTHROW (begin_handler_decl) = 1; end_handler_decl = create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); unhandled_except_decl = create_subprog_decl (get_identifier ("__gnat_unhandled_except_handler"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* Indicate that it never returns. */ ftype = build_qualified_type (ftype, TYPE_QUAL_VOLATILE); reraise_zcx_decl = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE, ftype, NULL_TREE, - is_disabled, true, true, true, false, NULL, Empty); + is_disabled, true, true, true, false, false, NULL, + Empty); /* Dummy objects to materialize "others" and "all others" in the exception tables. These are exported by a-exexpr-gcc.adb, so see this unit for @@ -573,7 +577,8 @@ gigi (Node_Id gnat_root, tree decl = create_subprog_decl (get_identifier ("__gnat_last_chance_handler"), NULL_TREE, ftype, - NULL_TREE, is_disabled, true, true, true, false, NULL, Empty); + NULL_TREE, is_disabled, true, true, true, false, false, NULL, + Empty); for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++) gnat_raise_decls[i] = decl; } @@ -739,7 +744,7 @@ build_raise_check (int check, enum exception_info_kind kind) result = create_subprog_decl (get_identifier (Name_Buffer), NULL_TREE, ftype, NULL_TREE, is_disabled, true, true, true, false, - NULL, Empty); + false, NULL, Empty); return result; } @@ -3745,6 +3750,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) = gnat_to_gnu_entity (gnat_subprog_id, NULL_TREE, Acts_As_Spec (gnat_node) && !present_gnu_tree (gnat_subprog_id)); + DECL_FUNCTION_IS_DEF (gnu_subprog_decl) = true; gnu_result_decl = DECL_RESULT (gnu_subprog_decl); gnu_subprog_type = TREE_TYPE (gnu_subprog_decl); gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type); @@ -5417,12 +5423,15 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) const Entity_Id gnat_unit_entity = Defining_Entity (gnat_unit); Entity_Id gnat_entity; Node_Id gnat_pragma; - /* Make the decl for the elaboration procedure. */ + /* Make the decl for the elaboration procedure. Emit debug info for it, so + that users can break into their elaboration code in debuggers. Kludge: + don't consider it as a definition so that we have a line map for its body, + but no subprogram description in debug info. */ tree gnu_elab_proc_decl = create_subprog_decl (create_concat_name (gnat_unit_entity, body_p ? "elabb" : "elabs"), NULL_TREE, void_ftype, NULL_TREE, - is_disabled, true, false, true, true, NULL, gnat_unit); + is_disabled, true, false, true, true, false, NULL, gnat_unit); struct elab_info *info; vec_safe_push (gnu_elab_proc_stack, gnu_elab_proc_decl); @@ -6453,7 +6462,7 @@ gnat_to_gnu (Node_Id gnat_node) gnu_prefix = gnat_to_gnu (gnat_prefix); gnu_prefix = maybe_implicit_deref (gnu_prefix); } - + gnu_result = build_component_ref (gnu_prefix, gnu_field, (Nkind (Parent (gnat_node)) @@ -6484,7 +6493,8 @@ gnat_to_gnu (Node_Id gnat_node) (Entity (Prefix (gnat_node)), attr == Attr_Elab_Body ? "elabb" : "elabs"), NULL_TREE, void_ftype, NULL_TREE, is_disabled, - true, true, true, true, NULL, gnat_node); + true, true, true, true, false, NULL, + gnat_node); gnu_result = Attribute_to_gnu (gnat_node, &gnu_result_type, attr); } diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index b8c5d3d31f6..9e656579dda 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -763,11 +763,13 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) if (!(TREE_CODE (decl) == TYPE_DECL && TREE_CODE (TREE_TYPE (decl)) == UNCONSTRAINED_ARRAY_TYPE)) { - if (DECL_EXTERNAL (decl)) - { - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) - vec_safe_push (builtin_decls, decl); - } + /* External declarations must go to the binding level they belong to. + This will make corresponding imported entities are available in the + debugger at the proper time. */ + if (DECL_EXTERNAL (decl) + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_BUILT_IN (decl)) + vec_safe_push (builtin_decls, decl); else if (global_bindings_p ()) vec_safe_push (global_decls, decl); else @@ -3189,6 +3191,8 @@ create_label_decl (tree name, Node_Id gnat_node) DEBUG_INFO_P is true if we need to write debug information for it. + DEFINITION is true if the subprogram is to be considered as a definition. + ATTR_LIST is the list of attributes to be attached to the subprogram. GNAT_NODE is used for the position of the decl. */ @@ -3197,7 +3201,8 @@ tree create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, enum inline_status_t inline_status, bool public_flag, bool extern_flag, bool artificial_p, bool debug_info_p, - struct attrib *attr_list, Node_Id gnat_node) + bool definition, struct attrib *attr_list, + Node_Id gnat_node) { tree subprog_decl = build_decl (input_location, FUNCTION_DECL, name, type); DECL_ARGUMENTS (subprog_decl) = param_decl_list; @@ -3208,6 +3213,8 @@ create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list, if (!debug_info_p) DECL_IGNORED_P (subprog_decl) = 1; + if (definition) + DECL_FUNCTION_IS_DEF (subprog_decl) = 1; switch (inline_status) { @@ -5523,10 +5530,22 @@ gnat_write_global_declarations (void) if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter)) debug_hooks->type_decl (iter, false); + /* Output imported functions. */ + FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) + if (TREE_CODE (iter) == FUNCTION_DECL + && DECL_EXTERNAL (iter) + && DECL_INITIAL (iter) == NULL + && !DECL_IGNORED_P (iter) + && DECL_FUNCTION_IS_DEF (iter)) + debug_hooks->early_global_decl (iter); + /* Then output the global variables. We need to do that after the debug - information for global types is emitted so that they are finalized. */ + information for global types is emitted so that they are finalized. Skip + external global variables, unless we need to emit debug info for them: + this is useful for imported variables, for instance. */ FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter) - if (TREE_CODE (iter) == VAR_DECL) + if (TREE_CODE (iter) == VAR_DECL + && (!DECL_EXTERNAL (iter) || !DECL_IGNORED_P (iter))) rest_of_decl_compilation (iter, true, 0); /* Output the imported modules/declarations. In GNAT, these are only diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 92444e3cd46..c277d27e8e8 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -25289,14 +25289,6 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, break; case FUNCTION_DECL: - /* Don't output any DIEs to represent mere function declarations, - unless they are class members or explicit block externs. */ - if (DECL_INITIAL (decl_or_origin) == NULL_TREE - && DECL_FILE_SCOPE_P (decl_or_origin) - && (current_function_decl == NULL_TREE - || DECL_ARTIFICIAL (decl_or_origin))) - break; - #if 0 /* FIXME */ /* This doesn't work because the C frontend sets DECL_ABSTRACT_ORIGIN @@ -25501,11 +25493,6 @@ dwarf2out_early_global_decl (tree decl) tree save_fndecl = current_function_decl; if (TREE_CODE (decl) == FUNCTION_DECL) { - /* No cfun means the symbol has no body, so there's nothing - to emit. */ - if (!DECL_STRUCT_FUNCTION (decl)) - goto early_decl_exit; - /* For nested functions, make sure we have DIEs for the parents first so that all nested DIEs are generated at the proper scope in the first shot. */ @@ -25522,7 +25509,6 @@ dwarf2out_early_global_decl (tree decl) if (TREE_CODE (decl) == FUNCTION_DECL) current_function_decl = save_fndecl; } - early_decl_exit: symtab->global_info_ready = save; } @@ -25761,42 +25747,6 @@ dwarf2out_decl (tree decl) return; case FUNCTION_DECL: - /* What we would really like to do here is to filter out all mere - file-scope declarations of file-scope functions which are never - referenced later within this translation unit (and keep all of ones - that *are* referenced later on) but we aren't clairvoyant, so we have - no idea which functions will be referenced in the future (i.e. later - on within the current translation unit). So here we just ignore all - file-scope function declarations which are not also definitions. If - and when the debugger needs to know something about these functions, - it will have to hunt around and find the DWARF information associated - with the definition of the function. - - We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL - nodes represent definitions and which ones represent mere - declarations. We have to check DECL_INITIAL instead. That's because - the C front-end supports some weird semantics for "extern inline" - function definitions. These can get inlined within the current - translation unit (and thus, we need to generate Dwarf info for their - abstract instances so that the Dwarf info for the concrete inlined - instances can have something to refer to) but the compiler never - generates any out-of-lines instances of such things (despite the fact - that they *are* definitions). - - The important point is that the C front-end marks these "extern - inline" functions as DECL_EXTERNAL, but we need to generate DWARF for - them anyway. Note that the C++ front-end also plays some similar games - for inline function definitions appearing within include files which - also contain `#pragma interface' pragmas. - - If we are called from dwarf2out_abstract_function output a DIE - anyway. We can end up here this way with early inlining and LTO - where the inlined function is output in a different LTRANS unit - or not at all. */ - if (DECL_INITIAL (decl) == NULL_TREE - && ! DECL_ABSTRACT_P (decl)) - return; - /* If we're a nested function, initially use a parent of NULL; if we're a plain function, this will be fixed up in decls_for_scope. If we're a method, it will be ignored, since we already have a DIE. */ diff --git a/gcc/godump.c b/gcc/godump.c index 4884deead80..3e905319b8f 100644 --- a/gcc/godump.c +++ b/gcc/godump.c @@ -504,7 +504,8 @@ static void go_early_global_decl (tree decl) { go_decl (decl); - real_debug_hooks->early_global_decl (decl); + if (TREE_CODE (decl) != FUNCTION_DECL || DECL_STRUCT_FUNCTION (decl) != NULL) + real_debug_hooks->early_global_decl (decl); } /* A global variable decl. */ diff --git a/gcc/passes.c b/gcc/passes.c index 64493ba1688..fb50baa1217 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -262,17 +262,18 @@ rest_of_decl_compilation (tree decl, finalize_compilation_unit (and by consequence, locally scoped symbols), or by rest_of_type_compilation below. - Also, pick up function prototypes, which will be mostly ignored - by the different early_global_decl() hooks, but will at least be - used by Go's hijack of the debug_hooks to implement - -fdump-go-spec. */ + For Go's hijack of the debug_hooks to implement -fdump-go-spec, pick up + function prototypes. Go's debug_hooks will not forward them to the + wrapped hooks. */ if (!in_lto_p && (TREE_CODE (decl) != FUNCTION_DECL /* This will pick up function prototypes with no bodies, which are not visible in finalize_compilation_unit() while iterating with FOR_EACH_*_FUNCTION through the symbol table. */ - || !DECL_SAVED_TREE (decl)) + || (flag_dump_go_spec != NULL + && !DECL_SAVED_TREE (decl) + && DECL_STRUCT_FUNCTION (decl) != NULL)) /* We need to check both decl_function_context and current_function_decl here to make sure local extern diff --git a/gcc/testsuite/gnat.dg/debug11_pkg.adb b/gcc/testsuite/gnat.dg/debug11_pkg.adb new file mode 100644 index 00000000000..336f2fd69be --- /dev/null +++ b/gcc/testsuite/gnat.dg/debug11_pkg.adb @@ -0,0 +1,26 @@ +-- { dg-options "-cargs -g -dA -margs" } +-- { dg-final { scan-assembler "local_imported_func" } } +-- { dg-final { scan-assembler "local_imported_var" } } +-- { dg-final { scan-assembler "global_imported_func" } } +-- { dg-final { scan-assembler "global_imported_var" } } +-- { dg-final { scan-assembler-not "foreign_imported_func" } } +-- { dg-final { scan-assembler-not "foreign_imported_var" } } + +with Debug11_Pkg2; + +package body Debug11_Pkg is + + procedure Dummy is + Local_Imported_Var : Integer; + pragma Import (C, Local_Imported_Var, "imported_var"); + + function Local_Imported_Func return Integer; + pragma Import (C, Local_Imported_Func, "imported_func"); + begin + Local_Imported_Var := Local_Imported_Func; + Global_Imported_Var := Global_Imported_Func; + Debug11_Pkg2.Foreign_Imported_Var := + Debug11_Pkg2.Foreign_Imported_Func; + end Dummy; + +end Debug11_Pkg; diff --git a/gcc/testsuite/gnat.dg/debug11_pkg.ads b/gcc/testsuite/gnat.dg/debug11_pkg.ads new file mode 100644 index 00000000000..dc453100d41 --- /dev/null +++ b/gcc/testsuite/gnat.dg/debug11_pkg.ads @@ -0,0 +1,11 @@ +package Debug11_Pkg is + + Global_Imported_Var : Integer; + pragma Import (C, Global_Imported_Var, "imported_var"); + + function Global_Imported_Func return Integer; + pragma Import (C, Global_Imported_Func, "imported_func"); + + procedure Dummy; + +end Debug11_Pkg; diff --git a/gcc/testsuite/gnat.dg/debug11_pkg2.ads b/gcc/testsuite/gnat.dg/debug11_pkg2.ads new file mode 100644 index 00000000000..350f51c5b40 --- /dev/null +++ b/gcc/testsuite/gnat.dg/debug11_pkg2.ads @@ -0,0 +1,9 @@ +package Debug11_Pkg2 is + + Foreign_Imported_Var : Integer; + pragma Import (C, Foreign_Imported_Var, "imported_var"); + + function Foreign_Imported_Func return Integer; + pragma Import (C, Foreign_Imported_Func, "imported_func"); + +end Debug11_Pkg2; -- 2.13.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-06-16 16:35 ` Pierre-Marie de Rodat @ 2017-06-20 12:16 ` Richard Biener 2017-06-20 14:34 ` Pierre-Marie de Rodat 0 siblings, 1 reply; 14+ messages in thread From: Richard Biener @ 2017-06-20 12:16 UTC (permalink / raw) To: Pierre-Marie de Rodat; +Cc: GCC Patches On Fri, Jun 16, 2017 at 6:35 PM, Pierre-Marie de Rodat <derodat@adacore.com> wrote: > On 05/31/2017 11:08 AM, Pierre-Marie de Rodat wrote: >> >> On 05/31/2017 09:34 AM, Richard Biener wrote: >>> >>> Actually for the bigger picture I'd refactor >>> rest_of_decl_compilation, not calling it from the frontends but >>> rely on finalize_decl/function. The missing part would then be >>> calling the dwarf hook which should eventually be done at some of >>> the places the frontends now call rest_of_decl_compliation. > > > I put some thought about this, but I suppose I don’t yet understand well > enough the relation between what rest_of_decl_compilation and > finalize_decl/function do. So I’ve tried to go half-way: I moved the > “specification?” guard from the DWARF back-end to callers of the > early_global_decl hook. In the end, this yielded a very small middle-end > change: almost all hook calls in front-ends are for variables or namespaces, > not for functions. > >>> But for an easier way (you might still explore the above ;)) just remove >>> the guards from dwarf2out.c and handle it more like types that we >>> prune if they end up being unused (OTOH I guess we don't refer to >>> the decl DIEs from "calls" because not all calls are refered to with >>> standard DWARF -- the GNU callsite stuff refers them I think but those >>> get generated too late). >>> >>> That said, when early_finish is called the cgraph and IPA references >>> exists and thus you can >>> sort-of see which functions are "used". >> >> >> Ok, thanks. I’ll give a try to the first option, then. :-) > > > I finally decided not to implement this scheme, as it does not give the same > results for the case in Ada that motivated this change: it would generate > potentially one DIE per “calling unit” per called function, which is quite > suboptimal compared to one DIE per subprogram definition or subprogram > import. This would look like a debug info bloat for debatable gain. > > So here’s an updated patch, without the new debug hook. It boostrapped and > regtested fine on x86_64-linux. After this change, I observed an increase > of: > > * an increase of ~22KB for gnat1 (base is 210MB); > * a decrease (?) of ~3KB for cc1 (base is 197MB); > * a similar decrease of 3KB for cc1plus (base is 220MB). > > Ok to commit? Nice. This looks ok. I'm mildy curious about the deecrease of debuginfo size for cc1 -- did you spot anything obvious there? I suspect Fortran wants to do sth similar as Ada for imported modules. Thanks, Richard. > -- > Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-06-20 12:16 ` Richard Biener @ 2017-06-20 14:34 ` Pierre-Marie de Rodat 2017-06-21 7:11 ` Richard Biener 0 siblings, 1 reply; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-06-20 14:34 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches On 06/20/2017 02:16 PM, Richard Biener wrote: > Nice. This looks ok. Great, thank you! > I'm mildy curious about the deecrease of debuginfo size for cc1 -- did > you spot anything obvious there? Well, the benchmark I exposed was for the whole file size, not just .debug_info section size. Just to be sure, I compared object files for both trunk and my patched tree: outside of Ada units, I only get the following evolution: > gcc/dwarf2out.o: -10168 bytes > gcc/godump.o: +272 bytes > gcc/passes.o: +880 bytes This diff comes from my changes themselves. I had a quick look at the same for cc1âs .debug_info: there is the expected evolution, too, > I suspect Fortran wants to do sth similar as Ada for imported modules. Maybe. I have zero Fortran knowledge, so Iâll let a Fortran expert decide, if that is fine for you. :-) In any case, the back-end is ready for that. -- Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-06-20 14:34 ` Pierre-Marie de Rodat @ 2017-06-21 7:11 ` Richard Biener 2017-06-21 11:25 ` Pierre-Marie de Rodat 0 siblings, 1 reply; 14+ messages in thread From: Richard Biener @ 2017-06-21 7:11 UTC (permalink / raw) To: Pierre-Marie de Rodat; +Cc: GCC Patches On Tue, Jun 20, 2017 at 4:34 PM, Pierre-Marie de Rodat <derodat@adacore.com> wrote: > On 06/20/2017 02:16 PM, Richard Biener wrote: >> >> Nice. This looks ok. > > > Great, thank you! > >> I'm mildy curious about the deecrease of debuginfo size for cc1 -- did >> you spot anything obvious there? > > > Well, the benchmark I exposed was for the whole file size, not just > .debug_info section size. Just to be sure, I compared object files for both > trunk and my patched tree: outside of Ada units, I only get the following > evolution: >> >> gcc/dwarf2out.o: -10168 bytes >> gcc/godump.o: +272 bytes >> gcc/passes.o: +880 bytes > > > This diff comes from my changes themselves. I had a quick look at the same > for cc1’s .debug_info: there is the expected evolution, too, > >> I suspect Fortran wants to do sth similar as Ada for imported modules. > > > Maybe. I have zero Fortran knowledge, so I’ll let a Fortran expert decide, > if that is fine for you. :-) In any case, the back-end is ready for that. Sure, no obligation for you to enhance Fortran debug! Thanks, Richard. > -- > Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only 2017-06-21 7:11 ` Richard Biener @ 2017-06-21 11:25 ` Pierre-Marie de Rodat 0 siblings, 0 replies; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-06-21 11:25 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches On 06/21/2017 09:11 AM, Richard Biener wrote: > Sure, no obligation for you to enhance Fortran debug! Understood, thanks. For your information, I just committed the change. Thank you again for reviewing! -- Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions 2017-05-29 7:50 [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Pierre-Marie de Rodat 2017-05-29 8:05 ` [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only Pierre-Marie de Rodat @ 2017-05-30 11:59 ` Richard Biener 2017-05-30 15:35 ` Pierre-Marie de Rodat 1 sibling, 1 reply; 14+ messages in thread From: Richard Biener @ 2017-05-30 11:59 UTC (permalink / raw) To: Pierre-Marie de Rodat; +Cc: GCC Patches On Mon, May 29, 2017 at 9:50 AM, Pierre-Marie de Rodat <derodat@adacore.com> wrote: > Hello, > > An upcoming patch exposes a bug in gimplify_modify_expr. There, we try > not to create DECL_DEBUG_EXPR links across functions, however we don't > check that *FROM_P actually belongs to the current function before > modifying it. This patch fixes this oversight. > > Bootstrapped and regtested on x86_64-linux. Ok to commit? Thank you in > advance! Ok. Richard. > gcc/ > > * gimplify.c (gimplify_modify_expr): Don't create a > DECL_DEBUG_EXPR link if *FROM_P does not belong to the current > function. > --- > gcc/gimplify.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/gcc/gimplify.c b/gcc/gimplify.c > index 455a6993e15..2c7fc9fabd1 100644 > --- a/gcc/gimplify.c > +++ b/gcc/gimplify.c > @@ -5580,7 +5580,8 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, > && DECL_IGNORED_P (*from_p) > && DECL_P (*to_p) > && !DECL_IGNORED_P (*to_p) > - && decl_function_context (*to_p) == current_function_decl) > + && decl_function_context (*to_p) == current_function_decl > + && decl_function_context (*from_p) == current_function_decl) > { > if (!DECL_NAME (*from_p) && DECL_NAME (*to_p)) > DECL_NAME (*from_p) > -- > 2.13.0 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions 2017-05-30 11:59 ` [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Richard Biener @ 2017-05-30 15:35 ` Pierre-Marie de Rodat 0 siblings, 0 replies; 14+ messages in thread From: Pierre-Marie de Rodat @ 2017-05-30 15:35 UTC (permalink / raw) To: Richard Biener; +Cc: GCC Patches On 05/30/2017 01:51 PM, Richard Biener wrote: > Ok. Thank you! This one is committed, now. -- Pierre-Marie de Rodat ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2017-06-21 11:25 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-05-29 7:50 [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Pierre-Marie de Rodat 2017-05-29 8:05 ` [PATCH 2/2] DWARF: make it possible to emit debug info for declarations only Pierre-Marie de Rodat 2017-05-29 13:39 ` Pierre-Marie de Rodat 2017-05-30 12:11 ` Richard Biener 2017-05-30 15:51 ` Pierre-Marie de Rodat 2017-05-31 7:37 ` Richard Biener 2017-05-31 9:12 ` Pierre-Marie de Rodat 2017-06-16 16:35 ` Pierre-Marie de Rodat 2017-06-20 12:16 ` Richard Biener 2017-06-20 14:34 ` Pierre-Marie de Rodat 2017-06-21 7:11 ` Richard Biener 2017-06-21 11:25 ` Pierre-Marie de Rodat 2017-05-30 11:59 ` [PATCH 1/2] gimplify_modify_expr: avoid DECL_DEBUG_EXPR links across functions Richard Biener 2017-05-30 15:35 ` Pierre-Marie de Rodat
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).