]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gcov: add info about "calls" to JSON output format
authorMartin Liska <mliska@suse.cz>
Thu, 6 Apr 2023 09:54:51 +0000 (11:54 +0200)
committerMartin Liska <mliska@suse.cz>
Tue, 25 Apr 2023 11:11:29 +0000 (13:11 +0200)
gcc/ChangeLog:

* doc/gcov.texi: Document the new "calls" field and document
the API bump. Mention also "block_ids" for lines.
* gcov.cc (output_intermediate_json_line): Output info about
calls and extend branches as well.
(generate_results): Bump version to 2.
(output_line_details): Use block ID instead of a non-sensual
index.

gcc/testsuite/ChangeLog:

* g++.dg/gcov/gcov-17.C: Add call to a noreturn function.
* g++.dg/gcov/test-gcov-17.py: Cover new format.
* lib/gcov.exp: Add options for gcov that emit the extra info.

gcc/doc/gcov.texi
gcc/gcov.cc
gcc/testsuite/g++.dg/gcov/gcov-17.C
gcc/testsuite/g++.dg/gcov/test-gcov-17.py
gcc/testsuite/lib/gcov.exp

index d39cce3a683556e2d9dacc657f267d29cd2c7828..3019efc467495815d2ace17a71a02663313b9caa 100644 (file)
@@ -195,7 +195,7 @@ Structure of the JSON is following:
 @{
   "current_working_directory": "foo/bar",
   "data_file": "a.out",
-  "format_version": "1",
+  "format_version": "2",
   "gcc_version": "11.1.1 20210510"
   "files": ["$file"]
 @}
@@ -214,6 +214,12 @@ a compilation unit was compiled
 @item
 @var{format_version}: semantic version of the format
 
+Changes in version @emph{2}:
+@itemize @bullet
+@item
+@var{calls}: information about function calls is added
+@end itemize
+
 @item
 @var{gcc_version}: version of the GCC compiler
 @end itemize
@@ -291,7 +297,9 @@ Each @var{line} has the following form:
 
 @smallexample
 @{
+  "block_ids": ["$block_id"],
   "branches": ["$branch"],
+  "calls": ["$call"],
   "count": 2,
   "line_number": 15,
   "unexecuted_block": false,
@@ -299,10 +307,13 @@ Each @var{line} has the following form:
 @}
 @end smallexample
 
-Branches are present only with @var{-b} option.
+Branches and calls are present only with @var{-b} option.
 Fields of the @var{line} element have following semantics:
 
 @itemize @bullet
+@item
+@var{block_ids}: IDs of basic blocks that belong to the line
+
 @item
 @var{count}: number of executions of the line
 
@@ -323,7 +334,9 @@ Each @var{branch} has the following form:
 @smallexample
 @{
   "count": 11,
+  "destination_block_id": 17,
   "fallthrough": true,
+  "source_block_id": 13,
   "throw": false
 @}
 @end smallexample
@@ -339,6 +352,36 @@ Fields of the @var{branch} element have following semantics:
 
 @item
 @var{throw}: true when the branch is an exceptional branch
+
+@item
+@var{isource_block_id}: ID of the basic block where this branch happens
+
+@item
+@var{destination_block_id}: ID of the basic block this branch jumps to
+@end itemize
+
+Each @var{call} has the following form:
+
+@smallexample
+@{
+  "destination_block_id": 1,
+  "returned": 11,
+  "source_block_id": 13
+@}
+@end smallexample
+
+Fields of the @var{call} element have following semantics:
+
+@itemize @bullet
+@item
+@var{returned}: number of times a function call returned (call count is equal
+to @var{line::count})
+
+@item
+@var{isource_block_id}: ID of the basic block where this call happens
+
+@item
+@var{destination_block_id}: ID of the basic block this calls continues after return
 @end itemize
 
 @item -H
index 2ec7248cc0efac43be490d2e525b9cc9b685231f..d96b4f77e3b95b0f738fd33f75ce57157f996fb4 100644 (file)
@@ -1113,9 +1113,17 @@ output_intermediate_json_line (json::array *object,
   lineo->set ("unexecuted_block",
              new json::literal (line->has_unexecuted_block));
 
+  json::array *bb_ids = new json::array ();
+  for (const block_info *block : line->blocks)
+    bb_ids->append (new json::integer_number (block->id));
+  lineo->set ("block_ids", bb_ids);
+
   json::array *branches = new json::array ();
   lineo->set ("branches", branches);
 
+  json::array *calls = new json::array ();
+  lineo->set ("calls", calls);
+
   vector<arc_info *>::const_iterator it;
   if (flag_branches)
     for (it = line->branches.begin (); it != line->branches.end ();
@@ -1128,8 +1136,23 @@ output_intermediate_json_line (json::array *object,
            branch->set ("throw", new json::literal ((*it)->is_throw));
            branch->set ("fallthrough",
                         new json::literal ((*it)->fall_through));
+           branch->set ("source_block_id",
+                        new json::integer_number ((*it)->src->id));
+           branch->set ("destination_block_id",
+                        new json::integer_number ((*it)->dst->id));
            branches->append (branch);
          }
+       else if ((*it)->is_call_non_return)
+         {
+           json::object *call = new json::object ();
+           gcov_type returns = (*it)->src->count - (*it)->count;
+           call->set ("source_block_id",
+                      new json::integer_number ((*it)->src->id));
+           call->set ("destination_block_id",
+                      new json::integer_number ((*it)->dst->id));
+           call->set ("returned", new json::integer_number (returns));
+           calls->append (call);
+         }
       }
 
   object->append (lineo);
@@ -1523,7 +1546,7 @@ generate_results (const char *file_name)
   gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
 
   json::object *root = new json::object ();
-  root->set ("format_version", new json::string ("1"));
+  root->set ("format_version", new json::string ("2"));
   root->set ("gcc_version", new json::string (version_string));
 
   if (bbg_cwd != NULL)
@@ -3060,9 +3083,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num)
   if (flag_all_blocks)
     {
       arc_info *arc;
-      int ix, jx;
-
-      ix = jx = 0;
+      int jx = 0;
       for (vector<block_info *>::const_iterator it = line->blocks.begin ();
           it != line->blocks.end (); it++)
        {
@@ -3072,7 +3093,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num)
                                     (*it)->exceptional, false,
                                     (*it)->count, line_num,
                                     "%%%%%", "$$$$$", 0);
-             fprintf (f, "-block %2d", ix++);
+             fprintf (f, "-block %d", (*it)->id);
              if (flag_verbose)
                fprintf (f, " (BB %u)", (*it)->id);
              fprintf (f, "\n");
index d11883cfd397290a4145799b69139310e5f9a809..efe019599a5959382c76cab0734dd111691a5309 100644 (file)
@@ -15,6 +15,11 @@ private:
 template class Foo<int>;
 template class Foo<char>;
 
+static void noret()
+{
+  __builtin_exit (0);
+}
+
 int
 main (void)
 {
@@ -34,6 +39,8 @@ main (void)
     __builtin_printf ("Failure\n");
   else
     __builtin_printf ("Success\n");
+
+  noret ();
   return 0;
 }
 
index ec5df3dec0361cae46bf4e8d40cad7ead1c19676..ad065b0f443675476f85abc101f65cff7680f5fe 100644 (file)
@@ -12,7 +12,7 @@ def test_basics(gcov):
     files = gcov['files']
     assert len(files) == 1
     functions = files[0]['functions']
-    assert len(functions) == 5
+    assert len(functions) == 6
 
 
 def test_lines(gcov):
@@ -31,7 +31,19 @@ def test_lines(gcov):
     assert line9[1]['count'] == 2
     assert line9[0]['unexecuted_block']
     assert not line9[1]['unexecuted_block']
-    assert linesdict[31][0]['unexecuted_block']
-    assert linesdict[34][0]['unexecuted_block']
-    assert not linesdict[37][0]['unexecuted_block']
+    assert linesdict[36][0]['unexecuted_block']
+    assert linesdict[39][0]['unexecuted_block']
+    assert not linesdict[41][0]['unexecuted_block']
     assert 32 not in linesdict
+    print(lines)
+
+    line41 = linesdict[41][0]
+    assert line41['count'] == 1
+    assert line41['calls'][0]['returned'] == 1
+    assert line41['calls'][0]['source_block_id'] == 13
+    assert line41['calls'][0]['destination_block_id'] == 1
+    assert len(line41['block_ids']) > 0
+
+    line43 = linesdict[43][0]
+    assert line43['count'] == 1
+    assert line43['calls'][0]['returned'] == 0
index 80e74aeb220dd0e20b7e3822796127821179edde..e5e94fa5a76ff7b842992d0ecfa5bb54eef4736d 100644 (file)
@@ -274,7 +274,7 @@ proc run-gcov-pytest { args } {
 
     verbose "Running $GCOV $testcase in $srcdir/$subdir" 2
     set testcase [remote_download host $testcase]
-    set result [remote_exec host $GCOV "$testcase -i"]
+    set result [remote_exec host $GCOV "$testcase -i -abc"]
 
     set pytest_script [lindex $args 1]
     if { ![check_effective_target_pytest3] } {