xref: /netbsd-src/external/gpl3/gcc/dist/contrib/jit-coverage-report.py (revision 4d5abbe83f525258eb479e5fca29f25cb943f379)
1*4d5abbe8Smrg#! /usr/bin/python
2*4d5abbe8Smrg#
3*4d5abbe8Smrg# Print a report on which libgccjit.so symbols are used in which test
4*4d5abbe8Smrg# cases, and which lack test coverage.  Tested with Python 2.7 and 3.2
5*4d5abbe8Smrg# To be run from the root directory of the source tree.
6*4d5abbe8Smrg#
7*4d5abbe8Smrg# Copyright (C) 2014 Free Software Foundation, Inc.
8*4d5abbe8Smrg# Written by David Malcolm <dmalcolm@redhat.com>.
9*4d5abbe8Smrg#
10*4d5abbe8Smrg# This script is Free Software, and it can be copied, distributed and
11*4d5abbe8Smrg# modified as defined in the GNU General Public License.  A copy of
12*4d5abbe8Smrg# its license can be downloaded from http://www.gnu.org/copyleft/gpl.html
13*4d5abbe8Smrg
14*4d5abbe8Smrgfrom collections import Counter
15*4d5abbe8Smrgimport glob
16*4d5abbe8Smrgimport re
17*4d5abbe8Smrgimport sys
18*4d5abbe8Smrg
19*4d5abbe8Smrgdef parse_map_file(path):
20*4d5abbe8Smrg    """
21*4d5abbe8Smrg    Parse libgccjit.map, returning the symbols in the API as a list of str.
22*4d5abbe8Smrg    """
23*4d5abbe8Smrg    syms = []
24*4d5abbe8Smrg    with open(path) as f:
25*4d5abbe8Smrg        for line in f:
26*4d5abbe8Smrg            m = re.match('^\s+([a-z_]+);$', line)
27*4d5abbe8Smrg            if m:
28*4d5abbe8Smrg                syms.append(m.group(1))
29*4d5abbe8Smrg    return syms
30*4d5abbe8Smrg
31*4d5abbe8Smrgdef parse_test_case(path):
32*4d5abbe8Smrg    """
33*4d5abbe8Smrg    Locate all symbol-like things in a C test case, yielding
34*4d5abbe8Smrg    them as a sequence of str.
35*4d5abbe8Smrg    """
36*4d5abbe8Smrg    with open(path) as f:
37*4d5abbe8Smrg        for line in f:
38*4d5abbe8Smrg            for m in re.finditer('([_A-Za-z][_A-Za-z0-9]*)', line):
39*4d5abbe8Smrg                yield m.group(1)
40*4d5abbe8Smrg
41*4d5abbe8Smrgdef find_test_cases():
42*4d5abbe8Smrg    for path in glob.glob('gcc/testsuite/jit.dg/*.[ch]'):
43*4d5abbe8Smrg        yield path
44*4d5abbe8Smrg
45*4d5abbe8Smrgapi_syms = parse_map_file('gcc/jit/libgccjit.map')
46*4d5abbe8Smrg
47*4d5abbe8Smrgsyms_in_test_cases = {}
48*4d5abbe8Smrgfor path in find_test_cases():
49*4d5abbe8Smrg    syms_in_test_cases[path] = list(parse_test_case(path))
50*4d5abbe8Smrg
51*4d5abbe8Smrguses = Counter()
52*4d5abbe8Smrgfor sym in sorted(api_syms):
53*4d5abbe8Smrg    print('symbol: %s' % sym)
54*4d5abbe8Smrg    uses[sym] = 0
55*4d5abbe8Smrg    for path in syms_in_test_cases:
56*4d5abbe8Smrg        count = syms_in_test_cases[path].count(sym)
57*4d5abbe8Smrg        uses[sym] += count
58*4d5abbe8Smrg        if count:
59*4d5abbe8Smrg            print('  uses in %s: %i' % (path, count))
60*4d5abbe8Smrg    if uses[sym] == 0:
61*4d5abbe8Smrg        print('  NEVER USED')
62*4d5abbe8Smrg    sys.stdout.write('\n')
63*4d5abbe8Smrg
64*4d5abbe8Smrglayout = '%40s  %5s  %s'
65*4d5abbe8Smrgprint(layout % ('SYMBOL', 'USES', 'HISTOGRAM'))
66*4d5abbe8Smrgfor sym, count in uses.most_common():
67*4d5abbe8Smrg    print(layout % (sym, count, '*' * count if count else 'UNUSED'))
68