LLVM API Documentation
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 }