aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorJørgen Kvalsvik <j@lambda.is>2024-07-04 09:42:24 +0200
committerJørgen Kvalsvik <j@lambda.is>2024-09-08 22:23:49 +0200
commit1e17a11171dae2bc5d60380bf48c12ef49f59c7f (patch)
tree8967185e763e6f15948c7c6ce129fbf097a09919 /gcc/fortran
parentb8cd236cbef60fc52524b41e2ca173eb12528792 (diff)
downloadgcc-1e17a11171dae2bc5d60380bf48c12ef49f59c7f.zip
gcc-1e17a11171dae2bc5d60380bf48c12ef49f59c7f.tar.gz
gcc-1e17a11171dae2bc5d60380bf48c12ef49f59c7f.tar.bz2
gcov: Cache source files
Cache the source files as they are read, rather than discarding them at the end of output_lines (), and move the reading of the source file to the new function slurp. This patch does not really change anything other than moving the file reading out of output_file, but set gcov up for more interaction with the source file. The motvating example is reporting coverage on functions from different source files, notably C++ headers and ((always_inline)). Here is an example of what gcov does today: hello.h: inline __attribute__((always_inline)) int hello (const char *s) { if (s) printf ("hello, %s!\n", s); else printf ("hello, world!\n"); return 0; } hello.c: int notmain(const char *entity) { return hello (entity); } int main() { const char *empty = 0; if (!empty) hello (empty); else puts ("Goodbye!"); } $ gcov -abc hello function notmain called 0 returned 0% blocks executed 0% #####: 4:int notmain(const char *entity) %%%%%: 4-block 2 branch 0 never executed (fallthrough) branch 1 never executed -: 5:{ #####: 6: return hello (entity); %%%%%: 6-block 7 -: 7:} Clearly there is a branch in notmain, but the branch comes from the inlining of hello. This is not very obvious from looking at the output. Here is hello.h.gcov: -: 3:inline __attribute__((always_inline)) -: 4:int hello (const char *s) -: 5:{ #####: 6: if (s) %%%%%: 6-block 3 branch 0 never executed (fallthrough) branch 1 never executed %%%%%: 6-block 2 branch 2 never executed (fallthrough) branch 3 never executed #####: 7: printf ("hello, %s!\n", s); %%%%%: 7-block 4 call 0 never executed %%%%%: 7-block 3 call 1 never executed -: 8: else #####: 9: printf ("hello, world!\n"); %%%%%: 9-block 5 call 0 never executed %%%%%: 9-block 4 call 1 never executed #####: 10: return 0; %%%%%: 10-block 6 %%%%%: 10-block 5 -: 11:} The blocks from the different call sites have all been interleaved. The reporting could tuned be to list the inlined function, too, like this: 1: 4:int notmain(const char *entity) -: == inlined from hello.h == 1: 6: if (s) branch 0 taken 0 (fallthrough) branch 1 taken 1 #####: 7: printf ("hello, %s!\n", s); %%%%%: 7-block 3 call 0 never executed -: 8: else 1: 9: printf ("hello, world!\n"); 1: 9-block 4 call 0 returned 1 1: 10: return 0; 1: 10-block 5 -: == inlined from hello.h (end) == -: 5:{ 1: 6: return hello (entity); 1: 6-block 7 -: 7:} Implementing something to this effect relies on having the sources for both files (hello.c, hello.h) available, which is what this patch sets up. Note that the previous reading code would leak the source file content, and explicitly storing them is not a huge departure nor performance implication. I verified this with valgrind: With slurp: $ valgrind gcov ./hello == == Memcheck, a memory error detector == == Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. == == Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info == == Command: ./gcc/gcov demo == == File 'hello.c' Lines executed:100.00% of 4 Creating 'hello.c.gcov' File 'hello.h' Lines executed:75.00% of 4 Creating 'hello.h.gcov' == == == == HEAP SUMMARY: == == in use at exit: 84,907 bytes in 54 blocks == == total heap usage: 254 allocs, 200 frees, 137,156 bytes allocated == == == == LEAK SUMMARY: == == definitely lost: 1,237 bytes in 22 blocks == == indirectly lost: 562 bytes in 18 blocks == == possibly lost: 0 bytes in 0 blocks == == still reachable: 83,108 bytes in 14 blocks == == of which reachable via heuristic: == == newarray : 1,544 bytes in 1 blocks == == suppressed: 0 bytes in 0 blocks == == Rerun with --leak-check=full to see details of leaked memory == == == == For lists of detected and suppressed errors, rerun with: -s == == ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Without slurp: $ valgrind gcov ./demo == == Memcheck, a memory error detector == == Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. == == Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info == == Command: ./gcc/gcov demo == == File 'hello.c' Lines executed:100.00% of 4 Creating 'hello.c.gcov' File 'hello.h' Lines executed:75.00% of 4 Creating 'hello.h.gcov' Lines executed:87.50% of 8 == == == == HEAP SUMMARY: == == in use at exit: 85,316 bytes in 82 blocks == == total heap usage: 250 allocs, 168 frees, 137,084 bytes allocated == == == == LEAK SUMMARY: == == definitely lost: 1,646 bytes in 50 blocks == == indirectly lost: 562 bytes in 18 blocks == == possibly lost: 0 bytes in 0 blocks == == still reachable: 83,108 bytes in 14 blocks == == of which reachable via heuristic: == == newarray : 1,544 bytes in 1 blocks == == suppressed: 0 bytes in 0 blocks == == Rerun with --leak-check=full to see details of leaked memory == == == == For lists of detected and suppressed errors, rerun with: -s == == ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) gcc/ChangeLog: * gcov.cc (release_structures): Release source_lines. (slurp): New function. (output_lines): Read sources with slurp.
Diffstat (limited to 'gcc/fortran')
0 files changed, 0 insertions, 0 deletions