llvm-cov: Simplify CounterMappingRegion, pushing logic to its user
[oota-llvm.git] / include / llvm / ProfileData / CoverageMapping.h
1 //=-- CoverageMapping.h - 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 // Code coverage mapping data is generated by clang and read by
11 // llvm-cov to show code coverage statistics for a file.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_
16 #define LLVM_PROFILEDATA_COVERAGEMAPPING_H_
17
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/Support/ErrorOr.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include <system_error>
22
23 namespace llvm {
24 namespace coverage {
25
26 struct CounterExpressions;
27
28 enum CoverageMappingVersion { CoverageMappingVersion1 };
29
30 /// \brief A Counter is an abstract value that describes how to compute the
31 /// execution count for a region of code using the collected profile count data.
32 struct Counter {
33   enum CounterKind { Zero, CounterValueReference, Expression };
34   static const unsigned EncodingTagBits = 2;
35   static const unsigned EncodingTagMask = 0x3;
36   static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
37       EncodingTagBits + 1;
38
39 private:
40   CounterKind Kind;
41   unsigned ID;
42
43   Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
44
45 public:
46   Counter() : Kind(Zero), ID(0) {}
47
48   CounterKind getKind() const { return Kind; }
49
50   bool isZero() const { return Kind == Zero; }
51
52   bool isExpression() const { return Kind == Expression; }
53
54   unsigned getCounterID() const { return ID; }
55
56   unsigned getExpressionID() const { return ID; }
57
58   bool operator==(const Counter &Other) const {
59     return Kind == Other.Kind && ID == Other.ID;
60   }
61
62   /// \brief Return the counter that represents the number zero.
63   static Counter getZero() { return Counter(); }
64
65   /// \brief Return the counter that corresponds to a specific profile counter.
66   static Counter getCounter(unsigned CounterId) {
67     return Counter(CounterValueReference, CounterId);
68   }
69
70   /// \brief Return the counter that corresponds to a specific
71   /// addition counter expression.
72   static Counter getExpression(unsigned ExpressionId) {
73     return Counter(Expression, ExpressionId);
74   }
75 };
76
77 /// \brief A Counter expression is a value that represents an arithmetic
78 /// operation with two counters.
79 struct CounterExpression {
80   enum ExprKind { Subtract, Add };
81   ExprKind Kind;
82   Counter LHS, RHS;
83
84   CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
85       : Kind(Kind), LHS(LHS), RHS(RHS) {}
86
87   bool operator==(const CounterExpression &Other) const {
88     return Kind == Other.Kind && LHS == Other.LHS && RHS == Other.RHS;
89   }
90 };
91
92 /// \brief A Counter expression builder is used to construct the
93 /// counter expressions. It avoids unecessary duplication
94 /// and simplifies algebraic expressions.
95 class CounterExpressionBuilder {
96   /// \brief A list of all the counter expressions
97   llvm::SmallVector<CounterExpression, 16> Expressions;
98   /// \brief An array of terms used in expression simplification.
99   llvm::SmallVector<int, 16> Terms;
100
101   /// \brief Return the counter which corresponds to the given expression.
102   ///
103   /// If the given expression is already stored in the builder, a counter
104   /// that references that expression is returned. Otherwise, the given
105   /// expression is added to the builder's collection of expressions.
106   Counter get(const CounterExpression &E);
107
108   /// \brief Convert the expression tree represented by a counter
109   /// into a polynomial in the form of K1Counter1 + .. + KNCounterN
110   /// where K1 .. KN are integer constants that are stored in the Terms array.
111   void extractTerms(Counter C, int Sign = 1);
112
113   /// \brief Simplifies the given expression tree
114   /// by getting rid of algebraically redundant operations.
115   Counter simplify(Counter ExpressionTree);
116
117 public:
118   CounterExpressionBuilder(unsigned NumCounterValues);
119
120   ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
121
122   /// \brief Return a counter that represents the expression
123   /// that adds LHS and RHS.
124   Counter add(Counter LHS, Counter RHS);
125
126   /// \brief Return a counter that represents the expression
127   /// that subtracts RHS from LHS.
128   Counter subtract(Counter LHS, Counter RHS);
129 };
130
131 /// \brief A Counter mapping region associates a source range with
132 /// a specific counter.
133 struct CounterMappingRegion {
134   enum RegionKind {
135     /// \brief A CodeRegion associates some code with a counter
136     CodeRegion,
137
138     /// \brief An ExpansionRegion represents a file expansion region that
139     /// associates a source range with the expansion of a virtual source file,
140     /// such as for a macro instantiation or #include file.
141     ExpansionRegion,
142
143     /// \brief A SkippedRegion represents a source range with code that
144     /// was skipped by a preprocessor or similar means.
145     SkippedRegion
146   };
147
148   static const unsigned EncodingHasCodeBeforeBits = 1;
149
150   Counter Count;
151   unsigned FileID, ExpandedFileID;
152   unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
153   RegionKind Kind;
154   /// \brief A flag that is set to true when there is already code before
155   /// this region on the same line.
156   /// This is useful to accurately compute the execution counts for a line.
157   bool HasCodeBefore;
158
159   CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart,
160                        unsigned ColumnStart, unsigned LineEnd,
161                        unsigned ColumnEnd, bool HasCodeBefore = false,
162                        RegionKind Kind = CodeRegion)
163       : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart),
164         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
165         Kind(Kind), HasCodeBefore(HasCodeBefore) {}
166
167   inline std::pair<unsigned, unsigned> startLoc() const {
168     return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
169   }
170
171   inline std::pair<unsigned, unsigned> endLoc() const {
172     return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd);
173   }
174
175   bool operator<(const CounterMappingRegion &Other) const {
176     if (FileID != Other.FileID)
177       return FileID < Other.FileID;
178     return startLoc() < Other.startLoc();
179   }
180
181   bool contains(const CounterMappingRegion &Other) const {
182     if (FileID != Other.FileID)
183       return false;
184     if (startLoc() > Other.startLoc())
185       return false;
186     if (endLoc() < Other.endLoc())
187       return false;
188     return true;
189   }
190 };
191
192 /// \brief Associates a source range with an execution count.
193 struct CountedRegion : public CounterMappingRegion {
194   uint64_t ExecutionCount;
195
196   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
197       : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
198 };
199
200 /// \brief A Counter mapping context is used to connect the counters,
201 /// expressions and the obtained counter values.
202 class CounterMappingContext {
203   ArrayRef<CounterExpression> Expressions;
204   ArrayRef<uint64_t> CounterValues;
205
206 public:
207   CounterMappingContext(ArrayRef<CounterExpression> Expressions,
208                         ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
209       : Expressions(Expressions), CounterValues(CounterValues) {}
210
211   void dump(const Counter &C, llvm::raw_ostream &OS) const;
212   void dump(const Counter &C) const { dump(C, llvm::outs()); }
213
214   /// \brief Return the number of times that a region of code associated with
215   /// this counter was executed.
216   ErrorOr<int64_t> evaluate(const Counter &C) const;
217 };
218
219 /// \brief Code coverage information for a single function.
220 struct FunctionCoverageMapping {
221   /// \brief Raw function name.
222   std::string Name;
223   /// \brief Associated files.
224   std::vector<std::string> Filenames;
225   /// \brief Regions in the function along with their counts.
226   std::vector<CountedRegion> CountedRegions;
227
228   FunctionCoverageMapping(StringRef Name, ArrayRef<StringRef> Filenames)
229       : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
230 };
231
232 } // end namespace coverage
233 } // end namespace llvm
234
235 #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_