From: Richard Biener <rguenther@suse.de>
To: Alexandre Oliva <oliva@adacore.com>
Cc: gcc-patches@gcc.gnu.org, ebotcazou@adacore.com, joseph@codesourcery.com
Subject: Re: introduce -fcallgraph-info option
Date: Mon, 04 Nov 2019 08:28:00 -0000 [thread overview]
Message-ID: <nycvar.YFH.7.76.1911040926580.5566@zhemvz.fhfr.qr> (raw)
In-Reply-To: <orv9s213ey.fsf@livre.home>
[-- Attachment #1: Type: text/plain, Size: 30058 bytes --]
On Sat, 2 Nov 2019, Alexandre Oliva wrote:
> On Oct 30, 2019, Richard Biener <rguenther@suse.de> wrote:
>
> > One way of operation would be to
> > generate the graph during the compilation step
>
> Stack usage is only computed during prologue/epilogue generation in RTL.
>
> > Additional arguments to -fcallgraph-info might be used to direct the
> > output to a specific directory as well.
>
> I've adjusted open_auxiliary_file for LTO recompilation auxiliary files
> to be placed in the same location as the specified executable output
> name, and noted that in the documentation.
Please leave that part out for now, I'd rather discuss this separately
from the bulk of the patch. That is, I wonder why we shouldn't
simply adjust aux_base_name to something else for -flto [in the driver].
> I've also added a bitmap to output nodes for externals, accidentally
> dropped in the transition to incremental generation of the .ci file.
>
> Regstrapped on x86_64-linux-gnu. Ok to install?
OK for the rest.
Thanks,
Richard.
>
> introduce -fcallgraph-info option
>
> This was first submitted many years ago
> https://gcc.gnu.org/ml/gcc-patches/2010-10/msg02468.html
>
> The command line option -fcallgraph-info is added and makes the
> compiler generate another output file (xxx.ci) for each compilation
> unit (or LTO partitoin), which is a valid VCG file (you can launch
> your favorite VCG viewer on it unmodified) and contains the "final"
> callgraph of the unit. "final" is a bit of a misnomer as this is
> actually the callgraph at RTL expansion time, but since most
> high-level optimizations are done at the Tree level and RTL doesn't
> usually fiddle with calls, it's final in almost all cases. Moreover,
> the nodes can be decorated with additional info: -fcallgraph-info=su
> adds stack usage info and -fcallgraph-info=da dynamic allocation info.
>
>
> for gcc/ChangeLog
> From Eric Botcazou <ebotcazou@adacore.com>, Alexandre Oliva <oliva@adacore.com>
>
> * common.opt (-fcallgraph-info[=]): New option.
> * doc/invoke.texi (Developer options): Document it.
> * opts.c (common_handle_option): Handle it.
> * builtins.c (expand_builtin_alloca): Record allocation if
> -fcallgraph-info=da.
> * calls.c (expand_call): If -fcallgraph-info, record the call.
> (emit_library_call_value_1): Likewise.
> * flag-types.h (enum callgraph_info_type): New type.
> * explow.c: Include stringpool.h.
> (set_stack_check_libfunc): Set SET_SYMBOL_REF_DECL on the symbol.
> * function.c (allocate_stack_usage_info): New.
> (allocate_struct_function): Call it for -fcallgraph-info.
> (prepare_function_start): Call it otherwise.
> (record_final_call, record_dynamic_alloc): New.
> * function.h (struct callinfo_callee): New.
> (CALLEE_FROM_CGRAPH_P): New.
> (struct callinfo_dalloc): New.
> (struct stack_usage): Add callees and dallocs.
> (record_final_call, record_dynamic_alloc): Declare.
> * gimplify.c (gimplify_decl_expr): Record dynamically-allocated
> object if -fcallgraph-info=da.
> * optabs-libfuncs.c (build_libfunc_function): Keep SYMBOL_REF_DECL.
> * print-tree.h (print_decl_identifier): Declare.
> (PRINT_DECL_ORIGIN, PRINT_DECL_NAME, PRINT_DECL_UNIQUE_NAME): New.
> * print-tree.c: Include print-tree.h.
> (print_decl_identifier): New function.
> * toplev.c: Include print-tree.h.
> (callgraph_info_file): New global variable.
> (callgraph_info_external_printed): Likewise.
> (open_auxiliary_file): Use dump_base_name for LTO partitions.
> (output_stack_usage): Rename to...
> (output_stack_usage_1): ... this. Make it static, add cf
> parameter. If -fcallgraph-info=su, print stack usage to cf.
> If -fstack-usage, use print_decl_identifier for
> pretty-printing.
> (INDIRECT_CALL_NAME): New.
> (dump_final_node_vcg_start): New.
> (dump_final_callee_vcg, dump_final_node_vcg): New.
> (output_stack_usage): New.
> (lang_dependent_init): Open and start file if
> -fcallgraph-info. Allocated callgraph_info_external_printed.
> (finalize): If callgraph_info_file is not null, finish it,
> close it, and release callgraph_info_external_printed.
>
> for gcc/ada/ChangeLog
>
> * gcc-interface/misc.c (callgraph_info_file): Delete.
> ---
> gcc/ada/gcc-interface/misc.c | 3 -
> gcc/builtins.c | 4 +
> gcc/calls.c | 6 +
> gcc/common.opt | 8 ++
> gcc/doc/invoke.texi | 22 +++++
> gcc/explow.c | 5 +
> gcc/flag-types.h | 16 ++++
> gcc/function.c | 59 ++++++++++++-
> gcc/function.h | 30 +++++++
> gcc/gimplify.c | 4 +
> gcc/optabs-libfuncs.c | 4 -
> gcc/opts.c | 26 ++++++
> gcc/output.h | 2
> gcc/print-tree.c | 76 +++++++++++++++++
> gcc/print-tree.h | 4 +
> gcc/toplev.c | 186 ++++++++++++++++++++++++++++++++++--------
> 16 files changed, 402 insertions(+), 53 deletions(-)
>
> diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
> index 4abd4d5..d68b373 100644
> --- a/gcc/ada/gcc-interface/misc.c
> +++ b/gcc/ada/gcc-interface/misc.c
> @@ -54,9 +54,6 @@
> #include "ada-tree.h"
> #include "gigi.h"
>
> -/* This symbol needs to be defined for the front-end. */
> -void *callgraph_info_file = NULL;
> -
> /* Command-line argc and argv. These variables are global since they are
> imported in back_end.adb. */
> unsigned int save_argc;
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index 5d811f1..bd30238 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -5406,6 +5406,10 @@ expand_builtin_alloca (tree exp)
> = allocate_dynamic_stack_space (op0, 0, align, max_size, alloca_for_var);
> result = convert_memory_address (ptr_mode, result);
>
> + /* Dynamic allocations for variables are recorded during gimplification. */
> + if (!alloca_for_var && (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC))
> + record_dynamic_alloc (exp);
> +
> return result;
> }
>
> diff --git a/gcc/calls.c b/gcc/calls.c
> index e2b770f..6292135 100644
> --- a/gcc/calls.c
> +++ b/gcc/calls.c
> @@ -3759,6 +3759,9 @@ expand_call (tree exp, rtx target, int ignore)
>
> preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
>
> + if (flag_callgraph_info)
> + record_final_call (fndecl, EXPR_LOCATION (exp));
> +
> /* We want to make two insn chains; one for a sibling call, the other
> for a normal call. We will select one of the two chains after
> initial RTL generation is complete. */
> @@ -5343,6 +5346,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
>
> before_call = get_last_insn ();
>
> + if (flag_callgraph_info)
> + record_final_call (SYMBOL_REF_DECL (orgfun), UNKNOWN_LOCATION);
> +
> /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
> will set inhibit_defer_pop to that value. */
> /* The return type is needed to decide how many bytes the function pops.
> diff --git a/gcc/common.opt b/gcc/common.opt
> index cc279f4..299eac6 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -1091,6 +1091,14 @@ fbtr-bb-exclusive
> Common Ignore
> Does nothing. Preserved for backward compatibility.
>
> +fcallgraph-info
> +Common Report RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO);
> +Output callgraph information on a per-file basis.
> +
> +fcallgraph-info=
> +Common Report RejectNegative Joined
> +Output callgraph information on a per-file basis with decorations.
> +
> fcall-saved-
> Common Joined RejectNegative Var(common_deferred_options) Defer
> -fcall-saved-<register> Mark <register> as being preserved across functions.
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index faa7fa9..266021c 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -584,8 +584,9 @@ Objective-C and Objective-C++ Dialects}.
> @item Developer Options
> @xref{Developer Options,,GCC Developer Options}.
> @gccoptlist{-d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
> --dumpfullversion -fchecking -fchecking=@var{n} -fdbg-cnt-list @gol
> --fdbg-cnt=@var{counter-value-list} @gol
> +-dumpfullversion -fcallgraph-info@r{[}=su,da@r{]}
> +-fchecking -fchecking=@var{n}
> +-fdbg-cnt-list @gol -fdbg-cnt=@var{counter-value-list} @gol
> -fdisable-ipa-@var{pass_name} @gol
> -fdisable-rtl-@var{pass_name} @gol
> -fdisable-rtl-@var{pass-name}=@var{range-list} @gol
> @@ -14564,6 +14565,23 @@ The files are created in the directory of the output file.
>
> @table @gcctabopt
>
> +@item -fcallgraph-info
> +@itemx -fcallgraph-info=@var{MARKERS}
> +@opindex fcallgraph-info
> +Makes the compiler output callgraph information for the program, on a
> +per-object-file basis. The information is generated in the common VCG format.
> +It can be decorated with additional, per-node and/or per-edge information,
> +if a list of comma-separated markers is additionally specified. When the
> +@code{su} marker is specified, the callgraph is decorated with stack usage
> +information; it is equivalent to @option{-fstack-usage}. When the @code{da}
> +marker is specified, the callgraph is decorated with information about
> +dynamically allocated objects.
> +
> +When compiling with @option{-flto}, no callgraph information is output
> +along with the object file. At LTO link time, @option{-fcallgraph-info}
> +may generate multiple callgraph information files next to the specified
> +output file.
> +
> @item -d@var{letters}
> @itemx -fdump-rtl-@var{pass}
> @itemx -fdump-rtl-@var{pass}=@var{filename}
> diff --git a/gcc/explow.c b/gcc/explow.c
> index 7eb854b..83c7863 100644
> --- a/gcc/explow.c
> +++ b/gcc/explow.c
> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
> #include "dojump.h"
> #include "explow.h"
> #include "expr.h"
> +#include "stringpool.h"
> #include "common/common-target.h"
> #include "output.h"
> #include "params.h"
> @@ -1611,6 +1612,10 @@ set_stack_check_libfunc (const char *libfunc_name)
> {
> gcc_assert (stack_check_libfunc == NULL_RTX);
> stack_check_libfunc = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
> + tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
> + get_identifier (libfunc_name), void_type_node);
> + DECL_EXTERNAL (decl) = 1;
> + SET_SYMBOL_REF_DECL (stack_check_libfunc, decl);
> }
> \f
> /* Emit one stack probe at ADDRESS, an address within the stack. */
> diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> index a210328..b23d3a2 100644
> --- a/gcc/flag-types.h
> +++ b/gcc/flag-types.h
> @@ -200,6 +200,22 @@ enum stack_check_type
> FULL_BUILTIN_STACK_CHECK
> };
>
> +/* Type of callgraph information. */
> +enum callgraph_info_type
> +{
> + /* No information. */
> + NO_CALLGRAPH_INFO = 0,
> +
> + /* Naked callgraph. */
> + CALLGRAPH_INFO_NAKED = 1,
> +
> + /* Callgraph decorated with stack usage information. */
> + CALLGRAPH_INFO_STACK_USAGE = 2,
> +
> + /* Callgraph decoration with dynamic allocation information. */
> + CALLGRAPH_INFO_DYNAMIC_ALLOC = 4
> +};
> +
> /* Floating-point contraction mode. */
> enum fp_contract_mode {
> FP_CONTRACT_OFF = 0,
> diff --git a/gcc/function.c b/gcc/function.c
> index a1c76a4..3f79a38 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -4725,6 +4725,16 @@ get_last_funcdef_no (void)
> return funcdef_no;
> }
>
> +/* Allocate and initialize the stack usage info data structure for the
> + current function. */
> +static void
> +allocate_stack_usage_info (void)
> +{
> + gcc_assert (!cfun->su);
> + cfun->su = ggc_cleared_alloc<stack_usage> ();
> + cfun->su->static_stack_size = -1;
> +}
> +
> /* Allocate a function structure for FNDECL and set its contents
> to the defaults. Set cfun to the newly-allocated object.
> Some of the helper functions invoked during initialization assume
> @@ -4802,6 +4812,9 @@ allocate_struct_function (tree fndecl, bool abstract_p)
>
> if (!profile_flag && !flag_instrument_function_entry_exit)
> DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl) = 1;
> +
> + if (flag_callgraph_info)
> + allocate_stack_usage_info ();
> }
>
> /* Don't enable begin stmt markers if var-tracking at assignments is
> @@ -4846,11 +4859,8 @@ prepare_function_start (void)
> init_expr ();
> default_rtl_profile ();
>
> - if (flag_stack_usage_info)
> - {
> - cfun->su = ggc_cleared_alloc<stack_usage> ();
> - cfun->su->static_stack_size = -1;
> - }
> + if (flag_stack_usage_info && !flag_callgraph_info)
> + allocate_stack_usage_info ();
>
> cse_not_expected = ! optimize;
>
> @@ -6373,12 +6383,49 @@ rest_of_handle_thread_prologue_and_epilogue (void)
> cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
>
> /* The stack usage info is finalized during prologue expansion. */
> - if (flag_stack_usage_info)
> + if (flag_stack_usage_info || flag_callgraph_info)
> output_stack_usage ();
>
> return 0;
> }
>
> +/* Record a final call to CALLEE at LOCATION. */
> +
> +void
> +record_final_call (tree callee, location_t location)
> +{
> + if (!callee || CALLEE_FROM_CGRAPH_P (callee))
> + return;
> +
> + struct callinfo_callee datum = { location, callee };
> + vec_safe_push (cfun->su->callees, datum);
> +}
> +
> +/* Record a dynamic allocation made for DECL_OR_EXP. */
> +
> +void
> +record_dynamic_alloc (tree decl_or_exp)
> +{
> + struct callinfo_dalloc datum;
> +
> + if (DECL_P (decl_or_exp))
> + {
> + datum.location = DECL_SOURCE_LOCATION (decl_or_exp);
> + const char *name = lang_hooks.decl_printable_name (decl_or_exp, 2);
> + const char *dot = strrchr (name, '.');
> + if (dot)
> + name = dot + 1;
> + datum.name = ggc_strdup (name);
> + }
> + else
> + {
> + datum.location = EXPR_LOCATION (decl_or_exp);
> + datum.name = NULL;
> + }
> +
> + vec_safe_push (cfun->su->dallocs, datum);
> +}
> +
> namespace {
>
> const pass_data pass_data_thread_prologue_and_epilogue =
> diff --git a/gcc/function.h b/gcc/function.h
> index 43ac5dff..14794c4 100644
> --- a/gcc/function.h
> +++ b/gcc/function.h
> @@ -192,6 +192,23 @@ public:
> poly_int64 length;
> };
>
> +/* Describe emitted builtin calls for -fcallgraph-info. Those that
> + are not builtin are taken from cgraph edges. */
> +struct GTY(()) callinfo_callee
> +{
> + location_t location;
> + tree decl;
> +};
> +#define CALLEE_FROM_CGRAPH_P(T) \
> + (!fndecl_built_in_p (T) && !DECL_IS_BUILTIN (T))
> +
> +/* Describe dynamic allocation for -fcallgraph-info=da. */
> +struct GTY(()) callinfo_dalloc
> +{
> + location_t location;
> + char const *name;
> +};
> +
> class GTY(()) stack_usage
> {
> public:
> @@ -210,6 +227,13 @@ public:
> /* Nonzero if the amount of stack space allocated dynamically cannot
> be bounded at compile-time. */
> unsigned int has_unbounded_dynamic_stack_size : 1;
> +
> + /* Functions called within the function, if callgraph is enabled. */
> + vec<callinfo_callee, va_gc> *callees;
> +
> + /* Dynamic allocations encountered within the function, if callgraph
> + da is enabled. */
> + vec<callinfo_dalloc, va_gc> *dallocs;
> };
>
> #define current_function_static_stack_size (cfun->su->static_stack_size)
> @@ -406,6 +430,12 @@ void add_local_decl (struct function *fun, tree d);
> #define FOR_EACH_LOCAL_DECL(FUN, I, D) \
> FOR_EACH_VEC_SAFE_ELT_REVERSE ((FUN)->local_decls, I, D)
>
> +/* Record a final call to CALLEE at LOCATION. */
> +void record_final_call (tree callee, location_t location);
> +
> +/* Record a dynamic allocation made for DECL_OR_EXP. */
> +void record_dynamic_alloc (tree decl_or_exp);
> +
> /* If va_list_[gf]pr_size is set to this, it means we don't know how
> many units need to be saved. */
> #define VA_LIST_MAX_GPR_SIZE 255
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 12ed3f8..74fc45a 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -1698,6 +1698,10 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
> t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
>
> gimplify_and_add (t, seq_p);
> +
> + /* Record the dynamic allocation associated with DECL if requested. */
> + if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
> + record_dynamic_alloc (decl);
> }
>
> /* A helper function to be called via walk_tree. Mark all labels under *TP
> diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
> index ef43dae..8916f7e4 100644
> --- a/gcc/optabs-libfuncs.c
> +++ b/gcc/optabs-libfuncs.c
> @@ -735,10 +735,6 @@ build_libfunc_function_visibility (const char *name, symbol_visibility vis)
> DECL_VISIBILITY_SPECIFIED (decl) = 1;
> gcc_assert (DECL_ASSEMBLER_NAME (decl));
>
> - /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
> - are the flags assigned by targetm.encode_section_info. */
> - SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
> -
> return decl;
> }
>
> diff --git a/gcc/opts.c b/gcc/opts.c
> index 10b9f10..f46b468 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -2433,6 +2433,32 @@ common_handle_option (struct gcc_options *opts,
> /* Deferred. */
> break;
>
> + case OPT_fcallgraph_info:
> + opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
> + break;
> +
> + case OPT_fcallgraph_info_:
> + {
> + char *my_arg, *p;
> + my_arg = xstrdup (arg);
> + p = strtok (my_arg, ",");
> + while (p)
> + {
> + if (strcmp (p, "su") == 0)
> + {
> + opts->x_flag_callgraph_info |= CALLGRAPH_INFO_STACK_USAGE;
> + opts->x_flag_stack_usage_info = true;
> + }
> + else if (strcmp (p, "da") == 0)
> + opts->x_flag_callgraph_info |= CALLGRAPH_INFO_DYNAMIC_ALLOC;
> + else
> + return 0;
> + p = strtok (NULL, ",");
> + }
> + free (my_arg);
> + }
> + break;
> +
> case OPT_fdiagnostics_show_location_:
> diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
> break;
> diff --git a/gcc/output.h b/gcc/output.h
> index 835d635..6cccada 100644
> --- a/gcc/output.h
> +++ b/gcc/output.h
> @@ -604,7 +604,7 @@ extern int maybe_assemble_visibility (tree);
>
> extern int default_address_cost (rtx, machine_mode, addr_space_t, bool);
>
> -/* Output stack usage information. */
> +/* Stack usage. */
> extern void output_stack_usage (void);
>
> #endif /* ! GCC_OUTPUT_H */
> diff --git a/gcc/print-tree.c b/gcc/print-tree.c
> index 6dcbb2d..bd09ec4 100644
> --- a/gcc/print-tree.c
> +++ b/gcc/print-tree.c
> @@ -1035,6 +1035,82 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
> fprintf (file, ">");
> }
>
> +/* Print the identifier for DECL according to FLAGS. */
> +
> +void
> +print_decl_identifier (FILE *file, tree decl, int flags)
> +{
> + bool needs_colon = false;
> + const char *name;
> + char c;
> +
> + if (flags & PRINT_DECL_ORIGIN)
> + {
> + if (DECL_IS_BUILTIN (decl))
> + fputs ("<built-in>", file);
> + else
> + {
> + expanded_location loc
> + = expand_location (DECL_SOURCE_LOCATION (decl));
> + fprintf (file, "%s:%d:%d", loc.file, loc.line, loc.column);
> + }
> + needs_colon = true;
> + }
> +
> + if (flags & PRINT_DECL_UNIQUE_NAME)
> + {
> + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
> + if (!TREE_PUBLIC (decl)
> + || (DECL_WEAK (decl) && !DECL_EXTERNAL (decl)))
> + /* The symbol has internal or weak linkage so its assembler name
> + is not necessarily unique among the compilation units of the
> + program. We therefore have to further mangle it. But we can't
> + simply use DECL_SOURCE_FILE because it contains the name of the
> + file the symbol originates from so, e.g. for function templates
> + in C++ where the templates are defined in a header file, we can
> + have symbols with the same assembler name and DECL_SOURCE_FILE.
> + That's why we use the name of the top-level source file of the
> + compilation unit. ??? Unnecessary for Ada. */
> + name = ACONCAT ((main_input_filename, ":", name, NULL));
> + }
> + else if (flags & PRINT_DECL_NAME)
> + {
> + /* We don't want to print the full qualified name because it can be long,
> + so we strip the scope prefix, but we may need to deal with the suffix
> + created by the compiler. */
> + const char *suffix = strchr (IDENTIFIER_POINTER (DECL_NAME (decl)), '.');
> + name = lang_hooks.decl_printable_name (decl, 2);
> + if (suffix)
> + {
> + const char *dot = strchr (name, '.');
> + while (dot && strcasecmp (dot, suffix) != 0)
> + {
> + name = dot + 1;
> + dot = strchr (name, '.');
> + }
> + }
> + else
> + {
> + const char *dot = strrchr (name, '.');
> + if (dot)
> + name = dot + 1;
> + }
> + }
> + else
> + return;
> +
> + if (needs_colon)
> + fputc (':', file);
> +
> + while ((c = *name++) != '\0')
> + {
> + /* Strip double-quotes because of VCG. */
> + if (c == '"')
> + continue;
> + fputc (c, file);
> + }
> +}
> +
>
> /* Print the node NODE on standard error, for debugging.
> Most nodes referred to by this one are printed recursively
> diff --git a/gcc/print-tree.h b/gcc/print-tree.h
> index 1d4fe6e..cbea48c 100644
> --- a/gcc/print-tree.h
> +++ b/gcc/print-tree.h
> @@ -42,5 +42,9 @@ extern void print_node (FILE *, const char *, tree, int,
> extern void print_node_brief (FILE *, const char *, const_tree, int);
> extern void indent_to (FILE *, int);
> #endif
> +#define PRINT_DECL_ORIGIN 0x1
> +#define PRINT_DECL_NAME 0x2
> +#define PRINT_DECL_UNIQUE_NAME 0x4
> +extern void print_decl_identifier (FILE *, tree, int flags);
>
> #endif // GCC_PRINT_TREE_H
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 00a5e83..8aaf216 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
> #include "dumpfile.h"
> #include "ipa-fnsummary.h"
> #include "dump-context.h"
> +#include "print-tree.h"
> #include "optinfo-emit-json.h"
>
> #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
> @@ -174,6 +175,8 @@ const char *user_label_prefix;
>
> FILE *asm_out_file;
> FILE *aux_info_file;
> +FILE *callgraph_info_file = NULL;
> +static bitmap callgraph_info_external_printed;
> FILE *stack_usage_file = NULL;
>
> /* The current working directory of a translation. It's generally the
> @@ -913,8 +916,8 @@ alloc_for_identifier_to_locale (size_t len)
> }
>
> /* Output stack usage information. */
> -void
> -output_stack_usage (void)
> +static void
> +output_stack_usage_1 (FILE *cf)
> {
> static bool warning_issued = false;
> enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED };
> @@ -970,41 +973,17 @@ output_stack_usage (void)
> stack_usage += current_function_dynamic_stack_size;
> }
>
> + if (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
> + fprintf (cf, "\\n" HOST_WIDE_INT_PRINT_DEC " bytes (%s)",
> + stack_usage,
> + stack_usage_kind_str[stack_usage_kind]);
> +
> if (stack_usage_file)
> {
> - expanded_location loc
> - = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
> - /* We don't want to print the full qualified name because it can be long,
> - so we strip the scope prefix, but we may need to deal with the suffix
> - created by the compiler. */
> - const char *suffix
> - = strchr (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), '.');
> - const char *name
> - = lang_hooks.decl_printable_name (current_function_decl, 2);
> - if (suffix)
> - {
> - const char *dot = strchr (name, '.');
> - while (dot && strcasecmp (dot, suffix) != 0)
> - {
> - name = dot + 1;
> - dot = strchr (name, '.');
> - }
> - }
> - else
> - {
> - const char *dot = strrchr (name, '.');
> - if (dot)
> - name = dot + 1;
> - }
> -
> - fprintf (stack_usage_file,
> - "%s:%d:%d:%s\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
> - loc.file == NULL ? "(artificial)" : lbasename (loc.file),
> - loc.line,
> - loc.column,
> - name,
> - stack_usage,
> - stack_usage_kind_str[stack_usage_kind]);
> + print_decl_identifier (stack_usage_file, current_function_decl,
> + PRINT_DECL_ORIGIN | PRINT_DECL_NAME);
> + fprintf (stack_usage_file, "\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
> + stack_usage, stack_usage_kind_str[stack_usage_kind]);
> }
>
> if (warn_stack_usage >= 0 && warn_stack_usage < HOST_WIDE_INT_MAX)
> @@ -1026,14 +1005,127 @@ output_stack_usage (void)
> }
> }
>
> -/* Open an auxiliary output file. */
> +/* Dump placeholder node for indirect calls in VCG format. */
> +
> +#define INDIRECT_CALL_NAME "__indirect_call"
> +
> +static void
> +dump_final_node_vcg_start (FILE *f, tree decl)
> +{
> + fputs ("node: { title: \"", f);
> + if (decl)
> + print_decl_identifier (f, decl, PRINT_DECL_UNIQUE_NAME);
> + else
> + fputs (INDIRECT_CALL_NAME, f);
> + fputs ("\" label: \"", f);
> + if (decl)
> + {
> + print_decl_identifier (f, decl, PRINT_DECL_NAME);
> + fputs ("\\n", f);
> + print_decl_identifier (f, decl, PRINT_DECL_ORIGIN);
> + }
> + else
> + fputs ("Indirect Call Placeholder", f);
> +}
> +
> +/* Dump final cgraph edge in VCG format. */
> +
> +static void
> +dump_final_callee_vcg (FILE *f, location_t location, tree callee)
> +{
> + if ((!callee || DECL_EXTERNAL (callee))
> + && bitmap_set_bit (callgraph_info_external_printed,
> + callee ? DECL_UID (callee) + 1 : 0))
> + {
> + dump_final_node_vcg_start (f, callee);
> + fputs ("\" shape : ellipse }\n", f);
> + }
> +
> + fputs ("edge: { sourcename: \"", f);
> + print_decl_identifier (f, current_function_decl, PRINT_DECL_UNIQUE_NAME);
> + fputs ("\" targetname: \"", f);
> + if (callee)
> + print_decl_identifier (f, callee, PRINT_DECL_UNIQUE_NAME);
> + else
> + fputs (INDIRECT_CALL_NAME, f);
> + if (LOCATION_LOCUS (location) != UNKNOWN_LOCATION)
> + {
> + expanded_location loc;
> + fputs ("\" label: \"", f);
> + loc = expand_location (location);
> + fprintf (f, "%s:%d:%d", loc.file, loc.line, loc.column);
> + }
> + fputs ("\" }\n", f);
> +}
> +
> +/* Dump final cgraph node in VCG format. */
> +
> +static void
> +dump_final_node_vcg (FILE *f)
> +{
> + dump_final_node_vcg_start (f, current_function_decl);
> +
> + if (flag_stack_usage_info
> + || (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE))
> + output_stack_usage_1 (f);
> +
> + if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
> + {
> + fprintf (f, "\\n%u dynamic objects", vec_safe_length (cfun->su->dallocs));
> +
> + unsigned i;
> + callinfo_dalloc *cda;
> + FOR_EACH_VEC_SAFE_ELT (cfun->su->dallocs, i, cda)
> + {
> + expanded_location loc = expand_location (cda->location);
> + fprintf (f, "\\n %s", cda->name);
> + fprintf (f, " %s:%d:%d", loc.file, loc.line, loc.column);
> + }
> +
> + vec_free (cfun->su->dallocs);
> + cfun->su->dallocs = NULL;
> + }
> +
> + fputs ("\" }\n", f);
> +
> + unsigned i;
> + callinfo_callee *c;
> + FOR_EACH_VEC_SAFE_ELT (cfun->su->callees, i, c)
> + dump_final_callee_vcg (f, c->location, c->decl);
> + vec_free (cfun->su->callees);
> + cfun->su->callees = NULL;
> +
> + cgraph_node *cnode = cgraph_node::get (current_function_decl);
> + for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
> + if (CALLEE_FROM_CGRAPH_P (e->callee->decl))
> + dump_final_callee_vcg (f, gimple_location (e->call_stmt),
> + e->callee->decl);
> + for (cgraph_edge *e = cnode->indirect_calls; e; e = e->next_callee)
> + dump_final_callee_vcg (f, gimple_location (e->call_stmt), NULL);
> +}
> +
> +/* Output stack usage and callgraph info, as requested. */
> +void
> +output_stack_usage (void)
> +{
> + if (flag_callgraph_info)
> + dump_final_node_vcg (callgraph_info_file);
> + else
> + output_stack_usage_1 (NULL);
> +}
> +
> +/* Open an auxiliary or dump output file. */
> static FILE *
> open_auxiliary_file (const char *ext)
> {
> char *filename;
> FILE *file;
> + const char *base_name = aux_base_name;
>
> - filename = concat (aux_base_name, ".", ext, NULL);
> + if (in_lto_p)
> + base_name = dump_base_name;
> +
> + filename = concat (base_name, ".", ext, NULL);
> file = fopen (filename, "w");
> if (!file)
> fatal_error (input_location, "cannot open %s for writing: %m", filename);
> @@ -1900,6 +1992,17 @@ lang_dependent_init (const char *name)
> /* If stack usage information is desired, open the output file. */
> if (flag_stack_usage && !flag_generate_lto)
> stack_usage_file = open_auxiliary_file ("su");
> +
> + /* If call graph information is desired, open the output file. */
> + if (flag_callgraph_info && !flag_generate_lto)
> + {
> + callgraph_info_file = open_auxiliary_file ("ci");
> + /* Write the file header. */
> + fprintf (callgraph_info_file,
> + "graph: { title: \"%s\"\n", main_input_filename);
> + bitmap_obstack_initialize (NULL);
> + callgraph_info_external_printed = BITMAP_ALLOC (NULL);
> + }
> }
>
> /* This creates various _DECL nodes, so needs to be called after the
> @@ -2053,6 +2156,15 @@ finalize (bool no_backend)
> stack_usage_file = NULL;
> }
>
> + if (callgraph_info_file)
> + {
> + fputs ("}\n", callgraph_info_file);
> + fclose (callgraph_info_file);
> + callgraph_info_file = NULL;
> + BITMAP_FREE (callgraph_info_external_printed);
> + bitmap_obstack_release (NULL);
> + }
> +
> if (seen_error ())
> coverage_remove_note_file ();
>
>
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
next prev parent reply other threads:[~2019-11-04 8:28 UTC|newest]
Thread overview: 117+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-26 5:30 Alexandre Oliva
2019-10-26 8:12 ` Richard Biener
2019-10-26 11:21 ` Alexandre Oliva
2019-10-27 9:08 ` Alexandre Oliva
2019-10-28 8:38 ` Richard Biener
2019-10-30 10:12 ` Alexandre Oliva
2019-10-30 11:28 ` Richard Biener
2019-11-02 19:31 ` Alexandre Oliva
2019-11-04 8:28 ` Richard Biener [this message]
2019-11-06 10:53 ` Alexandre Oliva
2019-11-20 4:35 ` Alexandre Oliva
2019-11-20 9:16 ` Richard Biener
2019-11-06 15:38 ` Alexandre Oliva
2019-11-07 7:49 ` Richard Biener
2019-11-07 10:50 ` Alexandre Oliva
2019-11-07 11:48 ` Richard Biener
2019-11-07 12:30 ` Alexandre Oliva
2019-11-07 14:02 ` Richard Biener
2019-11-07 22:39 ` Alexandre Oliva
2019-11-08 8:28 ` Richard Biener
2019-11-08 23:12 ` Eric Gallager
2019-11-15 1:34 ` Alexandre Oliva
2019-11-15 1:01 ` Alexandre Oliva
2019-11-15 7:30 ` Alexandre Oliva
2019-11-15 8:08 ` Richard Biener
2019-11-15 22:50 ` Alexandre Oliva
2019-12-03 22:44 ` Alexandre Oliva
2019-12-09 9:41 ` Richard Biener
2019-12-12 1:14 ` Alexandre Oliva
2019-12-25 10:05 ` Alexandre Oliva
2019-12-26 19:00 ` drop -aux{dir,base}, revamp -dump{dir,base} (was: Re: introduce -fcallgraph-info option) Alexandre Oliva
2020-01-09 13:33 ` Richard Biener
2020-01-09 19:09 ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-01-16 11:06 ` Alexandre Oliva
2020-01-16 11:15 ` Alexandre Oliva
2020-01-17 2:14 ` Joseph Myers
2020-01-20 10:38 ` Richard Biener
2020-01-22 1:25 ` Alexandre Oliva
2020-01-22 8:15 ` Richard Biener
2020-01-23 20:06 ` Alexandre Oliva
2020-01-24 1:50 ` Alexandre Oliva
2020-05-19 8:51 ` Alexandre Oliva
2020-05-19 8:59 ` Alexandre Oliva
2020-05-19 9:29 ` Richard Biener
2020-05-19 8:59 ` Alexandre Oliva
2020-05-19 9:30 ` Richard Biener
2020-05-19 9:00 ` Alexandre Oliva
2020-05-19 9:04 ` Richard Biener
2020-05-22 0:32 ` Alexandre Oliva
2020-05-22 6:05 ` Richard Biener
2020-05-26 7:08 ` Alexandre Oliva
2020-05-26 8:52 ` Richard Biener
2020-05-26 9:02 ` Martin Liška
2020-05-26 10:00 ` Alexandre Oliva
2020-05-26 12:14 ` Alexandre Oliva
2020-05-26 13:52 ` Alexandre Oliva
2020-05-26 13:56 ` Richard Biener
2020-05-27 22:05 ` Alexandre Oliva
2020-05-27 23:01 ` Jeff Law
2020-06-02 11:52 ` Alexandre Oliva
2020-06-02 12:02 ` Richard Biener
2020-05-27 1:04 ` Broken build (was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Hans-Peter Nilsson
2020-05-27 14:30 ` Broken build Alexandre Oliva
2020-05-27 15:04 ` Hans-Peter Nilsson
2020-05-28 0:53 ` Alexandre Oliva
2020-05-28 0:39 ` Anthony Green
2020-06-02 11:29 ` Alexandre Oliva
2020-06-02 14:07 ` Hans-Peter Nilsson
2020-05-27 9:45 ` drop -aux{dir,base}, revamp -dump{dir,base} Andreas Schwab
2020-05-27 10:28 ` Andreas Schwab
2020-05-27 14:41 ` Alexandre Oliva
2020-05-27 14:59 ` Andreas Schwab
2020-06-09 12:29 ` Thomas Schwinge
2020-06-09 12:42 ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir, base}, revamp -dump{dir, base}) Martin Jambor
2020-06-09 18:31 ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Mike Stump
2020-06-11 14:28 ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir, base}, revamp -dump{dir, base}) Martin Jambor
2020-06-12 20:52 ` BRIG FE testsuite: Fix all dump-scans (Was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Mike Stump
2020-06-10 21:50 ` BRIG FE testsuite: Fix all dump-scans Alexandre Oliva
2020-06-23 9:44 ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-06-23 11:30 ` Martin Jambor
2020-06-09 13:08 ` Thomas Schwinge
2020-06-10 22:24 ` Alexandre Oliva
2020-06-17 10:50 ` Tobias Burnus
2020-06-18 2:58 ` Alexandre Oliva
2020-06-18 6:10 ` Alexandre Oliva
2020-06-18 9:41 ` Tobias Burnus
2020-06-18 10:39 ` Alexandre Oliva
2020-06-18 12:06 ` Tobias Burnus
2020-06-30 16:13 ` Thomas Schwinge
2020-07-14 5:46 ` Alexandre Oliva
2020-07-24 6:08 ` Thomas Schwinge
2020-07-24 17:54 ` Alexandre Oliva
2020-07-14 5:49 ` Alexandre Oliva
2020-06-19 9:53 ` Alexandre Oliva
2020-06-19 16:09 ` Tobias Burnus
2020-06-22 6:08 ` Alexandre Oliva
2020-06-22 7:07 ` Tobias Burnus
2020-06-22 14:32 ` Alexandre Oliva
2020-06-23 8:17 ` Richard Biener
2020-06-30 16:35 ` Thomas Schwinge
2020-07-24 12:06 ` Thomas Schwinge
2020-06-30 18:52 ` Thomas Schwinge
2020-07-14 4:48 ` Alexandre Oliva
2020-07-24 6:01 ` Thomas Schwinge
2020-07-24 18:00 ` Alexandre Oliva
2023-11-24 12:46 ` testsuite: Add 'only_for_offload_target' wrapper for 'scan-offload-tree-dump' etc. (was: drop -aux{dir,base}, revamp -dump{dir,base}) Thomas Schwinge
2020-06-23 9:50 ` drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2020-06-30 16:07 ` Thomas Schwinge
2020-07-23 21:12 ` [PR95720] protect gluefile and wrap_flags with -Wl too (was: Re: drop -aux{dir,base}, revamp -dump{dir,base}) Alexandre Oliva
2020-07-24 6:48 ` Richard Biener
2020-05-26 8:09 ` [wwwdocs] Re: drop -aux{dir,base}, revamp -dump{dir,base} Alexandre Oliva
2019-10-28 23:56 ` introduce -fcallgraph-info option Joseph Myers
2019-10-30 9:22 ` Alexandre Oliva
2019-10-30 9:43 ` Alexandre Oliva
2019-10-30 18:17 ` Joseph Myers
2019-11-06 21:27 ` Thomas Schwinge
2019-11-07 11:23 ` Alexandre Oliva
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=nycvar.YFH.7.76.1911040926580.5566@zhemvz.fhfr.qr \
--to=rguenther@suse.de \
--cc=ebotcazou@adacore.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=joseph@codesourcery.com \
--cc=oliva@adacore.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).