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]

[GCOV] Add all blocks mode, and function summaries


Hi,
this patch adds a mode to gcov where it will output individual counts for
all basic blocks, rather than just those blocks with a line number note.
Such a mode makes it easier to spot unexecuted blocks, such as
	if (always-true-expr || never-executed)

built & tested on i686-pc-linux-gnu, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan at codesourcery dot com : http://www.cs.bris.ac.uk/~nathan/ : nathan at acm dot org

Index: gcov-io.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcov-io.h,v
retrieving revision 1.21
diff -c -3 -p -r1.21 gcov-io.h
*** gcov-io.h	4 Mar 2003 20:56:21 -0000	1.21
--- gcov-io.h	27 Mar 2003 11:33:15 -0000
*************** Software Foundation, 59 Temple Place - S
*** 90,95 ****
--- 90,96 ----
     	bbg:  function-graph*
  	function-graph: announce_function basic_blocks {arcs | lines}*
  	announce_function: header string:name int32:checksum
+ 		string:source int32:lineno
  	basic_block: header int32:flags*
  	arcs: header int32:block_no arc*
  	arc:  int32:dest_block int32:flags
*************** Software Foundation, 59 Temple Place - S
*** 121,127 ****
  	summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
  		int64:max_sum int64:sum_max
  
!    The ANNOUNCE_FUNCTION record is the same as that in the BBG file.
     The ARC_COUNTS gives the counter values for those arcs that are
     instrumented.  The SUMMARY records give information about the whole
     object file and about the whole program.  The checksum is used for
--- 122,129 ----
  	summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
  		int64:max_sum int64:sum_max
  
!    The ANNOUNCE_FUNCTION record is the same as that in the BBG file,
!    but without the source location.
     The ARC_COUNTS gives the counter values for those arcs that are
     instrumented.  The SUMMARY records give information about the whole
     object file and about the whole program.  The checksum is used for
Index: gcov.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcov.c,v
retrieving revision 1.53
diff -c -3 -p -r1.53 gcov.c
*** gcov.c	18 Jan 2003 22:32:06 -0000	1.53
--- gcov.c	27 Mar 2003 11:33:27 -0000
*************** typedef HOST_WIDEST_INT gcov_type;
*** 69,74 ****
--- 69,75 ----
  
  struct function_info;
  struct block_info;
+ struct source_info;
  
  /* Describes an arc between two basic blocks.  */
  
*************** typedef struct arc_info
*** 88,93 ****
--- 89,97 ----
  
    /* Arc to a call.  */
    unsigned int is_call : 1;
+ 
+   /* Arc on the local block spanning tree. */
+   unsigned int local_span : 1;
    
    /* Next branch on line.  */
    struct arc_info *line_next;
*************** typedef struct block_info
*** 112,117 ****
--- 116,122 ----
  
    /* Block execution count.  */
    gcov_type count;
+   unsigned flags : 13;
    unsigned count_valid : 1;
    unsigned valid_chain : 1;
    unsigned invalid_chain : 1;
*************** typedef struct block_info
*** 119,128 ****
    /* Array of line numbers and source files. source files are
       introduced by a linenumber of zero, the next 'line number' is the
       number of the source file.  Always starts with a source file.  */
!   unsigned *encoding;
!   unsigned num_encodings;
  
!   /* Temporary chain for solving graph.  */
    struct block_info *chain;
    
  } block_t;
--- 124,145 ----
    /* Array of line numbers and source files. source files are
       introduced by a linenumber of zero, the next 'line number' is the
       number of the source file.  Always starts with a source file.  */
!   union
!   {
!     struct
!     {
!       unsigned *encoding;
!       unsigned num;
!     } line;
!     struct
!     {
!       struct block_info *root;
!       unsigned siblings;
!     } span;
!   } u;
  
!   /* Temporary chain for solving graph, and for chaining blocks on one
!      line.  */
    struct block_info *chain;
    
  } block_t;
*************** typedef struct function_info
*** 142,147 ****
--- 159,171 ----
    /* Raw arc coverage counts.  */
    gcov_type *counts;
    unsigned num_counts;
+ 
+   /* First line number.  */
+   unsigned line;
+   struct source_info *src;
+ 
+   /* Next function in same source file.  */
+   struct function_info *line_next;
    
    /* Next function.  */
    struct function_info *next;
*************** typedef struct coverage_info
*** 170,177 ****
  typedef struct line_info
  {
    gcov_type count;	   /* execution count */
!   arc_t *branches; 	   /* branches from blocks that end on this
! 			      line.  */
    unsigned exists : 1;
  } line_t;
  
--- 194,205 ----
  typedef struct line_info
  {
    gcov_type count;	   /* execution count */
!   union
!   {
!     arc_t *branches; 	   /* branches from blocks that end on this
! 			      line */
!     block_t *blocks;       /* blocks which start on this line.  */
!   } u;
    unsigned exists : 1;
  } line_t;
  
*************** typedef struct source_info
*** 189,194 ****
--- 217,226 ----
    unsigned num_lines;
  
    coverage_t coverage;
+ 
+   /* Functions in this source file.  These are in ascending line
+      number order.  */
+   function_t *functions;
    
    /* Next source file.  */
    struct source_info *next;
*************** static function_t *functions;
*** 202,207 ****
--- 234,244 ----
  
  static source_t *sources;
  
+ /* This holds data summary information.  */
+ 
+ static struct gcov_summary object_summary;
+ static unsigned program_count;
+ 
  /* Modification time of graph file.  */
  
  static time_t bbg_file_time;
*************** static int flag_gcov_file = 1;
*** 229,234 ****
--- 266,276 ----
  
  static int flag_long_names = 0;
  
+ /* Output count information for every basic block, not merely those
+    that contain line number information.  */
+ 
+ static int flag_all_blocks = 0;
+ 
  /* Output summary info for each function.  */
  
  static int flag_function_summary = 0;
*************** static void print_usage PARAMS ((int)) A
*** 256,261 ****
--- 298,304 ----
  static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
  static void process_file PARAMS ((const char *));
  static void create_file_names PARAMS ((const char *));
+ static source_t *find_source PARAMS ((char *));
  static int read_graph_file PARAMS ((void));
  static int read_count_file PARAMS ((void));
  static void solve_flow_graph PARAMS ((function_t *));
*************** static void add_line_counts PARAMS ((cov
*** 264,269 ****
--- 307,313 ----
  static void function_summary PARAMS ((const coverage_t *, const char *));
  static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
  static void accumulate_line_counts PARAMS ((source_t *));
+ static void output_branch_count PARAMS ((FILE *, int, const arc_t *));
  static void output_lines PARAMS ((FILE *, const source_t *));
  static char *make_gcov_file_name PARAMS ((const char *, const char *));
  static void release_structures PARAMS ((void));
*************** print_usage (error_p)
*** 328,333 ****
--- 372,378 ----
    fnotice (file, "Print code coverage information.\n\n");
    fnotice (file, "  -h, --help                      Print this help, then exit\n");
    fnotice (file, "  -v, --version                   Print version number, then exit\n");
+   fnotice (file, "  -a, --all-blocks                Show information for every basic block\n");
    fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
    fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
                                      rather than percentages\n");
*************** static const struct option options[] =
*** 365,370 ****
--- 410,416 ----
  {
    { "help",                 no_argument,       NULL, 'h' },
    { "version",              no_argument,       NULL, 'v' },
+   { "all-blocks",           no_argument,       NULL, 'a' },
    { "branch-probabilities", no_argument,       NULL, 'b' },
    { "branch-counts",        no_argument,       NULL, 'c' },
    { "no-output",            no_argument,       NULL, 'n' },
*************** process_args (argc, argv)
*** 384,413 ****
  {
    int opt;
  
!   while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
      {
        switch (opt)
  	{
! 	case 'h':
! 	  print_usage (false);
! 	  /* print_usage will exit.  */
! 	case 'v':
! 	  print_version ();
! 	  /* print_version will exit.  */
  	case 'b':
  	  flag_branches = 1;
  	  break;
  	case 'c':
  	  flag_counts = 1;
  	  break;
! 	case 'n':
! 	  flag_gcov_file = 0;
  	  break;
  	case 'l':
  	  flag_long_names = 1;
  	  break;
! 	case 'f':
! 	  flag_function_summary = 1;
  	  break;
  	case 'o':
  	  object_directory = optarg;
--- 430,459 ----
  {
    int opt;
  
!   while ((opt = getopt_long (argc, argv, "abcfhlno:pv", options, NULL)) != -1)
      {
        switch (opt)
  	{
! 	case 'a':
! 	  flag_all_blocks = 1;
! 	  break;
  	case 'b':
  	  flag_branches = 1;
  	  break;
  	case 'c':
  	  flag_counts = 1;
  	  break;
! 	case 'f':
! 	  flag_function_summary = 1;
  	  break;
+ 	case 'h':
+ 	  print_usage (false);
+ 	  /* print_usage will exit.  */
  	case 'l':
  	  flag_long_names = 1;
  	  break;
! 	case 'n':
! 	  flag_gcov_file = 0;
  	  break;
  	case 'o':
  	  object_directory = optarg;
*************** process_args (argc, argv)
*** 415,420 ****
--- 461,469 ----
  	case 'p':
  	  flag_preserve_paths = 1;
  	  break;
+ 	case 'v':
+ 	  print_version ();
+ 	  /* print_version will exit.  */
  	default:
  	  print_usage (true);
  	  /* print_usage will exit.  */
*************** release_structures ()
*** 528,534 ****
  	      arc_n = arc->succ_next;
  	      free (arc);
  	    }
- 	  free (block->encoding);
  	}
        free (fn->blocks);
        free (fn->counts);
--- 577,582 ----
*************** create_file_names (file_name)
*** 597,602 ****
--- 645,678 ----
    return;
  }
  
+ /* Find or create a source file structure for FILE_NAME. Free
+    FILE_NAME appropriately */
+ 
+ static source_t *
+ find_source (file_name)
+      char *file_name;
+ {
+ 
+   source_t *src;
+   
+   for (src = sources; src; src = src->next)
+     if (!strcmp (file_name, src->name))
+       {
+ 	free (file_name);
+ 	break;
+       }
+   if (!src)
+     {
+       src = (source_t *)xcalloc (1, sizeof (source_t));
+       src->name = file_name;
+       src->coverage.name = file_name;
+       src->index = sources ? sources->index + 1 : 1;
+       src->next = sources;
+       sources = src;
+     }
+   return src;
+ }
+ 
  /* Read the graph file. Return nonzero on fatal error.  */
  
  static int
*************** read_graph_file ()
*** 650,671 ****
  	goto corrupt;
  
        base = gcov_save_position (file);
!       
        if (tag == GCOV_TAG_FUNCTION)
  	{
  	  char *function_name = NULL;
! 	  unsigned checksum;
  
  	  if (gcov_read_string (file, &function_name, NULL)
! 	      || gcov_read_unsigned (file, &checksum))
  	    goto corrupt;
  	  fn = (function_t *)xcalloc (1, sizeof (function_t));
  	  fn->name = function_name;
  	  fn->checksum = checksum;
  
  	  fn->next = functions;
  	  functions = fn;
  	  current_tag = tag;
  	}
        else if (fn && tag == GCOV_TAG_BLOCKS)
  	{
--- 726,770 ----
  	goto corrupt;
  
        base = gcov_save_position (file);
! 
        if (tag == GCOV_TAG_FUNCTION)
  	{
  	  char *function_name = NULL;
! 	  char *function_file = NULL;
! 	  unsigned checksum, lineno;
! 	  source_t *src;
! 	  function_t *probe, *prev;
  
  	  if (gcov_read_string (file, &function_name, NULL)
! 	      || gcov_read_unsigned (file, &checksum)
! 	      || gcov_read_string (file, &function_file, NULL)
! 	      || gcov_read_unsigned (file, &lineno))
  	    goto corrupt;
+ 	  src = find_source (function_file);
  	  fn = (function_t *)xcalloc (1, sizeof (function_t));
  	  fn->name = function_name;
  	  fn->checksum = checksum;
+ 	  fn->src = src;
+ 	  fn->line = lineno;
  
  	  fn->next = functions;
  	  functions = fn;
  	  current_tag = tag;
+ 	  
+ 	  if (lineno >= src->num_lines)
+ 	    src->num_lines = lineno + 1;
+ 	  /* Now insert it into the source file's list of
+ 	     functions. Normally functions will be encountered in
+ 	     ascending order, so a simple scan is quick.  */
+ 	  for (probe = src->functions, prev = NULL;
+ 	       probe && probe->line > lineno;
+ 	       prev = probe, probe = probe->line_next)
+ 	    continue;
+ 	  fn->line_next = probe;
+ 	  if (prev)
+ 	    prev->line_next = fn;
+ 	  else
+ 	    src->functions = fn;
  	}
        else if (fn && tag == GCOV_TAG_BLOCKS)
  	{
*************** read_graph_file ()
*** 674,682 ****
  		     bbg_file_name, fn->name);
  	  else
  	    {
! 	      fn->num_blocks = length / 4;
  	      fn->blocks
  		= (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
  	    }
  	}
        else if (fn && tag == GCOV_TAG_ARCS)
--- 773,791 ----
  		     bbg_file_name, fn->name);
  	  else
  	    {
! 	      unsigned ix, num_blocks = length / 4;
! 	      fn->num_blocks = num_blocks;
! 	      
  	      fn->blocks
  		= (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
+ 	      for (ix = 0; ix != num_blocks; ix++)
+ 		{
+ 		  unsigned flags;
+ 		  
+ 		  if (gcov_read_unsigned (file, &flags))
+ 		    goto corrupt;
+ 		  fn->blocks[ix].flags = flags;
+ 		}
  	    }
  	}
        else if (fn && tag == GCOV_TAG_ARCS)
*************** read_graph_file ()
*** 731,737 ****
  
  	  if (gcov_read_unsigned (file, &blockno)
  	      || blockno >= fn->num_blocks
! 	      || fn->blocks[blockno].encoding)
  	    goto corrupt;
  	  
  	  for (ix = 0; ;  )
--- 840,846 ----
  
  	  if (gcov_read_unsigned (file, &blockno)
  	      || blockno >= fn->num_blocks
! 	      || fn->blocks[blockno].u.line.encoding)
  	    goto corrupt;
  	  
  	  for (ix = 0; ;  )
*************** read_graph_file ()
*** 759,786 ****
  		    goto corrupt;
  		  if (!file_name)
  		    break;
! 		  for (src = sources; src; src = src->next)
! 		    if (!strcmp (file_name, src->name))
! 		      {
! 			free (file_name);
! 			break;
! 		      }
! 		  if (!src)
! 		    {
! 		      src = (source_t *)xcalloc (1, sizeof (source_t));
! 		      src->name = file_name;
! 		      src->coverage.name = file_name;
! 		      src->index = sources ? sources->index + 1 : 1;
! 		      src->next = sources;
! 		      sources = src;
! 		    }
  		  line_nos[ix++] = 0;
  		  line_nos[ix++] = src->index;
  		}
  	    }
  	  
! 	  fn->blocks[blockno].encoding = line_nos;
! 	  fn->blocks[blockno].num_encodings = ix;
  	}
        else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
  	{
--- 868,882 ----
  		    goto corrupt;
  		  if (!file_name)
  		    break;
! 		  src = find_source (file_name);
! 		  
  		  line_nos[ix++] = 0;
  		  line_nos[ix++] = src->index;
  		}
  	    }
  	  
! 	  fn->blocks[blockno].u.line.encoding = line_nos;
! 	  fn->blocks[blockno].u.line.num = ix;
  	}
        else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
  	{
*************** read_count_file ()
*** 906,912 ****
  	  goto cleanup;
  	}
        base = gcov_save_position (file);
!       if (tag == GCOV_TAG_FUNCTION)
  	{
  	  unsigned checksum;
  	  struct function_info *fn_n = functions;
--- 1002,1016 ----
  	  goto cleanup;
  	}
        base = gcov_save_position (file);
!       if (tag == GCOV_TAG_OBJECT_SUMMARY)
! 	{
! 	  if (gcov_read_summary (file, &object_summary))
! 	    goto corrupt;
! 	}
!       else if (tag == GCOV_TAG_PROGRAM_SUMMARY
! 	       || tag == GCOV_TAG_INCORRECT_SUMMARY)
! 	program_count++;
!       else if (tag == GCOV_TAG_FUNCTION)
  	{
  	  unsigned checksum;
  	  struct function_info *fn_n = functions;
*************** add_line_counts (coverage, fn)
*** 1383,1395 ****
    /* Scan each basic block.  */
    for (ix = 0; ix != fn->num_blocks; ix++)
      {
!       const block_t *block = &fn->blocks[ix];
        unsigned *encoding;
        const source_t *src = NULL;
        unsigned jx;
  
!       for (jx = 0, encoding = block->encoding;
! 	   jx != block->num_encodings; jx++, encoding++)
  	if (!*encoding)
  	  {
  	    unsigned src_n = *++encoding;
--- 1487,1500 ----
    /* Scan each basic block.  */
    for (ix = 0; ix != fn->num_blocks; ix++)
      {
!       block_t *block = &fn->blocks[ix];
        unsigned *encoding;
        const source_t *src = NULL;
        unsigned jx;
+       line_t *first_line = NULL;
  
!       for (jx = 0, encoding = block->u.line.encoding;
! 	   jx != block->u.line.num; jx++, encoding++)
  	if (!*encoding)
  	  {
  	    unsigned src_n = *++encoding;
*************** add_line_counts (coverage, fn)
*** 1406,1419 ****
  	      {
  		if (!line->exists)
  		  coverage->lines++;
! 		if  (!line->count && block->count)
  		  coverage->lines_executed++;
  	      }
  	    line->exists = 1;
  	    line->count += block->count;
  	  }
!       
!       if (line && flag_branches)
  	{
  	  arc_t *arc;
  	  
--- 1511,1540 ----
  	      {
  		if (!line->exists)
  		  coverage->lines++;
! 		if (!line->count && block->count)
  		  coverage->lines_executed++;
  	      }
  	    line->exists = 1;
  	    line->count += block->count;
+ 	    if (!first_line)
+ 	      first_line = line;
  	  }
!       free (block->u.line.encoding);
!       block->u.span.root = NULL;
!       if (!first_line)
! 	first_line = line;
! 
!       if (!ix || ix + 1 == fn->num_blocks)
! 	/* Entry or exit block */;
!       else if (flag_all_blocks)
! 	{
! 	  if (!first_line)
! 	    first_line = &fn->src->lines[fn->line];
! 	  
! 	  block->chain = first_line->u.blocks;
! 	  first_line->u.blocks = block;
! 	}
!       else if (flag_branches)
  	{
  	  arc_t *arc;
  	  
*************** add_line_counts (coverage, fn)
*** 1423,1430 ****
  	      if (arc->fall_through)
  		continue;
  	      
! 	      arc->line_next = line->branches;
! 	      line->branches = arc;
  	      if (coverage)
  		add_branch_counts (coverage, arc);
  	    }
--- 1544,1551 ----
  	      if (arc->fall_through)
  		continue;
  	      
! 	      arc->line_next = line->u.branches;
! 	      line->u.branches = arc;
  	      if (coverage)
  		add_branch_counts (coverage, arc);
  	    }
*************** accumulate_line_counts (src)
*** 1441,1462 ****
       source_t *src;
  {
    line_t *line;
    unsigned ix;
    
    for (ix = src->num_lines, line = src->lines; ix--; line++)
      {
!       arc_t *arc, *arc_p, *arc_n;
!       
!       /* Total and reverse the branch information.  */
!       for (arc = line->branches, arc_p = NULL; arc; arc_p = arc, arc = arc_n)
  	{
! 	  arc_n = arc->line_next;
! 	  arc->line_next = arc_p;
! 
! 	  add_branch_counts (&src->coverage, arc);
  	}
!       line->branches = arc_p;
  
        if (line->exists)
  	{
  	  src->coverage.lines++;
--- 1562,1684 ----
       source_t *src;
  {
    line_t *line;
+   function_t *fn, *fn_p, *fn_n;
    unsigned ix;
+ 
+   /* Reverse the function order.  */
+   for (fn = src->functions, fn_p = NULL; fn;
+        fn_p = fn, fn = fn_n)
+     {
+       fn_n = fn->line_next;
+       fn->line_next = fn_p;
+     }
+   src->functions = fn_p;
    
    for (ix = src->num_lines, line = src->lines; ix--; line++)
      {
!       if (!flag_all_blocks)
  	{
! 	  arc_t *arc, *arc_p, *arc_n;
! 	  
! 	  /* Total and reverse the branch information.  */
! 	  for (arc = line->u.branches, arc_p = NULL; arc;
! 	       arc_p = arc, arc = arc_n)
! 	    {
! 	      arc_n = arc->line_next;
! 	      arc->line_next = arc_p;
! 	      
! 	      add_branch_counts (&src->coverage, arc);
! 	    }
! 	  line->u.branches = arc_p;
  	}
!       else if (line->u.blocks)
! 	{
! 	  /* The user expects the line count to be the number of times
! 	     a line has been executed. Simply summing the block count
! 	     will give an artificially high number.  The Right Thing
! 	     is to generate the spanning tree of the blocks on this
! 	     line, and the sum the entry arcs to that tree.  */
! 	  block_t *block, *block_p, *block_n;
! 	  int changes = 1;
! 	  gcov_type count = 0;
! 	  
! 	  /* Reverse the block information */
! 	  for (block = line->u.blocks, block_p = NULL; block;
! 	       block_p = block, block = block_n)
! 	    {
! 	      block_n = block->chain;
! 	      block->chain = block_p;
! 	      /* Each block is it's own spanning tree, with no siblings  */
! 	      block->u.span.root = block;
! 	      block->u.span.siblings = 0;
! 	    }
! 	  line->u.blocks = block_p;
  
+ 	  while (changes)
+ 	    {
+ 	      changes = 0;
+ 	      
+ 	      for (block = line->u.blocks; block; block = block->chain)
+ 		{
+ 		  arc_t *arc;
+ 		  
+ 		  for (arc = block->succ; arc; arc = arc->succ_next)
+ 		    {
+ 		      block_t *dst = arc->dst;
+ 		      
+ 		      if (!dst->u.span.root)
+ 			/* Not on this line.  */;
+ 		      else if (dst->u.span.root == block->u.span.root)
+ 			/* Same spanning tree.  */;
+ 		      else
+ 			{
+ 			  block_t *root = block->u.span.root;
+ 			  block_t *dst_root = dst->u.span.root;
+ 			  
+ 			  /* Join spanning trees */
+ 			  if (root->u.span.siblings && !dst_root->u.span.root)
+ 			    {
+ 			      root = dst->u.span.root;
+ 			      dst_root = block->u.span.root;
+ 			    }
+ 			  
+ 			  dst->u.span.root = root;
+ 			  root->u.span.siblings += 1 + dst->u.span.siblings;
+ 			  if (dst->u.span.siblings)
+ 			    {
+ 			      block_t *dst_sib;
+ 			      
+ 			      dst->u.span.siblings = 0;
+ 			      for (dst_sib = line->u.blocks; dst_sib;
+ 				   dst_sib = dst_sib->chain)
+ 				if (dst_sib->u.span.root == dst_root)
+ 				  dst_sib->u.span.root = root;
+ 			    }
+ 			  arc->local_span = 1;
+ 			  changes = 1;
+ 			}
+ 		    }
+ 		}
+ 	    }
+ 
+ 	  /* Now sum the entry counts */
+ 	  for (block = line->u.blocks; block; block = block->chain)
+ 	    {
+ 	      arc_t *arc;
+ 
+ 	      for (arc = block->succ; arc; arc = arc->succ_next)
+ 		{
+ 		  if (!arc->local_span)
+ 		    count += arc->count;
+ 		  if (flag_branches)
+ 		    add_branch_counts (&src->coverage, arc);
+ 		}
+ 	      block->u.span.root = NULL;
+ 	    }
+ 	  
+ 	  line->count = count;
+ 	}
+       
        if (line->exists)
  	{
  	  src->coverage.lines++;
*************** accumulate_line_counts (src)
*** 1466,1471 ****
--- 1688,1721 ----
      }
  }
  
+ /* Ouput information about ARC number IX. */
+ 
+ static void
+ output_branch_count (gcov_file, ix, arc)
+      FILE *gcov_file;
+      int ix;
+      const arc_t *arc;
+ {
+   
+   if (arc->is_call)
+     {
+       if (arc->src->count)
+ 	fnotice (gcov_file, "call   %2d returns %s\n", ix,
+ 		 format_gcov (arc->src->count - arc->count,
+ 			      arc->src->count, -flag_counts));
+       else
+ 	fnotice (gcov_file, "call   %2d never executed\n", ix);
+     }
+   else
+     {
+       if (arc->src->count)
+ 	fnotice (gcov_file, "branch %2d taken %s\n", ix,
+ 		 format_gcov (arc->count, arc->src->count, -flag_counts));
+       else
+ 	fnotice (gcov_file, "branch %2d never executed\n", ix);
+     }
+ }
+ 
  /* Read in the source file one line at a time, and output that line to
     the gcov file preceded by its execution count and other
     information.  */
*************** output_lines (gcov_file, src)
*** 1480,1489 ****
--- 1730,1742 ----
    const line_t *line;           /* current line info ptr.  */
    char string[STRING_SIZE];     /* line buffer.  */
    char const *retval = "";	/* status of source file reading.  */
+   function_t *fn = src->functions;
  
    fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
    fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
    fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
+   fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_summary.runs);
+   fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
    
    source_file = fopen (src->name, "r");
    if (!source_file)
*************** output_lines (gcov_file, src)
*** 1508,1513 ****
--- 1761,1776 ----
    for (line_num = 1, line = &src->lines[line_num];
         line_num < src->num_lines; line_num++, line++)
      {
+       for (; fn && fn->line == line_num; fn = fn->line_next)
+ 	{
+ 	  fprintf (gcov_file, "function %s", fn->name);
+ 	  fprintf (gcov_file, " called %s",
+ 		   format_gcov (fn->blocks[0].count, 0, -1));
+ 	  fprintf (gcov_file, " returned %s",
+ 		   format_gcov (fn->blocks[fn->num_blocks - 1].count, 0, -1));
+ 	  fprintf (gcov_file, "\n");
+ 	}
+       
        /* For lines which don't exist in the .bb file, print '-' before
   	 the source line.  For lines which exist but were never
   	 executed, print '#####' before the source line.  Otherwise,
*************** output_lines (gcov_file, src)
*** 1535,1570 ****
  	}
        if (!retval)
  	fputs ("??\n", gcov_file);
!       
!       if (flag_branches)
  	{
! 	  int ix;
! 	  arc_t *arc;
  	  
! 	  for (ix = 0, arc = line->branches; arc; arc = arc->line_next, ix++)
  	    {
! 	      if (arc->is_call)
! 		{
! 		  if (arc->src->count)
! 		    fnotice
! 		      (gcov_file, "call   %2d returns %s\n", ix,
! 		       format_gcov (arc->src->count - arc->count,
! 				    arc->src->count,
! 				    -flag_counts));
! 		  else
! 		    fnotice (gcov_file, "call   %2d never executed\n", ix);
! 		}
! 	      else
  		{
! 		  if (arc->src->count)
! 		    fnotice
! 		      (gcov_file, "branch %2d taken %s\n", ix,
! 		       format_gcov (arc->count, arc->src->count,
! 				    -flag_counts));
! 		  else
! 		    fnotice (gcov_file, "branch %2d never executed\n", ix);
  		}
  	    }
  	}
      }
    
--- 1798,1832 ----
  	}
        if (!retval)
  	fputs ("??\n", gcov_file);
! 
!       if (flag_all_blocks)
  	{
! 	  block_t *block;
! 	  int ix, jx;
  	  
! 	  for (ix = jx = 0, block = line->u.blocks; block;
! 	       block = block->chain, ix++)
  	    {
! 	      fprintf (gcov_file, "%9s:%5u-block %2d\n",
! 		       !line->exists ? "-" : !block->count ? "$$$$$"
! 		       : format_gcov (block->count, 0, -1), line_num, ix);
! 	      
! 	      if (flag_branches)
  		{
! 		  arc_t *arc;
! 		  
! 		  for (arc = block->succ; arc; arc = arc->succ_next, jx++)
! 		    output_branch_count (gcov_file, jx, arc);
  		}
  	    }
+ 	}
+       else if (flag_branches)
+ 	{
+ 	  int ix;
+ 	  arc_t *arc;
+ 	  
+ 	  for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next, ix++)
+ 	    output_branch_count (gcov_file, ix, arc);
  	}
      }
    
Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.108
diff -c -3 -p -r1.108 profile.c
*** profile.c	26 Feb 2003 16:55:10 -0000	1.108
--- profile.c	27 Mar 2003 11:33:27 -0000
*************** branch_prob ()
*** 925,931 ****
    unsigned num_edges, ignored_edges;
    struct edge_list *el;
    const char *name = IDENTIFIER_POINTER
! 		      (DECL_ASSEMBLER_NAME (current_function_decl));
  
    profile_info.current_function_cfg_checksum = compute_checksum ();
    for (i = 0; i < profile_info.n_sections; i++)
--- 925,931 ----
    unsigned num_edges, ignored_edges;
    struct edge_list *el;
    const char *name = IDENTIFIER_POINTER
!     (DECL_ASSEMBLER_NAME (current_function_decl));
  
    profile_info.current_function_cfg_checksum = compute_checksum ();
    for (i = 0; i < profile_info.n_sections; i++)
*************** branch_prob ()
*** 1085,1090 ****
--- 1085,1092 ----
    if (flag_test_coverage && bbg_file)
      {
        long offset;
+       const char *file = DECL_SOURCE_FILE (current_function_decl);
+       unsigned line = DECL_SOURCE_LINE (current_function_decl);
        
        /* Announce function */
        if (gcov_write_unsigned (bbg_file, GCOV_TAG_FUNCTION)
*************** branch_prob ()
*** 1093,1098 ****
--- 1095,1102 ----
  			     strlen (name))
  	  || gcov_write_unsigned (bbg_file,
  			    profile_info.current_function_cfg_checksum)
+ 	  || gcov_write_string (bbg_file, file, strlen (file))
+ 	  || gcov_write_unsigned (bbg_file, line)
  	  || gcov_write_length (bbg_file, offset))
  	goto bbg_error;
  
Index: doc/gcov.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/gcov.texi,v
retrieving revision 1.14
diff -c -3 -p -r1.14 gcov.texi
*** doc/gcov.texi	4 Feb 2003 01:27:46 -0000	1.14
--- doc/gcov.texi	27 Mar 2003 11:38:27 -0000
*************** gcov @r{[} at var{options}@r{]} @var{source
*** 120,125 ****
--- 120,126 ----
  @ignore
  @c man begin SYNOPSIS
  gcov [ at option{-v}|@option{--version}] [ at option{-h}|@option{--help}]
+      [ at option{-a}|@option{--all-blocks}]
       [ at option{-b}|@option{--branch-probabilities}]
       [ at option{-c}|@option{--branch-counts}]
       [ at option{-n}|@option{--no-output}]
*************** exit without doing any further processin
*** 145,150 ****
--- 146,159 ----
  Display the @command{gcov} version number (on the standard output),
  and exit without doing any further processing.
  
+ @item -a
+ @itemx --all-blocks
+ Write individual execution counts for every basic block. Normally gcov
+ outputs execution counts only for the main blocks of a line. With this
+ option you can determine if blocks within a single line are not being
+ executed. Also, each block is considered to occupy a single line of
+ source, rather than multiple lines.
+ 
  @item -b
  @itemx --branch-probabilities
  Write branch frequencies to the output file, and write branch summary
*************** Here is a sample:
*** 248,257 ****
  
  @smallexample
          -:    0:Source:tmp.c
!         -:    0:Object:tmp.bb
          -:    1:#include <stdio.h>
          -:    2:
          -:    3:int main (void)
          1:    4:@{
          1:    5:  int i, total;
          -:    6:  
--- 257,270 ----
  
  @smallexample
          -:    0:Source:tmp.c
!         -:    0:Graph:tmp.bbg
!         -:    0:Data:tmp.da
!         -:    0:Runs:1
!         -:    0:Programs:1
          -:    1:#include <stdio.h>
          -:    2:
          -:    3:int main (void)
+ function main called 1 returned 1
          1:    4:@{
          1:    5:  int i, total;
          -:    6:  
*************** Here is a sample:
*** 265,273 ****
          -:   14:  else
          1:   15:    printf ("Success\n");
          1:   16:  return 0;
!         1:   17:@}
  @end smallexample
  
  @need 450
  When you use the @option{-b} option, your output looks like this:
  
--- 278,326 ----
          -:   14:  else
          1:   15:    printf ("Success\n");
          1:   16:  return 0;
!         -:   17:@}
  @end smallexample
  
+ When you use the @option{-a} option, you will get individual block
+ counts, and the output looks like this:
+ 
+ @smallexample
+         -:    0:Source:tmp.c
+         -:    0:Graph:tmp.bbg
+         -:    0:Data:tmp.da
+         -:    0:Runs:1
+         -:    0:Programs:1
+         -:    1:#include <stdio.h>
+         -:    2:
+         -:    3:int main (void)
+ function main called 1 returned 1
+         1:    4:@{
+         1:    4-block  0
+         1:    5:  int i, total;
+         -:    6:  
+         1:    7:  total = 0;
+         -:    8:  
+        11:    9:  for (i = 0; i < 10; i++)
+        11:    9-block  0
+        10:   10:    total += i;
+        10:   10-block  0
+         -:   11:  
+         1:   12:  if (total != 45)
+         1:   12-block  0
+     #####:   13:    printf ("Failure\n");
+     $$$$$:   13-block  0
+     $$$$$:   13-block  1
+         -:   14:  else
+         1:   15:    printf ("Success\n");
+         1:   15-block  0
+         1:   16:  return 0;
+         1:   16-block  0
+         -:   17:@}
+ @end smallexample
+ 
+ As you can see, line 13 contained two basic blocks, neither of which was
+ executed.
+ 
  @need 450
  When you use the @option{-b} option, your output looks like this:
  
*************** Here is a sample of a resulting @file{tm
*** 284,314 ****
  
  @smallexample
          -:    0:Source:tmp.c
!         -:    0:Object:tmp.bb
          -:    1:#include <stdio.h>
          -:    2:
          -:    3:int main (void)
          1:    4:@{
          1:    5:  int i, total;
          -:    6:  
          1:    7:  total = 0;
          -:    8:  
         11:    9:  for (i = 0; i < 10; i++)
! branch  0: taken 90%
! branch  1: taken 100%
! branch  2: taken 100%
         10:   10:    total += i;
          -:   11:  
          1:   12:  if (total != 45)
! branch  0: taken 100%
      #####:   13:    printf ("Failure\n");
! call    0: never executed
! branch  1: never executed
          -:   14:  else
          1:   15:    printf ("Success\n");
! call    0: returns 100%
          1:   16:  return 0;
!         1:   17:@}
  @end smallexample
  
  For each basic block, a line is printed after the last line of the basic
--- 337,370 ----
  
  @smallexample
          -:    0:Source:tmp.c
!         -:    0:Graph:tmp.bbg
!         -:    0:Data:tmp.da
!         -:    0:Runs:1
!         -:    0:Programs:1
          -:    1:#include <stdio.h>
          -:    2:
          -:    3:int main (void)
+ function main called 1 returned 1
          1:    4:@{
          1:    5:  int i, total;
          -:    6:  
          1:    7:  total = 0;
          -:    8:  
         11:    9:  for (i = 0; i < 10; i++)
! branch  0 taken 9%
! branch  1 taken 100%
         10:   10:    total += i;
          -:   11:  
          1:   12:  if (total != 45)
! branch  0 taken 100%
      #####:   13:    printf ("Failure\n");
! call    0 never executed
! branch  1 never executed
          -:   14:  else
          1:   15:    printf ("Success\n");
! call    0 returns 100%
          1:   16:  return 0;
!         -:   17:@}
  @end smallexample
  
  For each basic block, a line is printed after the last line of the basic

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