InstrProf: Don't keep a large sparse list around just to zero it
[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 class IndexedInstrProfReader;
25 namespace coverage {
26
27 class ObjectFileCoverageMappingReader;
28
29 class CoverageMapping;
30 struct CounterExpressions;
31
32 enum CoverageMappingVersion { CoverageMappingVersion1 };
33
34 /// \brief A Counter is an abstract value that describes how to compute the
35 /// execution count for a region of code using the collected profile count data.
36 struct Counter {
37   enum CounterKind { Zero, CounterValueReference, Expression };
38   static const unsigned EncodingTagBits = 2;
39   static const unsigned EncodingTagMask = 0x3;
40   static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
41       EncodingTagBits + 1;
42
43 private:
44   CounterKind Kind;
45   unsigned ID;
46
47   Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
48
49 public:
50   Counter() : Kind(Zero), ID(0) {}
51
52   CounterKind getKind() const { return Kind; }
53
54   bool isZero() const { return Kind == Zero; }
55
56   bool isExpression() const { return Kind == Expression; }
57
58   unsigned getCounterID() const { return ID; }
59
60   unsigned getExpressionID() const { return ID; }
61
62   bool operator==(const Counter &Other) const {
63     return Kind == Other.Kind && ID == Other.ID;
64   }
65
66   friend bool operator<(const Counter &LHS, const Counter &RHS) {
67     return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
68   }
69
70   /// \brief Return the counter that represents the number zero.
71   static Counter getZero() { return Counter(); }
72
73   /// \brief Return the counter that corresponds to a specific profile counter.
74   static Counter getCounter(unsigned CounterId) {
75     return Counter(CounterValueReference, CounterId);
76   }
77
78   /// \brief Return the counter that corresponds to a specific
79   /// addition counter expression.
80   static Counter getExpression(unsigned ExpressionId) {
81     return Counter(Expression, ExpressionId);
82   }
83 };
84
85 /// \brief A Counter expression is a value that represents an arithmetic
86 /// operation with two counters.
87 struct CounterExpression {
88   enum ExprKind { Subtract, Add };
89   ExprKind Kind;
90   Counter LHS, RHS;
91
92   CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
93       : Kind(Kind), LHS(LHS), RHS(RHS) {}
94
95   bool operator==(const CounterExpression &Other) const {
96     return Kind == Other.Kind && LHS == Other.LHS && RHS == Other.RHS;
97   }
98 };
99
100 /// \brief A Counter expression builder is used to construct the
101 /// counter expressions. It avoids unecessary duplication
102 /// and simplifies algebraic expressions.
103 class CounterExpressionBuilder {
104   /// \brief A list of all the counter expressions
105   llvm::SmallVector<CounterExpression, 16> Expressions;
106
107   /// \brief Return the counter which corresponds to the given expression.
108   ///
109   /// If the given expression is already stored in the builder, a counter
110   /// that references that expression is returned. Otherwise, the given
111   /// expression is added to the builder's collection of expressions.
112   Counter get(const CounterExpression &E);
113
114   /// \brief Gather the terms of the expression tree for processing.
115   ///
116   /// This collects each addition and subtraction referenced by the counter into
117   /// a sequence that can be sorted and combined to build a simplified counter
118   /// expression.
119   void extractTerms(Counter C, int Sign,
120                     SmallVectorImpl<std::pair<unsigned, int>> &Terms);
121
122   /// \brief Simplifies the given expression tree
123   /// by getting rid of algebraically redundant operations.
124   Counter simplify(Counter ExpressionTree);
125
126 public:
127   ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
128
129   /// \brief Return a counter that represents the expression
130   /// that adds LHS and RHS.
131   Counter add(Counter LHS, Counter RHS);
132
133   /// \brief Return a counter that represents the expression
134   /// that subtracts RHS from LHS.
135   Counter subtract(Counter LHS, Counter RHS);
136 };
137
138 /// \brief A Counter mapping region associates a source range with
139 /// a specific counter.
140 struct CounterMappingRegion {
141   enum RegionKind {
142     /// \brief A CodeRegion associates some code with a counter
143     CodeRegion,
144
145     /// \brief An ExpansionRegion represents a file expansion region that
146     /// associates a source range with the expansion of a virtual source file,
147     /// such as for a macro instantiation or #include file.
148     ExpansionRegion,
149
150     /// \brief A SkippedRegion represents a source range with code that
151     /// was skipped by a preprocessor or similar means.
152     SkippedRegion
153   };
154
155   static const unsigned EncodingHasCodeBeforeBits = 1;
156
157   Counter Count;
158   unsigned FileID, ExpandedFileID;
159   unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
160   RegionKind Kind;
161   /// \brief A flag that is set to true when there is already code before
162   /// this region on the same line.
163   /// This is useful to accurately compute the execution counts for a line.
164   bool HasCodeBefore;
165
166   CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart,
167                        unsigned ColumnStart, unsigned LineEnd,
168                        unsigned ColumnEnd, bool HasCodeBefore = false,
169                        RegionKind Kind = CodeRegion)
170       : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart),
171         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
172         Kind(Kind), HasCodeBefore(HasCodeBefore) {}
173
174   inline std::pair<unsigned, unsigned> startLoc() const {
175     return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
176   }
177
178   inline std::pair<unsigned, unsigned> endLoc() const {
179     return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd);
180   }
181
182   bool operator<(const CounterMappingRegion &Other) const {
183     if (FileID != Other.FileID)
184       return FileID < Other.FileID;
185     return startLoc() < Other.startLoc();
186   }
187
188   bool contains(const CounterMappingRegion &Other) const {
189     if (FileID != Other.FileID)
190       return false;
191     if (startLoc() > Other.startLoc())
192       return false;
193     if (endLoc() < Other.endLoc())
194       return false;
195     return true;
196   }
197 };
198
199 /// \brief Associates a source range with an execution count.
200 struct CountedRegion : public CounterMappingRegion {
201   uint64_t ExecutionCount;
202
203   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
204       : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
205 };
206
207 /// \brief A Counter mapping context is used to connect the counters,
208 /// expressions and the obtained counter values.
209 class CounterMappingContext {
210   ArrayRef<CounterExpression> Expressions;
211   ArrayRef<uint64_t> CounterValues;
212
213 public:
214   CounterMappingContext(ArrayRef<CounterExpression> Expressions,
215                         ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
216       : Expressions(Expressions), CounterValues(CounterValues) {}
217
218   void dump(const Counter &C, llvm::raw_ostream &OS) const;
219   void dump(const Counter &C) const { dump(C, llvm::outs()); }
220
221   /// \brief Return the number of times that a region of code associated with
222   /// this counter was executed.
223   ErrorOr<int64_t> evaluate(const Counter &C) const;
224 };
225
226 /// \brief Code coverage information for a single function.
227 struct FunctionRecord {
228   /// \brief Raw function name.
229   std::string Name;
230   /// \brief Associated files.
231   std::vector<std::string> Filenames;
232   /// \brief Regions in the function along with their counts.
233   std::vector<CountedRegion> CountedRegions;
234   /// \brief The number of times this function was executed.
235   uint64_t ExecutionCount;
236
237   FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
238                  uint64_t ExecutionCount)
239       : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
240         ExecutionCount(ExecutionCount) {}
241 };
242
243 /// \brief Coverage information for a macro expansion or #included file.
244 ///
245 /// When covered code has pieces that can be expanded for more detail, such as a
246 /// preprocessor macro use and its definition, these are represented as
247 /// expansions whose coverage can be looked up independently.
248 struct ExpansionRecord {
249   /// \brief The abstract file this expansion covers.
250   unsigned FileID;
251   /// \brief The region that expands to this record.
252   const CountedRegion &Region;
253   /// \brief Coverage for the expansion.
254   const FunctionRecord &Function;
255
256   ExpansionRecord(const CountedRegion &Region,
257                   const FunctionRecord &Function)
258       : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
259 };
260
261 /// \brief The execution count information starting at a point in a file.
262 ///
263 /// A sequence of CoverageSegments gives execution counts for a file in format
264 /// that's simple to iterate through for processing.
265 struct CoverageSegment {
266   /// \brief The line where this segment begins.
267   unsigned Line;
268   /// \brief The column where this segment begins.
269   unsigned Col;
270   /// \brief The execution count, or zero if no count was recorded.
271   uint64_t Count;
272   /// \brief When false, the segment was uninstrumented or skipped.
273   bool HasCount;
274   /// \brief Whether this enters a new region or returns to a previous count.
275   bool IsRegionEntry;
276
277   CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
278       : Line(Line), Col(Col), Count(0), HasCount(false),
279         IsRegionEntry(IsRegionEntry) {}
280   void setCount(uint64_t NewCount) {
281     Count = NewCount;
282     HasCount = true;
283   }
284   void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
285 };
286
287 /// \brief Coverage information to be processed or displayed.
288 ///
289 /// This represents the coverage of an entire file, expansion, or function. It
290 /// provides a sequence of CoverageSegments to iterate through, as well as the
291 /// list of expansions that can be further processed.
292 class CoverageData {
293   std::string Filename;
294   std::vector<CoverageSegment> Segments;
295   std::vector<ExpansionRecord> Expansions;
296   friend class CoverageMapping;
297
298 public:
299   CoverageData() {}
300
301   CoverageData(StringRef Filename) : Filename(Filename) {}
302
303   CoverageData(CoverageData &&RHS)
304       : Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)),
305         Expansions(std::move(RHS.Expansions)) {}
306
307   /// \brief Get the name of the file this data covers.
308   StringRef getFilename() { return Filename; }
309
310   std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
311   std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
312   bool empty() { return Segments.empty(); }
313
314   /// \brief Expansions that can be further processed.
315   std::vector<ExpansionRecord> getExpansions() { return Expansions; }
316 };
317
318 /// \brief The mapping of profile information to coverage data.
319 ///
320 /// This is the main interface to get coverage information, using a profile to
321 /// fill out execution counts.
322 class CoverageMapping {
323   std::vector<FunctionRecord> Functions;
324   unsigned MismatchedFunctionCount;
325
326   CoverageMapping() : MismatchedFunctionCount(0) {}
327
328 public:
329   /// \brief Load the coverage mapping using the given readers.
330   static ErrorOr<std::unique_ptr<CoverageMapping>>
331   load(ObjectFileCoverageMappingReader &CoverageReader,
332        IndexedInstrProfReader &ProfileReader);
333
334   /// \brief Load the coverage mapping from the given files.
335   static ErrorOr<std::unique_ptr<CoverageMapping>>
336   load(StringRef ObjectFilename, StringRef ProfileFilename);
337
338   /// \brief The number of functions that couldn't have their profiles mapped.
339   ///
340   /// This is a count of functions whose profile is out of date or otherwise
341   /// can't be associated with any coverage information.
342   unsigned getMismatchedCount() { return MismatchedFunctionCount; }
343
344   /// \brief Returns the list of files that are covered.
345   std::vector<StringRef> getUniqueSourceFiles();
346
347   /// \brief Get the coverage for a particular file.
348   ///
349   /// The given filename must be the name as recorded in the coverage
350   /// information. That is, only names returned from getUniqueSourceFiles will
351   /// yield a result.
352   CoverageData getCoverageForFile(StringRef Filename);
353
354   /// \brief Gets all of the functions covered by this profile.
355   ArrayRef<FunctionRecord> getCoveredFunctions() {
356     return ArrayRef<FunctionRecord>(Functions.data(), Functions.size());
357   }
358
359   /// \brief Get the list of function instantiations in the file.
360   ///
361   /// Fucntions that are instantiated more than once, such as C++ template
362   /// specializations, have distinct coverage records for each instantiation.
363   std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
364
365   /// \brief Get the coverage for a particular function.
366   CoverageData getCoverageForFunction(const FunctionRecord &Function);
367
368   /// \brief Get the coverage for an expansion within a coverage set.
369   CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
370 };
371
372 } // end namespace coverage
373 } // end namespace llvm
374
375 #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_