This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Implement -fcallgraph-info


Hi,

To be applied on top of the -fstack-usage patch, still related to:
 http://www.gccsummit.org/2005/view_abstract.php?content_key=18

Even comes with a basic Perl script to merge and analyze *.ci files.

Tested on i586-suse-linux.


2006-06-19  Eric Botcazou  <ebotcazou@adacore.com>

	Callgraph info support
	* common.opt (-fcallgraph-info): New option.
	(-fcallgraph-info=): Likewise.
	* doc/invoke.texi (Debugging options): Document them.
	* flags.h (flag_stack_usage_info): New flag.
	(flag_callgraph_info): Likewise.
	* opts.c (common_handle_option): Handle -fcallgraph-info and
	-fcallgraph-info=.  Set flag_stack_usage_info to 1 if -fstack-usage.
	* cgraph.h (stack_usage_kind): New enumeration.
	(struct cgraph_rtl_info): Add stack_usage and stack_usage_kind fields.
	(struct cgraph_node): Add indirect_calls field.
	(dump_cgraph_node_vcg): Declare.
	(dump_cgraph_edge_vcg): Likewise.
	(callgraph_info_file): Likewise.
	(finish_cgraph): Likewise.
	* cgraph.c (dump_cgraph_indirect_call_node_vcg): New function.
	(dump_cgraph_node_vcg): Likewise.
	(dump_cgraph_edge_vcg): Likewise.
	* cgraphunit.c (callgraph_info_file): New global variable.
	(cgraph_create_edges): Record indirect calls.
	(rebuild_cgraph_edges): Likewise.
	(cgraph_expand_function): If -fcallgraph-info, dump the node.
	(init_cgraph): If -fcallgraph-info, open the associated file.
	(finish_cgraph): New function.
	* explow.c (allocate_dynamic_stack_space): Test flag_stack_usage_info
	instead of flag_stack_usage.
	* function.c (instantiate_virtual_regs): Likewise.
	* flow.c (rest_of_handle_flow2): Likewise.
	* langhooks.c (lhd_print_decl_source_location): New function.
	* langhooks.h (lang_hooks): New method 'print_decl_source_location'.
	* langhooks-def.h (lhd_print_decl_source_location): Declare it.
	(LANG_HOOKS_PRINT_DECL_SOURCE_LOCATION): Define to above.
	(LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_PRINT_DECL_SOURCE_LOCATION.
	* print-tree.c (print_decl_identifier): New function.
	* tree.h (print_decl_identifier): Declare it.
	(PRINT_DECL_ORIGIN, PRINT_DECL_NAME, PRINT_DECL_UNIQUE_NAME): New.
	* tree-optimize.c (tree_rest_of_compilation): If -fcallgraph-info,
	dump the callee edges before discarding them.  Remove redundant code.
	* toplev.c (flag_stack_usage_info): New flag.
	(flag_callgraph_info): Likewise.
	(output_stack_usage): If -fcallgraph-info=su, set stack_usage_kind
	and stack_usage of associated callgraph node.  If -fstack-usage, use
	print_decl_identifier for pretty-printing.
	(open_auxiliary_file): Export.
	(finalize): Invoke finish_cgraph.
	* toplev.h (open_auxiliary_file): Declare.



-- 
Eric Botcazou
*** gcc/common.opt.0	2006-06-19 15:39:05.783262568 +0200
--- gcc/common.opt	2006-06-19 15:39:13.760049912 +0200
*************** fcaller-saves
*** 327,332 ****
--- 327,340 ----
  Common Report Var(flag_caller_saves)
  Save registers around function calls
  
+ fcallgraph-info
+ Common RejectNegative
+ Output callgraph information on a per-file basis
+ 
+ fcallgraph-info=
+ Common RejectNegative Joined
+ Output callgraph information on a per-file basis with decorations
+ 
  fcommon
  Common Report Var(flag_no_common,0)
  Do not put uninitialized globals in the common section
*** gcc/doc/invoke.texi.0	2006-06-19 15:39:05.818257248 +0200
--- gcc/doc/invoke.texi	2006-06-19 15:39:13.798044136 +0200
*************** Objective-C and Objective-C++ Dialects}.
*** 287,292 ****
--- 287,293 ----
  -fdump-tree-vrp@r{[}-@var{n}@r{]} @gol
  -ftree-vectorizer-verbose=@var{n} @gol
  -fdump-tree-storeccp@r{[}-@var{n}@r{]} @gol
+ -fcallgraph-info@r{[}=su@r{]} @gol
  -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
  -feliminate-unused-debug-symbols -femit-class-debug-always @gol
  -fmem-report -fprofile-arcs @gol
*************** the function.  If it is not present, the
*** 3683,3688 ****
--- 3684,3699 ----
  not bounded at compile-time and the second field only represents the
  bounded part.
  
+ @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; only
+ @code{su} is supported for the time being and is equivalent to
+ @option{-fstack-usage}.
+ 
  @item -fprofile-arcs
  @opindex fprofile-arcs
  Add code so that program flow @dfn{arcs} are instrumented.  During
*** gcc/flags.h.0	2006-06-19 15:39:05.827255880 +0200
--- gcc/flags.h	2006-06-19 15:39:13.800043832 +0200
*************** extern int flag_var_tracking;
*** 250,255 ****
--- 250,263 ----
     warning message in case flag was set by -fprofile-{generate,use}.  */
  extern bool flag_speculative_prefetching_set;
  
+ /* Compute stack usage information on a per-function basis.  */
+ extern int flag_stack_usage_info;
+ 
+ /* Type of callgraph info.  */
+ #define CALLGRAPH_INFO_NAKED        0x1
+ #define CALLGRAPH_INFO_STACK_USAGE  0x2
+ extern int flag_callgraph_info;
+ 
  /* A string that's used when a random name is required.  NULL means
     to make it really random.  */
  
*** gcc/opts.c.0	2006-06-19 15:39:05.847252840 +0200
--- gcc/opts.c	2006-06-19 15:39:13.802043528 +0200
*************** common_handle_option (size_t scode, cons
*** 778,783 ****
--- 778,797 ----
        fix_register (arg, 0, 0);
        break;
  
+     case OPT_fcallgraph_info:
+       flag_callgraph_info |= CALLGRAPH_INFO_NAKED;
+       break;
+ 
+     case OPT_fcallgraph_info_:
+       if (!strcmp (arg, "su"))
+ 	{
+ 	  flag_callgraph_info |= CALLGRAPH_INFO_STACK_USAGE;
+ 	  flag_stack_usage_info = 1;
+ 	}
+       else
+ 	return 0;
+       break;
+ 
      case OPT_fdiagnostics_show_location_:
        if (!strcmp (arg, "once"))
  	diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
*************** common_handle_option (size_t scode, cons
*** 930,935 ****
--- 944,955 ----
        stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg));
        break;
  
+     case OPT_fstack_usage:
+       flag_stack_usage = value;
+       if (value)
+ 	flag_stack_usage_info = 1;
+       break;
+ 
      case OPT_ftree_vectorizer_verbose_:
        vect_set_verbosity_level (arg);
        break;
*** gcc/cgraph.c.0	2006-06-19 15:39:05.856251472 +0200
--- gcc/cgraph.c	2006-06-19 15:39:13.804043224 +0200
*************** dump_varpool (FILE *f)
*** 722,727 ****
--- 722,815 ----
      dump_cgraph_varpool_node (f, node);
  }
  
+ #define INDIRECT_CALL_NAME  "__indirect_call"
+ 
+ static void
+ dump_cgraph_indirect_call_node_vcg (FILE *f)
+ {
+   static bool emitted = false;
+   if (emitted)
+     return;
+ 
+   fputs ("node: { title: \"", f);
+   fputs (INDIRECT_CALL_NAME, f);
+   fputs ("\" label: \"", f);
+   fputs ("Indirect Call Placeholder", f);
+   fputs ("\" shape : ellipse }\n", f);
+   emitted = true;
+ }
+ 
+ /* Dump cgraph node in VCG format.  */
+ 
+ void
+ dump_cgraph_node_vcg (FILE *f, struct cgraph_node *node)
+ {
+   fputs ("node: { title: \"", f);
+   print_decl_identifier (f, node->decl, PRINT_DECL_UNIQUE_NAME);
+   fputs ("\" label: \"", f);
+   print_decl_identifier (f, node->decl, PRINT_DECL_NAME);
+   fputs ("\\n", f);
+   print_decl_identifier (f, node->decl, PRINT_DECL_ORIGIN);
+ 
+   if (DECL_EXTERNAL (node->decl))
+     {
+       fputs ("\" shape : ellipse }\n", f);
+       return;
+     }
+ 
+   if (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
+     {
+       if (node->rtl.stack_usage)
+ 	{
+ 	  const char *qualifiers;
+ 	  fprintf (f, "\\n"HOST_WIDE_INT_PRINT_DEC" bytes (",
+ 		   node->rtl.stack_usage);
+ 	  switch (node->rtl.stack_usage_kind)
+ 	    {
+ 	    case STATIC:
+ 	      qualifiers = "static";
+ 	      break;
+ 	    case DYNAMIC:
+ 	    default:
+ 	      qualifiers = "dynamic";
+ 	      break;
+ 	    case DYNAMIC_BOUNDED:
+ 	      qualifiers = "dynamic,bounded";
+ 	      break;
+ 	    }
+ 	  fprintf (f, "%s)", qualifiers);
+ 	}
+       else
+ 	fputs ("\\n0 bytes", f);
+     }
+ 
+   fputs ("\" }\n", f);
+ 
+   if (node->indirect_calls)
+     {
+       struct cgraph_edge fake_edge;
+       fake_edge.caller = node;
+       fake_edge.callee = 0;
+       dump_cgraph_edge_vcg (f, &fake_edge);
+       dump_cgraph_indirect_call_node_vcg (f);
+     }
+ }
+ 
+ /* Dump cgraph edge in VCG format.  */
+ 
+ void
+ dump_cgraph_edge_vcg (FILE *f, struct cgraph_edge *edge)
+ {
+   fputs ("edge: { sourcename: \"", f);
+   print_decl_identifier (f, edge->caller->decl, PRINT_DECL_UNIQUE_NAME);
+   fputs ("\" targetname: \"", f);
+   if (edge->callee)
+     print_decl_identifier (f, edge->callee->decl, PRINT_DECL_UNIQUE_NAME);
+   else
+     fputs (INDIRECT_CALL_NAME, f);
+   fputs ("\" priority: 100 linestyle: solid }\n", f);
+ }
+ 
  /* Returns a hash code for P.  */
  
  static hashval_t
*** gcc/cgraphunit.c.0	2006-06-19 15:39:05.871249192 +0200
--- gcc/cgraphunit.c	2006-06-19 15:39:13.808042616 +0200
*************** static void cgraph_output_pending_asms (
*** 180,185 ****
--- 180,186 ----
  static struct pointer_set_t *visited_nodes;
  
  static FILE *cgraph_dump_file;
+ FILE *callgraph_info_file = NULL;
  
  /* Determine if function DECL is needed.  That is, visible to something
     either outside this translation unit, something magic in the system
*************** cgraph_create_edges (struct cgraph_node 
*** 569,581 ****
        {
  	tree stmt = bsi_stmt (bsi);
  	tree call = get_call_expr_in (stmt);
- 	tree decl;
  
! 	if (call && (decl = get_callee_fndecl (call)))
  	  {
! 	    cgraph_create_edge (node, cgraph_node (decl), stmt,
! 				bb->count,
! 				bb->loop_depth);
  	    walk_tree (&TREE_OPERAND (call, 1),
  		       record_reference, node, visited_nodes);
  	    if (TREE_CODE (stmt) == MODIFY_EXPR)
--- 570,585 ----
        {
  	tree stmt = bsi_stmt (bsi);
  	tree call = get_call_expr_in (stmt);
  
! 	if (call)
  	  {
! 	    tree decl = get_callee_fndecl (call);
! 	    if (decl)
! 	      cgraph_create_edge (node, cgraph_node (decl), stmt,
! 				  bb->count,
! 				  bb->loop_depth);
! 	    else
! 	      node->indirect_calls = true;
  	    walk_tree (&TREE_OPERAND (call, 1),
  		       record_reference, node, visited_nodes);
  	    if (TREE_CODE (stmt) == MODIFY_EXPR)
*************** rebuild_cgraph_edges (void)
*** 644,655 ****
        {
  	tree stmt = bsi_stmt (bsi);
  	tree call = get_call_expr_in (stmt);
- 	tree decl;
  
! 	if (call && (decl = get_callee_fndecl (call)))
! 	  cgraph_create_edge (node, cgraph_node (decl), stmt,
! 			      bb->count,
! 			      bb->loop_depth);
        }
    initialize_inline_failed (node);
    gcc_assert (!node->global.inlined_to);
--- 648,664 ----
        {
  	tree stmt = bsi_stmt (bsi);
  	tree call = get_call_expr_in (stmt);
  
! 	if (call)
! 	  {
! 	    tree decl = get_callee_fndecl (call);
! 	    if (decl)
! 	      cgraph_create_edge (node, cgraph_node (decl), stmt,
! 				  bb->count,
! 				  bb->loop_depth);
! 	    else
! 	      node->indirect_calls = true;
! 	  }
        }
    initialize_inline_failed (node);
    gcc_assert (!node->global.inlined_to);
*************** cgraph_expand_function (struct cgraph_no
*** 1115,1120 ****
--- 1124,1132 ----
    /* ??? Can happen with nested function of extern inline.  */
    gcc_assert (TREE_ASM_WRITTEN (node->decl));
  
+   if (flag_callgraph_info)
+     dump_cgraph_node_vcg (callgraph_info_file, node);
+ 
    current_function_decl = NULL;
    if (!cgraph_preserve_function_body_p (node->decl))
      {
*************** void
*** 1561,1566 ****
--- 1573,1602 ----
  init_cgraph (void)
  {
    cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
+ 
+   if (flag_callgraph_info)
+     {
+       callgraph_info_file = open_auxiliary_file ("ci");
+       fprintf (callgraph_info_file,
+ 	       "graph: { title: \"%s\"\n", main_input_filename);
+     }
+ }
+ 
+ void finish_cgraph (void)
+ {
+   if (callgraph_info_file)
+     {
+       struct cgraph_node *node;
+       /* Output nodes for external functions.  */
+       for (node = cgraph_nodes; node ; node = node->next)
+ 	if (DECL_EXTERNAL (node->decl) && !DECL_ARTIFICIAL (node->decl))
+ 	  dump_cgraph_node_vcg (callgraph_info_file, node);
+       fputs ("}\n", callgraph_info_file);
+       fclose (callgraph_info_file);
+     }
+ 
+   if (cgraph_dump_file)
+     dump_end (TDI_cgraph, cgraph_dump_file);
  }
  
  /* The edges representing the callers of the NEW_VERSION node were
*** gcc/cgraph.h.0	2006-06-19 15:39:05.879247976 +0200
--- gcc/cgraph.h	2006-06-19 15:41:06.886852024 +0200
*************** struct cgraph_global_info GTY(())
*** 101,111 ****
--- 101,122 ----
    bool inlined;
  };
  
+ /* Kind of stack usage associated with the function.  See the
+    -fstack-usage option in the manual for a detailed description.  */
+ enum stack_usage_kind
+ {
+   STATIC = 0,
+   DYNAMIC,
+   DYNAMIC_BOUNDED
+ };
+ 
  /* Information about the function that is propagated by the RTL backend.
     Available only for functions that has been already assembled.  */
  
  struct cgraph_rtl_info GTY(())
  {
+    HOST_WIDE_INT stack_usage;
+    enum stack_usage_kind stack_usage_kind;
     int preferred_incoming_stack_boundary;
  };
  
*************** struct cgraph_node GTY((chain_next ("%h.
*** 164,169 ****
--- 175,182 ----
    unsigned externally_visible : 1;
    /* Set for aliases once they got through assemble_alias.  */
    unsigned alias : 1;
+   /* Set when function contains indirect calls.  */
+   unsigned indirect_calls : 1;
  
    /* In non-unit-at-a-time mode the function body of inline candidates is saved
       into clone before compiling so the function in original form can be
*************** extern GTY(()) int cgraph_order;
*** 255,260 ****
--- 268,275 ----
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
  void dump_cgraph_node (FILE *, struct cgraph_node *);
+ void dump_cgraph_node_vcg (FILE *, struct cgraph_node *);
+ void dump_cgraph_edge_vcg (FILE *, struct cgraph_edge *);
  void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
  void dump_varpool (FILE *);
  void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
*************** struct cgraph_node *cgraph_master_clone 
*** 298,303 ****
--- 313,319 ----
  void cgraph_add_new_function (tree);
  
  /* In cgraphunit.c  */
+ extern FILE *callgraph_info_file;
  bool cgraph_assemble_pending_functions (void);
  bool cgraph_varpool_assemble_pending_decls (void);
  void cgraph_finalize_function (tree, bool);
*************** void verify_cgraph_node (struct cgraph_n
*** 312,317 ****
--- 328,334 ----
  void cgraph_build_static_cdtor (char which, tree body, int priority);
  void cgraph_reset_static_var_maps (void);
  void init_cgraph (void);
+ void finish_cgraph (void);
  struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
  						VEC(cgraph_edge_p,heap)*,
  						varray_type);
*** gcc/explow.c.0	2006-06-19 15:39:05.891246152 +0200
--- gcc/explow.c	2006-06-19 15:39:13.814041704 +0200
*************** allocate_dynamic_stack_space (rtx size, 
*** 1109,1115 ****
    /* If stack usage info is requested, look into the size we are passed.
       We need to do so this early to avoid the obfuscation that may be
       introduced later by the various alignment operations.  */
!   if (flag_stack_usage)
      {
        if (GET_CODE (size) == CONST_INT)
  	stack_usage_size = INTVAL (size);
--- 1109,1115 ----
    /* If stack usage info is requested, look into the size we are passed.
       We need to do so this early to avoid the obfuscation that may be
       introduced later by the various alignment operations.  */
!   if (flag_stack_usage_info)
      {
        if (GET_CODE (size) == CONST_INT)
  	stack_usage_size = INTVAL (size);
*************** allocate_dynamic_stack_space (rtx size, 
*** 1173,1179 ****
  					BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
  			 NULL_RTX);
  
!       if (flag_stack_usage)
  	stack_usage_size += BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1;
  
        known_align_valid = false;
--- 1173,1179 ----
  					BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
  			 NULL_RTX);
  
!       if (flag_stack_usage_info)
  	stack_usage_size += BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1;
  
        known_align_valid = false;
*************** allocate_dynamic_stack_space (rtx size, 
*** 1203,1209 ****
        /* The above dynamic offset cannot be computed statically at this
  	 point, but it will be possible to do so after RTL expansion is
  	 done.  Record how many times we will need to add it.  */
!       if (flag_stack_usage)
  	current_function_dynamic_alloc_count++;
  
        known_align_valid = false;
--- 1203,1209 ----
        /* The above dynamic offset cannot be computed statically at this
  	 point, but it will be possible to do so after RTL expansion is
  	 done.  Record how many times we will need to add it.  */
!       if (flag_stack_usage_info)
  	current_function_dynamic_alloc_count++;
  
        known_align_valid = false;
*************** allocate_dynamic_stack_space (rtx size, 
*** 1227,1233 ****
      {
        size = round_push (size);
  
!       if (flag_stack_usage)
  	{
  	  int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
  	  stack_usage_size = (stack_usage_size + align - 1) / align * align;
--- 1227,1233 ----
      {
        size = round_push (size);
  
!       if (flag_stack_usage_info)
  	{
  	  int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
  	  stack_usage_size = (stack_usage_size + align - 1) / align * align;
*************** allocate_dynamic_stack_space (rtx size, 
*** 1236,1242 ****
  
    /* The size is supposed to be fully adjusted at this point so record it
       if stack usage info is requested.  */
!   if (flag_stack_usage)
      {
        current_function_dynamic_stack_size += stack_usage_size;
  
--- 1236,1242 ----
  
    /* The size is supposed to be fully adjusted at this point so record it
       if stack usage info is requested.  */
!   if (flag_stack_usage_info)
      {
        current_function_dynamic_stack_size += stack_usage_size;
  
*** gcc/function.c.0	2006-06-19 15:39:05.907243720 +0200
--- gcc/function.c	2006-06-19 15:39:13.819040944 +0200
*************** instantiate_virtual_regs (void)
*** 1729,1735 ****
  
    /* See allocate_dynamic_stack_space for the rationale.  */
  #ifdef SETJMP_VIA_SAVE_AREA
!   if (flag_stack_usage && current_function_calls_setjmp)
      {
        int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
        dynamic_offset = (dynamic_offset + align - 1) / align * align;
--- 1729,1735 ----
  
    /* See allocate_dynamic_stack_space for the rationale.  */
  #ifdef SETJMP_VIA_SAVE_AREA
!   if (flag_stack_usage_info && current_function_calls_setjmp)
      {
        int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
        dynamic_offset = (dynamic_offset + align - 1) / align * align;
*** gcc/flow.c.0	2006-06-19 15:39:05.927240680 +0200
--- gcc/flow.c	2006-06-19 15:39:13.824040184 +0200
*************** rest_of_handle_flow2 (void)
*** 4700,4706 ****
      cleanup_cfg (CLEANUP_EXPENSIVE);
  
    /* The IA-64 port invalidates its static stack usage info right after.  */
!   if (flag_stack_usage)
      output_stack_usage ();
  
    /* On some machines, the prologue and epilogue code, or parts thereof,
--- 4700,4706 ----
      cleanup_cfg (CLEANUP_EXPENSIVE);
  
    /* The IA-64 port invalidates its static stack usage info right after.  */
!   if (flag_stack_usage_info)
      output_stack_usage ();
  
    /* On some machines, the prologue and epilogue code, or parts thereof,
*** gcc/langhooks.c.0	2006-06-19 15:39:05.936239312 +0200
--- gcc/langhooks.c	2006-06-19 15:39:13.825040032 +0200
*************** lhd_print_tree_nothing (FILE * ARG_UNUSE
*** 116,121 ****
--- 116,134 ----
  {
  }
  
+ void
+ lhd_print_decl_source_location (FILE *file, tree decl, int indent)
+ {
+   expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
+   indent_to (file, indent);
+ #ifdef USE_MAPPED_LOCATION
+   if (flag_show_column && xloc.column != 0)
+     fprintf (file, "%s:%d:%d", xloc.file, xloc.line, xloc.column)
+   else
+ #endif
+   fprintf (file, "%s:%d", xloc.file, xloc.line);
+ }
+ 
  /* Called from safe_from_p.  */
  
  int
*** gcc/langhooks.h.0	2006-06-19 15:39:05.939238856 +0200
--- gcc/langhooks.h	2006-06-19 15:39:13.827039728 +0200
*************** struct lang_hooks
*** 371,376 ****
--- 371,377 ----
    /* Called to print language-dependent parts of tcc_decl, tcc_type,
       and IDENTIFIER_NODE nodes.  */
    lang_print_tree_hook print_decl;
+   lang_print_tree_hook print_decl_source_location;
    lang_print_tree_hook print_type;
    lang_print_tree_hook print_identifier;
  
*** gcc/langhooks-def.h.0	2006-06-19 15:39:05.946237792 +0200
--- gcc/langhooks-def.h	2006-06-19 15:39:13.829039424 +0200
*************** extern tree lhd_do_nothing_iii_return_nu
*** 52,57 ****
--- 52,58 ----
  extern int lhd_safe_from_p (rtx, tree);
  extern tree lhd_staticp (tree);
  extern void lhd_print_tree_nothing (FILE *, tree, int);
+ extern void lhd_print_decl_source_location (FILE *, tree, int);
  extern const char *lhd_decl_printable_name (tree, int);
  extern const char *lhd_dwarf_name (tree, int);
  extern int lhd_types_compatible_p (tree, tree);
*************** extern void lhd_omp_firstprivatize_type_
*** 121,126 ****
--- 122,128 ----
  #define LANG_HOOKS_PRINT_STATISTICS	lhd_do_nothing
  #define LANG_HOOKS_PRINT_XNODE		lhd_print_tree_nothing
  #define LANG_HOOKS_PRINT_DECL		lhd_print_tree_nothing
+ #define LANG_HOOKS_PRINT_DECL_SOURCE_LOCATION lhd_print_decl_source_location
  #define LANG_HOOKS_PRINT_TYPE		lhd_print_tree_nothing
  #define LANG_HOOKS_PRINT_IDENTIFIER	lhd_print_tree_nothing
  #define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
*************** extern tree lhd_make_node (enum tree_cod
*** 308,313 ****
--- 310,316 ----
    LANG_HOOKS_PRINT_STATISTICS, \
    LANG_HOOKS_PRINT_XNODE, \
    LANG_HOOKS_PRINT_DECL, \
+   LANG_HOOKS_PRINT_DECL_SOURCE_LOCATION, \
    LANG_HOOKS_PRINT_TYPE, \
    LANG_HOOKS_PRINT_IDENTIFIER, \
    LANG_HOOKS_DECL_PRINTABLE_NAME, \
*** gcc/print-tree.c.0	2006-06-19 15:39:05.963235208 +0200
--- gcc/print-tree.c	2006-06-19 15:39:13.831039120 +0200
*************** print_node (FILE *file, const char *pref
*** 866,868 ****
--- 866,927 ----
  
    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 *malloced_name = NULL;
+   char p;
+ 
+   if (flags & PRINT_DECL_ORIGIN)
+     {
+       lang_hooks.print_decl_source_location (file, decl, 0);
+       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 = malloced_name = concat (main_input_filename, ":", name, NULL);
+     }
+   else if (flags & PRINT_DECL_NAME)
+     {
+       const char *dot;
+ 
+       name = lang_hooks.decl_printable_name (decl, 2);
+       dot = strrchr (name, '.');
+       if (dot)
+ 	name = dot + 1;
+     }
+   else
+     return;
+ 
+   if (needs_colon)
+     fputc (':', file);
+ 
+   while ((p = *name++) != 0)
+     {
+       /* Strip double-quotes because of VCG.  */
+       if (p == '"')
+ 	continue;
+       fputc (p, file);
+     }
+ 
+   if (malloced_name)
+     free (malloced_name);
+ }
*** gcc/tree.h.0	2006-06-19 15:39:05.980232624 +0200
--- gcc/tree.h	2006-06-19 15:39:13.836038360 +0200
*************** extern void print_node (FILE *, const ch
*** 4338,4343 ****
--- 4338,4347 ----
  extern void print_node_brief (FILE *, const char *, 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);
  
  /* In tree-inline.c:  */
  extern bool debug_find_tree (tree, tree);
*** gcc/tree-optimize.c.0	2006-06-19 15:39:05.987231560 +0200
--- gcc/tree-optimize.c	2006-06-19 15:39:13.837038208 +0200
*************** tree_rest_of_compilation (tree fndecl)
*** 393,413 ****
  	  timevar_pop (TV_INTEGRATION);
  	}
      }
    /* We are not going to maintain the cgraph edges up to date.
       Kill it so it won't confuse us.  */
    while (node->callees)
      {
!       /* In non-unit-at-a-time we must mark all referenced functions as needed.
!          */
        if (node->callees->callee->analyzed && !flag_unit_at_a_time)
          cgraph_mark_needed_node (node->callees->callee);
-       cgraph_remove_edge (node->callees);
-     }
  
!   /* We are not going to maintain the cgraph edges up to date.
!      Kill it so it won't confuse us.  */
!   cgraph_node_remove_callees (node);
  
  
    /* Initialize the default bitmap obstack.  */
    bitmap_obstack_initialize (NULL);
--- 393,413 ----
  	  timevar_pop (TV_INTEGRATION);
  	}
      }
+ 
    /* We are not going to maintain the cgraph edges up to date.
       Kill it so it won't confuse us.  */
    while (node->callees)
      {
!       /* In non-unit-at-a-time mode, we must mark all referenced functions
! 	 as needed. */
        if (node->callees->callee->analyzed && !flag_unit_at_a_time)
          cgraph_mark_needed_node (node->callees->callee);
  
!       if (flag_callgraph_info)
!         dump_cgraph_edge_vcg (callgraph_info_file, node->callees);
  
+       cgraph_remove_edge (node->callees);
+     }
  
    /* Initialize the default bitmap obstack.  */
    bitmap_obstack_initialize (NULL);
*** gcc/toplev.c.0	2006-06-19 15:39:05.996230192 +0200
--- gcc/toplev.c	2006-06-19 15:39:13.857035168 +0200
*************** int flag_renumber_insns = 1;
*** 339,344 ****
--- 339,350 ----
     to optimize, debug_info_level and debug_hooks in process_options ().  */
  int flag_var_tracking = AUTODETECT_VALUE;
  
+ /* Compute stack usage information on a per-function basis.  */
+ int flag_stack_usage_info;
+ 
+ /* Output callgraph information on a per-file basis.  */
+ int flag_callgraph_info;
+ 
  /* True if the user has tagged the function with the 'section'
     attribute.  */
  
*************** void
*** 1437,1451 ****
  output_stack_usage (void)
  {
    static bool warning_issued = false;
-   enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED };
    const char *stack_usage_kind_str[] = {
      "static",
      "dynamic",
      "dynamic,bounded"
    };
    HOST_WIDE_INT stack_usage = -1;
!   enum stack_usage_kind_type stack_usage_kind;
!   const char *raw_id, *id;
  
    /* Rely on the back-end to compute the maximum static stack usage.
       The back-end needs this information at one point or another to
--- 1443,1455 ----
  output_stack_usage (void)
  {
    static bool warning_issued = false;
    const char *stack_usage_kind_str[] = {
      "static",
      "dynamic",
      "dynamic,bounded"
    };
    HOST_WIDE_INT stack_usage = -1;
!   enum stack_usage_kind stack_usage_kind;
  
    /* Rely on the back-end to compute the maximum static stack usage.
       The back-end needs this information at one point or another to
*************** output_stack_usage (void)
*** 1485,1509 ****
        stack_usage += current_function_dynamic_stack_size;
      }
  
!   /* Strip the scope prefix if any.  */
!   raw_id = lang_hooks.decl_printable_name (current_function_decl, 2);
!   id = strrchr (raw_id, '.');
!   if (id)
!     id++;
!   else
!     id = raw_id;
  
!   fprintf (stack_usage_file,
! 	   "%s:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
! 	   basename (DECL_SOURCE_FILE (current_function_decl)),
! 	   DECL_SOURCE_LINE (current_function_decl),
! 	   id,
! 	   stack_usage,
! 	   stack_usage_kind_str[stack_usage_kind]);
  }
  
  /* Open an auxiliary output file.  */
! static FILE *
  open_auxiliary_file (const char *ext)
  {
    char *filename;
--- 1489,1512 ----
        stack_usage += current_function_dynamic_stack_size;
      }
  
!   if (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
!     {
!       struct cgraph_rtl_info *cgi = cgraph_rtl_info (current_function_decl);
!       cgi->stack_usage = stack_usage;
!       cgi->stack_usage_kind = stack_usage_kind;
!     }
  
!   if (flag_stack_usage)
!     {
!       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]);
!     }
  }
  
  /* Open an auxiliary output file.  */
! FILE *
  open_auxiliary_file (const char *ext)
  {
    char *filename;
*************** finalize (void)
*** 2014,2019 ****
--- 2017,2023 ----
    if (stack_usage_file)
      fclose (stack_usage_file);
  
+   finish_cgraph ();
    finish_optimization_passes ();
  
    if (mem_report)
*** gcc/toplev.h.0	2006-06-19 15:39:05.999229736 +0200
--- gcc/toplev.h	2006-06-19 15:39:13.857035168 +0200
*************** extern void check_global_declarations (t
*** 100,105 ****
--- 100,108 ----
  extern void emit_debug_global_declarations (tree *, int);
  extern void write_global_declarations (void);
  
+ /* Open an auxiliary output file.  */
+ extern FILE *open_auxiliary_file (const char *);
+ 
  /* Output stack usage information.  */
  extern void output_stack_usage (void);
  

Attachment: analyze-ci.pl
Description: Perl program


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]