On 4/14/23 14:34, Jan Hubicka wrote: >> On 4/11/23 11:23, Richard Biener wrote: >>> On Thu, Apr 6, 2023 at 3:58 PM Martin Liška wrote: >>>> >>>> Patch can bootstrap on x86_64-linux-gnu and survives regression tests. >>>> >>>> Ready to be installed after stage1 opens? >>> >>> Did we release a compiler with version 1? If not we might want to sneak >> >> Yes, all compilers starting with 9.1 emit version 1. >> >>> this in before 13.1 ... >> >> Yep, I would welcome sneaking in. >> >>> >>> Up to Honza. >> >> PING: Honza! > > THe motivation is for external tools to effectively track execution > counts after function calls that does not return normally? Yes, they wanted basically equal information as we present in the human-readable format. > What about other cases we produce fake edges for, like trapping > statements or volatile asms (via stmt_can_terminate_bb_p). Are those > handled as branches with "throw" flag? That's probably something for future. There was not demand for it right now. > > Calls not returning is just one of special cases where control of > function may terminate. Also do we want to handle function returning > twice (fork and setjmp?) Similarly here. Anyway, I'm going to commit a bit enhanced version where I: - added blocks_ids for each line number - for each branch and call source and destination block is added - in human-readable format I change block::index to block::id as the index does not makes sense much Martin > > Patch looks OK. > Honza >> >> Thanks, >> Martin >> >>> >>> Thanks, >>> Richard. >>> >>>> Thanks, >>>> Martin >>>> >>>> gcc/ChangeLog: >>>> >>>> * doc/gcov.texi: Document the new "calls" field and document >>>> the API bump. >>>> * gcov.cc (output_intermediate_json_line): Output info about >>>> calls. >>>> (generate_results): Bump version to 2. >>>> >>>> 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 | 27 +++++++++++++++++++++-- >>>> gcc/gcov.cc | 12 +++++++++- >>>> gcc/testsuite/g++.dg/gcov/gcov-17.C | 7 ++++++ >>>> gcc/testsuite/g++.dg/gcov/test-gcov-17.py | 17 ++++++++++---- >>>> gcc/testsuite/lib/gcov.exp | 2 +- >>>> 5 files changed, 57 insertions(+), 8 deletions(-) >>>> >>>> diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi >>>> index d39cce3a683..6739ebb3643 100644 >>>> --- a/gcc/doc/gcov.texi >>>> +++ b/gcc/doc/gcov.texi >>>> @@ -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 >>>> @@ -292,6 +298,7 @@ Each @var{line} has the following form: >>>> @smallexample >>>> @{ >>>> "branches": ["$branch"], >>>> + "calls": ["$call"], >>>> "count": 2, >>>> "line_number": 15, >>>> "unexecuted_block": false, >>>> @@ -299,7 +306,7 @@ 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 >>>> @@ -341,6 +348,22 @@ Fields of the @var{branch} element have following semantics: >>>> @var{throw}: true when the branch is an exceptional branch >>>> @end itemize >>>> >>>> +Each @var{call} has the following form: >>>> + >>>> +@smallexample >>>> +@{ >>>> + "returned": 11, >>>> +@} >>>> +@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}) >>>> +@end itemize >>>> + >>>> @item -H >>>> @itemx --human-readable >>>> Write counts in human readable format (like 24.6k). >>>> diff --git a/gcc/gcov.cc b/gcc/gcov.cc >>>> index 2ec7248cc0e..88324143640 100644 >>>> --- a/gcc/gcov.cc >>>> +++ b/gcc/gcov.cc >>>> @@ -1116,6 +1116,9 @@ output_intermediate_json_line (json::array *object, >>>> json::array *branches = new json::array (); >>>> lineo->set ("branches", branches); >>>> >>>> + json::array *calls = new json::array (); >>>> + lineo->set ("calls", calls); >>>> + >>>> vector::const_iterator it; >>>> if (flag_branches) >>>> for (it = line->branches.begin (); it != line->branches.end (); >>>> @@ -1130,6 +1133,13 @@ output_intermediate_json_line (json::array *object, >>>> new json::literal ((*it)->fall_through)); >>>> 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 ("returned", new json::integer_number (returns)); >>>> + calls->append (call); >>>> + } >>>> } >>>> >>>> object->append (lineo); >>>> @@ -1523,7 +1533,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) >>>> diff --git a/gcc/testsuite/g++.dg/gcov/gcov-17.C b/gcc/testsuite/g++.dg/gcov/gcov-17.C >>>> index d11883cfd39..efe019599a5 100644 >>>> --- a/gcc/testsuite/g++.dg/gcov/gcov-17.C >>>> +++ b/gcc/testsuite/g++.dg/gcov/gcov-17.C >>>> @@ -15,6 +15,11 @@ private: >>>> template class Foo; >>>> template class Foo; >>>> >>>> +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; >>>> } >>>> >>>> diff --git a/gcc/testsuite/g++.dg/gcov/test-gcov-17.py b/gcc/testsuite/g++.dg/gcov/test-gcov-17.py >>>> index ec5df3dec03..a0b8b09b85c 100644 >>>> --- a/gcc/testsuite/g++.dg/gcov/test-gcov-17.py >>>> +++ b/gcc/testsuite/g++.dg/gcov/test-gcov-17.py >>>> @@ -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,16 @@ 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'] == [{'returned': 1}] >>>> + >>>> + line43 = linesdict[43][0] >>>> + assert line43['count'] == 1 >>>> + assert line43['calls'] == [{'returned': 0}] >>>> diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp >>>> index 80e74aeb220..e5e94fa5a76 100644 >>>> --- a/gcc/testsuite/lib/gcov.exp >>>> +++ b/gcc/testsuite/lib/gcov.exp >>>> @@ -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] } { >>>> -- >>>> 2.40.0 >>>> >>