Add code coverage mapping data, reader, and writer.
[oota-llvm.git] / lib / ProfileData / CoverageMapping.cpp
1 //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for clang's and llvm's instrumentation based
11 // code coverage.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ProfileData/CoverageMapping.h"
16
17 using namespace llvm;
18 using namespace coverage;
19
20 CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
21   Terms.resize(NumCounterValues);
22 }
23
24 Counter CounterExpressionBuilder::get(const CounterExpression &E) {
25   for (unsigned I = 0, S = Expressions.size(); I < S; ++I) {
26     if (Expressions[I] == E)
27       return Counter::getExpression(I);
28   }
29   Expressions.push_back(E);
30   return Counter::getExpression(Expressions.size() - 1);
31 }
32
33 void CounterExpressionBuilder::extractTerms(Counter C, int Sign) {
34   switch (C.getKind()) {
35   case Counter::Zero:
36     break;
37   case Counter::CounterValueReference:
38     Terms[C.getCounterID()] += Sign;
39     break;
40   case Counter::Expression:
41     const auto &E = Expressions[C.getExpressionID()];
42     extractTerms(E.LHS, Sign);
43     extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign);
44     break;
45   }
46 }
47
48 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
49   // Gather constant terms.
50   for (auto &I : Terms)
51     I = 0;
52   extractTerms(ExpressionTree);
53
54   Counter C;
55   // Create additions.
56   // Note: the additions are created first
57   // to avoid creation of a tree like ((0 - X) + Y) instead of (Y - X).
58   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
59     if (Terms[I] <= 0)
60       continue;
61     for (int J = 0; J < Terms[I]; ++J) {
62       if (C.isZero())
63         C = Counter::getCounter(I);
64       else
65         C = get(CounterExpression(CounterExpression::Add, C,
66                                   Counter::getCounter(I)));
67     }
68   }
69
70   // Create subtractions.
71   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
72     if (Terms[I] >= 0)
73       continue;
74     for (int J = 0; J < (-Terms[I]); ++J)
75       C = get(CounterExpression(CounterExpression::Subtract, C,
76                                 Counter::getCounter(I)));
77   }
78   return C;
79 }
80
81 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
82   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
83 }
84
85 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
86   return simplify(
87       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
88 }
89
90 void CounterMappingContext::dump(const Counter &C,
91                                  llvm::raw_ostream &OS) const {
92   switch (C.getKind()) {
93   case Counter::Zero:
94     OS << '0';
95     return;
96   case Counter::CounterValueReference:
97     OS << '#' << C.getCounterID();
98     break;
99   case Counter::Expression: {
100     if (C.getExpressionID() >= Expressions.size())
101       return;
102     const auto &E = Expressions[C.getExpressionID()];
103     OS << '(';
104     dump(E.LHS);
105     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
106     dump(E.RHS);
107     OS << ')';
108     break;
109   }
110   }
111   if (CounterValues.empty())
112     return;
113   std::error_code Error;
114   auto Value = evaluate(C, Error);
115   if (Error)
116     return;
117   OS << '[' << Value << ']';
118 }
119
120 int64_t CounterMappingContext::evaluate(const Counter &C,
121                                         std::error_code *EC) const {
122   switch (C.getKind()) {
123   case Counter::Zero:
124     return 0;
125   case Counter::CounterValueReference:
126     if (C.getCounterID() >= CounterValues.size()) {
127       if (EC)
128         *EC = std::make_error_code(std::errc::argument_out_of_domain);
129       break;
130     }
131     return CounterValues[C.getCounterID()];
132   case Counter::Expression: {
133     if (C.getExpressionID() >= Expressions.size()) {
134       if (EC)
135         *EC = std::make_error_code(std::errc::argument_out_of_domain);
136       break;
137     }
138     const auto &E = Expressions[C.getExpressionID()];
139     auto LHS = evaluate(E.LHS, EC);
140     if (EC && *EC)
141       return 0;
142     auto RHS = evaluate(E.RHS, EC);
143     if (EC && *EC)
144       return 0;
145     return E.Kind == CounterExpression::Subtract ? LHS - RHS : LHS + RHS;
146   }
147   }
148   return 0;
149 }