LLVM API Documentation

CoverageMapping.cpp
Go to the documentation of this file.
00001 //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains support for clang's and llvm's instrumentation based
00011 // code coverage.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/ProfileData/CoverageMapping.h"
00016 #include "llvm/Support/ErrorHandling.h"
00017 
00018 using namespace llvm;
00019 using namespace coverage;
00020 
00021 CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
00022   Terms.resize(NumCounterValues);
00023 }
00024 
00025 Counter CounterExpressionBuilder::get(const CounterExpression &E) {
00026   for (unsigned I = 0, S = Expressions.size(); I < S; ++I) {
00027     if (Expressions[I] == E)
00028       return Counter::getExpression(I);
00029   }
00030   Expressions.push_back(E);
00031   return Counter::getExpression(Expressions.size() - 1);
00032 }
00033 
00034 void CounterExpressionBuilder::extractTerms(Counter C, int Sign) {
00035   switch (C.getKind()) {
00036   case Counter::Zero:
00037     break;
00038   case Counter::CounterValueReference:
00039     Terms[C.getCounterID()] += Sign;
00040     break;
00041   case Counter::Expression:
00042     const auto &E = Expressions[C.getExpressionID()];
00043     extractTerms(E.LHS, Sign);
00044     extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign);
00045     break;
00046   }
00047 }
00048 
00049 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
00050   // Gather constant terms.
00051   for (auto &I : Terms)
00052     I = 0;
00053   extractTerms(ExpressionTree);
00054 
00055   Counter C;
00056   // Create additions.
00057   // Note: the additions are created first
00058   // to avoid creation of a tree like ((0 - X) + Y) instead of (Y - X).
00059   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
00060     if (Terms[I] <= 0)
00061       continue;
00062     for (int J = 0; J < Terms[I]; ++J) {
00063       if (C.isZero())
00064         C = Counter::getCounter(I);
00065       else
00066         C = get(CounterExpression(CounterExpression::Add, C,
00067                                   Counter::getCounter(I)));
00068     }
00069   }
00070 
00071   // Create subtractions.
00072   for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
00073     if (Terms[I] >= 0)
00074       continue;
00075     for (int J = 0; J < (-Terms[I]); ++J)
00076       C = get(CounterExpression(CounterExpression::Subtract, C,
00077                                 Counter::getCounter(I)));
00078   }
00079   return C;
00080 }
00081 
00082 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
00083   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
00084 }
00085 
00086 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
00087   return simplify(
00088       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
00089 }
00090 
00091 void CounterMappingContext::dump(const Counter &C,
00092                                  llvm::raw_ostream &OS) const {
00093   switch (C.getKind()) {
00094   case Counter::Zero:
00095     OS << '0';
00096     return;
00097   case Counter::CounterValueReference:
00098     OS << '#' << C.getCounterID();
00099     break;
00100   case Counter::Expression: {
00101     if (C.getExpressionID() >= Expressions.size())
00102       return;
00103     const auto &E = Expressions[C.getExpressionID()];
00104     OS << '(';
00105     dump(E.LHS, OS);
00106     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
00107     dump(E.RHS, OS);
00108     OS << ')';
00109     break;
00110   }
00111   }
00112   if (CounterValues.empty())
00113     return;
00114   ErrorOr<int64_t> Value = evaluate(C);
00115   if (!Value)
00116     return;
00117   OS << '[' << *Value << ']';
00118 }
00119 
00120 ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
00121   switch (C.getKind()) {
00122   case Counter::Zero:
00123     return 0;
00124   case Counter::CounterValueReference:
00125     if (C.getCounterID() >= CounterValues.size())
00126       return std::make_error_code(std::errc::argument_out_of_domain);
00127     return CounterValues[C.getCounterID()];
00128   case Counter::Expression: {
00129     if (C.getExpressionID() >= Expressions.size())
00130       return std::make_error_code(std::errc::argument_out_of_domain);
00131     const auto &E = Expressions[C.getExpressionID()];
00132     ErrorOr<int64_t> LHS = evaluate(E.LHS);
00133     if (!LHS)
00134       return LHS;
00135     ErrorOr<int64_t> RHS = evaluate(E.RHS);
00136     if (!RHS)
00137       return RHS;
00138     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
00139   }
00140   }
00141   llvm_unreachable("Unhandled CounterKind");
00142 }