about summary refs log tree commit diff homepage
path: root/scripts/IStatsSum.py
blob: 0546e8955ecd187fc7eb4afb8aa2067acc1e4def (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/python

# ===-- IStatsSum.py ------------------------------------------------------===##
# 
#                      The KLEE Symbolic Virtual Machine
# 
#  This file is distributed under the University of Illinois Open Source
#  License. See LICENSE.TXT for details.
# 
# ===----------------------------------------------------------------------===##

from __future__ import division

import sys, os

def getSummary(input):
    inputs = [[None,iter(open(input))]]
    def getLine(elt):
        la,i = elt
        if la is None:
            try:
                ln = i.next()
            except StopIteration:
                ln = None
            except:
                raise ValueError("unexpected IO error")
            return ln
        else:
            elt[0] = None
            return la
    def getLines():
        return map(getLine,inputs)
    def putback(ln,elt):
        assert elt[0] is None
        elt[0] = ln
        
    events = None
    
    # read header (up to ob=)
    while 1:
        lns = getLines()
        ln = lns[0]
        if ln.startswith('ob='):
            break
        else:
            if ln.startswith('positions:'):
                if ln!='positions: instr line\n':
                    raise ValueError("unexpected 'positions' directive")
            elif ln.startswith('events:'):
                events = ln[len('events: '):].strip().split(' ')

    if events is None:
        raise ValueError('missing events directive')
    boolTypes = set(['Icov','Iuncov'])
    numEvents = len(events)
    eventTypes = [e in boolTypes for e in events]

    def readCalls():
        results = {}
        for elt in inputs:
            while 1:
                ln = getLine(elt)
                if ln is not None and (ln.startswith('cfl=') or ln.startswith('cfn=')):
                    if ln.startswith('cfl='):
                        cfl = ln
                        cfn = getLine(elt)
                        if not cfn.startswith('cfn='):
                            raise ValueError("unexpected cfl directive without function")
                    else:
                        cfl = None
                        cfn = ln
                    target = getLine(elt)
                    if not target.startswith('calls='):
                        raise ValueError("unexpected cfn directive with calls")
                    stat = map(int,getLine(elt).strip().split(' '))
                    key = target
                    existing = results.get(target)
                    if existing is None:
                        results[key] = [cfl,cfn,target,stat]
                    else:
                        if existing[0]!=cfl or existing[1]!=cfn:
                            raise ValueError("multiple call descriptions for a single target")
                        existing[3] = mergeStats([existing[3],stat])
                else:
                    putback(ln, elt)
                    break
        return results

    summed = [0]*len(events)
    
    # read statistics
    while 1:
        lns = getLines()
        ln = lns[0]
        if ln is None:
            break
        elif ln.startswith('fn') or ln.startswith('fl'):
            pass
        elif ln.strip():
            # an actual statistic
            data = [map(int,ln.strip().split(' ')) for ln in lns][0]
            summed = map(lambda a,b: a+b, data[2:], summed)

            # read any associated calls
            for cfl,cfn,calls,stat in readCalls().values():
                pass

    return events,summed
    
def main(args):
    from optparse import OptionParser
    op = OptionParser("usage: %prog [options] file")
    opts,args = op.parse_args()

    total = {}
    for i in args:
        events,summed = getSummary(i)
        for e,s in zip(events,summed):
            total[e] = total.get(e,[0,0])
            total[e][0] += s
            total[e][1] += 1
        print '-- %s --'%(i,)
        items = zip(events,summed)
        items.sort()
        for e,s in items:
            print '%s: %s'%(e,s)

    print '-- totals --'
    items = total.items()
    table = []    
    for e,(s,N) in items:
        table.append((str(e),str(s),str(N),str(s//N)))
    w = map(lambda l: max(map(len,l)), zip(*table))
    for (a,b,c,d) in table:
        print '%-*s: %*s (in %*s files, avg: %*s)'%(w[0],a,w[1],b,w[2],c,w[3],d)

if __name__=='__main__':
    main(sys.argv)