llvm-cov: Use ErrorOr rather than an error_code* (NFC)
[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 #include "llvm/Support/ErrorHandling.h"
17
18 using namespace llvm;
19 using namespace coverage;
20
21 CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
22   Terms.resize(NumCounterValues);
23 }
24
25 Counter CounterExpressionBuilder::get(const CounterExpression &E) {
26   for (unsigned I = 0, S = Expressions.size(); I < S; ++I) {
27     if (Expressions[I] == E)
28       return Counter::getExpression(I);
29   }
30   Expressions.push_back(E);
31   return Counter::getExpression(Expressions.size() - 1);
32 }
33
34 void CounterExpressionBuilder::extractTerms(Counter C, int Sign) {
35   switch (C.getKind()) {
36   case Counter::Zero:
37     break;
38   case Counter::CounterValueReference:
39     Terms[C.getCounterID()] += Sign;
40     break;
41   case Counter::Expression:
42     const auto &E = Expressions[C.getExpressionID()];
43     extractTerms(E.LHS, Sign);
44     extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign);
45     break;
46   }
47 }
48
49 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
50   // Gather constant terms.
51   for (auto &I : Terms)
52     I = 0;
53   extractTerms(ExpressionTree);
54
55   Counter C;
56   // Create additions.
57   // Note: the additions are created first
58   // to avoid creation of a tree like ((0 - X) + Y) instead of (Y - X).
59   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
60     if (Terms[I] <= 0)
61       continue;
62     for (int J = 0; J < Terms[I]; ++J) {
63       if (C.isZero())
64         C = Counter::getCounter(I);
65       else
66         C = get(CounterExpression(CounterExpression::Add, C,
67                                   Counter::getCounter(I)));
68     }
69   }
70
71   // Create subtractions.
72   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
73     if (Terms[I] >= 0)
74       continue;
75     for (int J = 0; J < (-Terms[I]); ++J)
76       C = get(CounterExpression(CounterExpression::Subtract, C,
77                                 Counter::getCounter(I)));
78   }
79   return C;
80 }
81
82 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
83   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
84 }
85
86 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
87   return simplify(
88       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
89 }
90
91 void CounterMappingContext::dump(const Counter &C,
92                                  llvm::raw_ostream &OS) const {
93   switch (C.getKind()) {
94   case Counter::Zero:
95     OS << '0';
96     return;
97   case Counter::CounterValueReference:
98     OS << '#' << C.getCounterID();
99     break;
100   case Counter::Expression: {
101     if (C.getExpressionID() >= Expressions.size())
102       return;
103     const auto &E = Expressions[C.getExpressionID()];
104     OS << '(';
105     dump(E.LHS, OS);
106     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
107     dump(E.RHS, OS);
108     OS << ')';
109     break;
110   }
111   }
112   if (CounterValues.empty())
113     return;
114   ErrorOr<int64_t> Value = evaluate(C);
115   if (!Value)
116     return;
117   OS << '[' << *Value << ']';
118 }
119
120 ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
121   switch (C.getKind()) {
122   case Counter::Zero:
123     return 0;
124   case Counter::CounterValueReference:
125     if (C.getCounterID() >= CounterValues.size())
126       return std::errc::argument_out_of_domain;
127     return CounterValues[C.getCounterID()];
128   case Counter::Expression: {
129     if (C.getExpressionID() >= Expressions.size())
130       return std::errc::argument_out_of_domain;
131     const auto &E = Expressions[C.getExpressionID()];
132     ErrorOr<int64_t> LHS = evaluate(E.LHS);
133     if (!LHS)
134       return LHS;
135     ErrorOr<int64_t> RHS = evaluate(E.RHS);
136     if (!RHS)
137       return RHS;
138     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
139   }
140   }
141   llvm_unreachable("Unhandled CounterKind");
142 }