From: Richard Biener <rguenther@suse.de>
To: Alexandre Oliva <oliva@adacore.com>,gcc-patches@gcc.gnu.org
Cc: ebotcazou@adacore.com,joseph@codesourcery.com
Subject: Re: introduce -fcallgraph-info option
Date: Sat, 26 Oct 2019 08:12:00 -0000 [thread overview]
Message-ID: <84223B6B-F6F0-4B94-835E-6661E1E1EB6A@suse.de> (raw)
In-Reply-To: <or1rv0run4.fsf@lxoliva.fsfla.org>
On October 26, 2019 6:35:43 AM GMT+02:00, Alexandre Oliva <oliva@adacore.com> wrote:
>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, 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.
>
>Compared with the earlier version, this patch does not modify cgraph,
>and instead adds the required information next to the stage usage
>function data structure, so we only hold one of those at at time. I've
>switched to vecs from linked lists, for more compact edges and dynamic
>allocation annotations, and arranged for them to be released as soon as
>we've printed out the information. I have NOT changed the file format,
>because existing tools such as gnatstack consume the current format.
>
>Regstrapped on x86_64-linux-gnu. Ok to install?
How does it relate to the LTO-dump utility we have now which can in theory provide a more complete view? Maybe some infrastructure can be shared here (the actual dumping of the cgraph?)
Thanks,
Richard.
>
>for gcc/ChangeLog
From Eric Botcazou <ebotcazou@adacore.com>, Alexandre Oliva
><oliva@adacore.com>
>
> * common.opt (-fcallgraph-info[=]): New option.
> * doc/invoke.texi (Debugging 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.
> (rest_of_handle_thread_prologue_and_epilogue): Release callees
> and dallocs after output_stack_usage.
> (record_final_call, record_dynamic_alloc): New.
> * function.h (struct callee, struct 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_indirect_emitted): 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_indirect_call_node_vcg): New.
> (dump_final_callee_vcg, dump_final_node_vcg): New.
> (output_stack_usage): New.
> (lang_dependent_init): Open and start file if
> -fcallgraph-info.
> (finalize): If callgraph_info_file is not null, finish it,
> close it, and reset callgraph info state.
>
>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 | 17 ++++
> gcc/explow.c | 5 +
> gcc/flag-types.h | 16 ++++
> gcc/function.c | 63 ++++++++++++++--
> gcc/function.h | 25 ++++++
> 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 | 169
>++++++++++++++++++++++++++++++++++--------
> 16 files changed, 381 insertions(+), 51 deletions(-)
>
>diff --git a/gcc/ada/gcc-interface/misc.c
>b/gcc/ada/gcc-interface/misc.c
>index 4abd4d5708a54..d68b37384ff7f 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 5d811f113c907..bd302383377ba 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 ae904473d0dc6..67c7c77598a3f 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 cc279f411d796..63d646fba2b42 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 1407d019d1404..545b842eade71 100644
>--- a/gcc/doc/invoke.texi
>+++ b/gcc/doc/invoke.texi
>@@ -583,8 +583,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
>@@ -14533,6 +14534,18 @@ 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-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.
>+
> @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 7eb854bca4a6d..83c786366c1aa 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);
> }
>
> /* Emit one stack probe at ADDRESS, an address within the stack. */
>diff --git a/gcc/flag-types.h b/gcc/flag-types.h
>index a2103282d469d..b23d3a271f1ee 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 a1c76a4dd7a84..152f927097c47 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,51 @@ 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)
>- output_stack_usage ();
>+ if (flag_stack_usage_info || flag_callgraph_info)
>+ {
>+ output_stack_usage ();
>+ vec_free (cfun->su->dallocs);
>+ cfun->su->dallocs = NULL;
>+ vec_free (cfun->su->callees);
>+ cfun->su->callees = NULL;
>+ }
>
> return 0;
> }
>
>+/* Record a final call to CALLEE at LOCATION. */
>+
>+void
>+record_final_call (tree callee, location_t location)
>+{
>+ struct 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 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 43ac5dffd2457..ec523765d6eec 100644
>--- a/gcc/function.h
>+++ b/gcc/function.h
>@@ -192,6 +192,18 @@ public:
> poly_int64 length;
> };
>
>+struct GTY(()) callee
>+{
>+ location_t location;
>+ tree decl;
>+};
>+
>+struct GTY(()) dalloc
>+{
>+ location_t location;
>+ char const *name;
>+};
>+
> class GTY(()) stack_usage
> {
> public:
>@@ -210,6 +222,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<callee, va_gc> *callees;
>+
>+ /* Dynamic allocations enocuntered within the function, if callgraph
>+ da is enabled. */
>+ vec<dalloc, va_gc> *dallocs;
> };
>
>#define current_function_static_stack_size
>(cfun->su->static_stack_size)
>@@ -406,6 +425,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 914bb8eb8d699..394f0fda9c98c 100644
>--- a/gcc/gimplify.c
>+++ b/gcc/gimplify.c
>@@ -1697,6 +1697,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 ef43dae12fb64..8916f7e4da0bb 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 10b9f108f8d06..f46b468a968e7 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 835d63556e6a8..6cccada4aeb1d 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 6dcbb2dcb1369..bd09ec4d7a7af 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 1d4fe6e8950cc..cbea48c486e3c 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 1c7002f5c37cd..016f6d688f324 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 bool callgraph_info_indirect_emitted = false;
> 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,22 @@ output_stack_usage (void)
> stack_usage += current_function_dynamic_stack_size;
> }
>
>- if (stack_usage_file)
>+ if (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
> {
>- 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, '.');
>- }
>- }
>+ if (stack_usage)
>+ fprintf (cf, "\\n" HOST_WIDE_INT_PRINT_DEC " bytes (%s)",
>+ stack_usage,
>+ stack_usage_kind_str[stack_usage_kind]);
> else
>- {
>- const char *dot = strrchr (name, '.');
>- if (dot)
>- name = dot + 1;
>- }
>+ fputs ("\\n0 bytes", cf);
>+ }
>
>- 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]);
>+ if (stack_usage_file)
>+ {
>+ 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 +1010,106 @@ output_stack_usage (void)
> }
> }
>
>+/* Dump placeholder node for indirect calls in VCG format. */
>+
>+#define INDIRECT_CALL_NAME "__indirect_call"
>+
>+static void
>+dump_final_indirect_call_node_vcg (FILE *f)
>+{
>+ if (callgraph_info_indirect_emitted)
>+ return;
>+
>+ fputs ("node: { title: \"", f);
>+ fputs (INDIRECT_CALL_NAME, f);
>+ fputs ("\" label: \"", f);
>+ fputs ("Indirect Call Placeholder", f);
>+ fputs ("\" shape : ellipse }\n", f);
>+ callgraph_info_indirect_emitted = true;
>+}
>+
>+/* Dump final cgraph edge in VCG format. */
>+
>+static void
>+dump_final_callee_vcg (FILE *f, struct callee *callee)
>+{
>+ fputs ("edge: { sourcename: \"", f);
>+ print_decl_identifier (f, current_function_decl,
>PRINT_DECL_UNIQUE_NAME);
>+ fputs ("\" targetname: \"", f);
>+ if (callee->decl)
>+ print_decl_identifier (f, callee->decl, PRINT_DECL_UNIQUE_NAME);
>+ else
>+ fputs (INDIRECT_CALL_NAME, f);
>+ if (LOCATION_LOCUS (callee->location) != UNKNOWN_LOCATION)
>+ {
>+ expanded_location loc;
>+ fputs ("\" label: \"", f);
>+ loc = expand_location (callee->location);
>+ fprintf (f, "%s:%d:%d", loc.file, loc.line, loc.column);
>+ }
>+ fputs ("\" }\n", f);
>+
>+ if (!callee->decl)
>+ dump_final_indirect_call_node_vcg (f);
>+}
>+
>+/* Dump final cgraph node in VCG format. */
>+
>+static void
>+dump_final_node_vcg (FILE *f)
>+{
>+ fputs ("node: { title: \"", f);
>+ print_decl_identifier (f, current_function_decl,
>PRINT_DECL_UNIQUE_NAME);
>+ fputs ("\" label: \"", f);
>+ print_decl_identifier (f, current_function_decl, PRINT_DECL_NAME);
>+ fputs ("\\n", f);
>+ print_decl_identifier (f, current_function_decl, PRINT_DECL_ORIGIN);
>+
>+ if (DECL_EXTERNAL (current_function_decl))
>+ {
>+ fputs ("\" shape : ellipse }\n", f);
>+ return;
>+ }
>+
>+ 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;
>+ 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);
>+ }
>+ }
>+
>+ fputs ("\" }\n", f);
>+
>+ if (flag_callgraph_info)
>+ {
>+ unsigned i;
>+ callee *c;
>+ FOR_EACH_VEC_SAFE_ELT (cfun->su->callees, i, c)
>+ dump_final_callee_vcg (f, c);
>+ }
>+}
>+
>+/* 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 +1984,15 @@ 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);
>+ }
> }
>
> /* This creates various _DECL nodes, so needs to be called after the
>@@ -2044,6 +2137,14 @@ 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;
>+ callgraph_info_indirect_emitted = false;
>+ }
>+
> if (seen_error ())
> coverage_remove_note_file ();
>
next prev parent reply other threads:[~2019-10-26 7: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 [this message]
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
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=84223B6B-F6F0-4B94-835E-6661E1E1EB6A@suse.de \
--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).