* [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 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 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 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
* 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
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).