1 //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains support for clang's and llvm's instrumentation based
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ProfileData/CoverageMapping.h"
18 using namespace coverage;
20 CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
21 Terms.resize(NumCounterValues);
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);
29 Expressions.push_back(E);
30 return Counter::getExpression(Expressions.size() - 1);
33 void CounterExpressionBuilder::extractTerms(Counter C, int Sign) {
34 switch (C.getKind()) {
37 case Counter::CounterValueReference:
38 Terms[C.getCounterID()] += Sign;
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);
48 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
49 // Gather constant terms.
52 extractTerms(ExpressionTree);
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) {
61 for (int J = 0; J < Terms[I]; ++J) {
63 C = Counter::getCounter(I);
65 C = get(CounterExpression(CounterExpression::Add, C,
66 Counter::getCounter(I)));
70 // Create subtractions.
71 for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
74 for (int J = 0; J < (-Terms[I]); ++J)
75 C = get(CounterExpression(CounterExpression::Subtract, C,
76 Counter::getCounter(I)));
81 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
82 return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
85 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
87 get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
90 void CounterMappingContext::dump(const Counter &C,
91 llvm::raw_ostream &OS) const {
92 switch (C.getKind()) {
96 case Counter::CounterValueReference:
97 OS << '#' << C.getCounterID();
99 case Counter::Expression: {
100 if (C.getExpressionID() >= Expressions.size())
102 const auto &E = Expressions[C.getExpressionID()];
105 OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
111 if (CounterValues.empty())
113 std::error_code Error;
114 auto Value = evaluate(C, Error);
117 OS << '[' << Value << ']';
120 int64_t CounterMappingContext::evaluate(const Counter &C,
121 std::error_code *EC) const {
122 switch (C.getKind()) {
125 case Counter::CounterValueReference:
126 if (C.getCounterID() >= CounterValues.size()) {
128 *EC = std::make_error_code(std::errc::argument_out_of_domain);
131 return CounterValues[C.getCounterID()];
132 case Counter::Expression: {
133 if (C.getExpressionID() >= Expressions.size()) {
135 *EC = std::make_error_code(std::errc::argument_out_of_domain);
138 const auto &E = Expressions[C.getExpressionID()];
139 auto LHS = evaluate(E.LHS, EC);
142 auto RHS = evaluate(E.RHS, EC);
145 return E.Kind == CounterExpression::Subtract ? LHS - RHS : LHS + RHS;