public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Alexandre Oliva <oliva@adacore.com>
To: Richard Biener <rguenther@suse.de>
Cc: gcc-patches@gcc.gnu.org, ebotcazou@adacore.com, joseph@codesourcery.com
Subject: Re: introduce -fcallgraph-info option
Date: Wed, 06 Nov 2019 10:53:00 -0000	[thread overview]
Message-ID: <ora799tgwf.fsf@livre.home> (raw)
In-Reply-To: <nycvar.YFH.7.76.1911040926580.5566@zhemvz.fhfr.qr> (Richard	Biener's message of "Mon, 4 Nov 2019 09:28:11 +0100 (CET)")

On Nov  4, 2019, Richard Biener <rguenther@suse.de> wrote:

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

*nod*, that makes sense to me.  After seeing your suggestion, I started
looking into how to do that, but didn't get very far yet.  For now, I've
split that bit out of the main patch.  So I'm installing the first, big
one, and not installing the latter, posted mainly so that the
documentation bit can be picked up.  Thanks!


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.
	(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          |   23 +++++
 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                 |  178 ++++++++++++++++++++++++++++++++++--------
 16 files changed, 397 insertions(+), 51 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..179452c 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,24 @@ 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 intermediate
+LTO output files.
+
 @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..18fea1c 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,6 +1005,115 @@ output_stack_usage (void)
     }
 }
 
+/* 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 output file.  */
 static FILE *
 open_auxiliary_file (const char *ext)
@@ -1900,6 +1988,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 +2152,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 ();
 


improve and document -flto -fcallgraph-info

From: Alexandre Oliva <oliva@adacore.com>

for  gcc/ChangeLog

	* toplev.c (open_auxiliary_file): Use dump_base_name for LTO
	partitions.
	* doc/invoke.texi (-fcallgraph-info): Adjust.
---
 gcc/doc/invoke.texi |    4 ++--
 gcc/toplev.c        |    8 ++++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 179452c..b7011b7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14580,8 +14580,8 @@ 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 intermediate
-LTO output files.
+may generate multiple callgraph information files next to the specified
+output file.
 
 @item -d@var{letters}
 @itemx -fdump-rtl-@var{pass}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 18fea1c..8aaf216 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1114,14 +1114,18 @@ output_stack_usage (void)
     output_stack_usage_1 (NULL);
 }
 
-/* Open an auxiliary output file.  */
+/* 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);


-- 
Alexandre Oliva, freedom fighter   he/him   https://FSFLA.org/blogs/lxo
Free Software Evangelist           Stallman was right, but he's left :(
GNU Toolchain Engineer    FSMatrix: It was he who freed the first of us
FSF & FSFLA board member                The Savior shall return (true);

  reply	other threads:[~2019-11-06 10:53 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
2019-11-06 10:53                 ` Alexandre Oliva [this message]
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=ora799tgwf.fsf@livre.home \
    --to=oliva@adacore.com \
    --cc=ebotcazou@adacore.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=rguenther@suse.de \
    /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).