blob: d08ec403d3217968df5108e78889e541e4f92169 [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"
Justin Bogner85b0a032014-09-08 21:04:00 +000016#include "llvm/Support/ErrorHandling.h"
Alex Lorenza20a5d52014-07-24 23:57:54 +000017
18using namespace llvm;
19using namespace coverage;
20
21CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
22 Terms.resize(NumCounterValues);
23}
24
25Counter 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
34void 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
49Counter 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
82Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
83 return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
84}
85
86Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
87 return simplify(
88 get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
89}
90
91void 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 << '(';
Alex Lorenza422911c2014-07-29 19:58:16 +0000105 dump(E.LHS, OS);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000106 OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
Alex Lorenza422911c2014-07-29 19:58:16 +0000107 dump(E.RHS, OS);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000108 OS << ')';
109 break;
110 }
111 }
112 if (CounterValues.empty())
113 return;
Justin Bogner85b0a032014-09-08 21:04:00 +0000114 ErrorOr<int64_t> Value = evaluate(C);
115 if (!Value)
Alex Lorenza20a5d52014-07-24 23:57:54 +0000116 return;
Justin Bogner85b0a032014-09-08 21:04:00 +0000117 OS << '[' << *Value << ']';
Alex Lorenza20a5d52014-07-24 23:57:54 +0000118}
119
Justin Bogner85b0a032014-09-08 21:04:00 +0000120ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000121 switch (C.getKind()) {
122 case Counter::Zero:
123 return 0;
124 case Counter::CounterValueReference:
Justin Bogner85b0a032014-09-08 21:04:00 +0000125 if (C.getCounterID() >= CounterValues.size())
Justin Bogner3f188342014-09-08 21:31:43 +0000126 return std::make_error_code(std::errc::argument_out_of_domain);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000127 return CounterValues[C.getCounterID()];
128 case Counter::Expression: {
Justin Bogner85b0a032014-09-08 21:04:00 +0000129 if (C.getExpressionID() >= Expressions.size())
Justin Bogner3f188342014-09-08 21:31:43 +0000130 return std::make_error_code(std::errc::argument_out_of_domain);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000131 const auto &E = Expressions[C.getExpressionID()];
Justin Bogner85b0a032014-09-08 21:04:00 +0000132 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;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000139 }
140 }
Justin Bogner85b0a032014-09-08 21:04:00 +0000141 llvm_unreachable("Unhandled CounterKind");
Alex Lorenza20a5d52014-07-24 23:57:54 +0000142}