public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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)

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