blob: 30132a3f749fe7370cbfcd013df11773a958869a [file] [log] [blame]
Alex Lorenza20a5d52014-07-24 23:57:54 +00001//=-- 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
17using namespace llvm;
18using namespace coverage;
19
20CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
21 Terms.resize(NumCounterValues);
22}
23
24Counter 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
33void 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
48Counter 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
81Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
82 return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
83}
84
85Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
86 return simplify(
87 get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
88}
89
90void 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
120int64_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}