Message ID | 3041a27a-8599-23da-237b-d802f83c40ae@suse.cz |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8FA53385771A for <patchwork@sourceware.org>; Thu, 6 Apr 2023 13:58:56 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id 6F87B3858D28 for <gcc-patches@gcc.gnu.org>; Thu, 6 Apr 2023 13:58:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6F87B3858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 1910F22723; Thu, 6 Apr 2023 13:58:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1680789516; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=HnjBoi7BfJ/ui6OQ76lFBbf8CJF0+19uBuqA9Pm8kZA=; b=QIyHhDJWtKGw7pGopGgt7iOxcDH+7f0E/hcYbkQZ2zXAlRhyt/jcSTvjHIofQIS82ECTNN sVrOumkPYgOIstoiwQPg1UZJzB1b8Sij7aTDymdTmlY9Nydm1xCunZkaMf3fHU1QaZ6Wam IWt+m4Q4mg7KqZ/dAC/1ABU9meKOQjc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1680789516; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=HnjBoi7BfJ/ui6OQ76lFBbf8CJF0+19uBuqA9Pm8kZA=; b=AaQsSowMwAI0y17Ch+HxmuWccJCokohav+MBFv8hvLP1SHEXH5ap4Gl1DfRpOKIS9mjUHL 7pdtr1er92JaJzCg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 057421351F; Thu, 6 Apr 2023 13:58:35 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 89M4OwvQLmRxHAAAMHmgww (envelope-from <mliska@suse.cz>); Thu, 06 Apr 2023 13:58:35 +0000 Message-ID: <3041a27a-8599-23da-237b-d802f83c40ae@suse.cz> Date: Thu, 6 Apr 2023 15:58:35 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 From: =?utf-8?q?Martin_Li=C5=A1ka?= <mliska@suse.cz> Subject: [PATCH] gcov: add info about "calls" to JSON output format To: gcc-patches@gcc.gnu.org Content-Language: en-US Cc: Jan Hubicka <hubicka@ucw.cz>, Richard Biener <richard.guenther@gmail.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
gcov: add info about "calls" to JSON output format
|
|
Commit Message
Martin Liška
April 6, 2023, 1:58 p.m. UTC
Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed after stage1 opens? 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(-)
Comments
On Thu, Apr 6, 2023 at 3:58 PM Martin Liška <mliska@suse.cz> 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 this in before 13.1 ... Up to Honza. 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<arc_info *>::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<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; > } > > 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 >
On 4/11/23 11:23, Richard Biener wrote: > On Thu, Apr 6, 2023 at 3:58 PM Martin Liška <mliska@suse.cz> 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! 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<arc_info *>::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<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; >> } >> >> 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 >>
> On 4/11/23 11:23, Richard Biener wrote: > > On Thu, Apr 6, 2023 at 3:58 PM Martin Liška <mliska@suse.cz> 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? 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? 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?) 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<arc_info *>::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<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; > >> } > >> > >> 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 > >> >
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 <mliska@suse.cz> 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<arc_info *>::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<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; >>>> } >>>> >>>> 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 >>>> >>
Hello. After discussion with the consumers of the format: https://github.com/gcovr/gcovr/issues/282#issuecomment-1534239536 I'm going to push a patch that prints JSON version in gcov -v. Thanks, Martin
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<arc_info *>::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<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; } 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] } {