Skip to content

Commit a20a5d5

Browse files
committed
Add code coverage mapping data, reader, and writer.
This patch implements the data structures, the reader and the writers for the new code coverage mapping system. The new code coverage mapping system uses the instrumentation based profiling to provide code coverage analysis. llvm-svn: 213910
1 parent 817e485 commit a20a5d5

File tree

6 files changed

+1296
-0
lines changed

6 files changed

+1296
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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/raw_ostream.h"
20+
#include <system_error>
21+
22+
namespace llvm {
23+
namespace coverage {
24+
25+
struct CounterExpressions;
26+
27+
enum CoverageMappingVersion { CoverageMappingVersion1 };
28+
29+
/// \brief A Counter is an abstract value that describes how to compute the
30+
/// execution count for a region of code using the collected profile count data.
31+
struct Counter {
32+
enum CounterKind { Zero, CounterValueReference, Expression };
33+
static const unsigned EncodingTagBits = 2;
34+
static const unsigned EncodingTagMask = 0x3;
35+
static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
36+
EncodingTagBits + 1;
37+
38+
private:
39+
CounterKind Kind;
40+
unsigned ID;
41+
42+
Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
43+
44+
public:
45+
Counter() : Kind(Zero), ID(0) {}
46+
47+
CounterKind getKind() const { return Kind; }
48+
49+
bool isZero() const { return Kind == Zero; }
50+
51+
bool isExpression() const { return Kind == Expression; }
52+
53+
unsigned getCounterID() const { return ID; }
54+
55+
unsigned getExpressionID() const { return ID; }
56+
57+
bool operator==(const Counter &Other) const {
58+
return Kind == Other.Kind && ID == Other.ID;
59+
}
60+
61+
/// \brief Return the counter that represents the number zero.
62+
static Counter getZero() { return Counter(); }
63+
64+
/// \brief Return the counter that corresponds to a specific profile counter.
65+
static Counter getCounter(unsigned CounterId) {
66+
return Counter(CounterValueReference, CounterId);
67+
}
68+
69+
/// \brief Return the counter that corresponds to a specific
70+
/// addition counter expression.
71+
static Counter getExpression(unsigned ExpressionId) {
72+
return Counter(Expression, ExpressionId);
73+
}
74+
};
75+
76+
/// \brief A Counter expression is a value that represents an arithmetic
77+
/// operation with two counters.
78+
struct CounterExpression {
79+
enum ExprKind { Subtract, Add };
80+
ExprKind Kind;
81+
Counter LHS, RHS;
82+
83+
CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
84+
: Kind(Kind), LHS(LHS), RHS(RHS) {}
85+
86+
bool operator==(const CounterExpression &Other) const {
87+
return Kind == Other.Kind && LHS == Other.LHS && RHS == Other.RHS;
88+
}
89+
};
90+
91+
/// \brief A Counter expression builder is used to construct the
92+
/// counter expressions. It avoids unecessary duplication
93+
/// and simplifies algebraic expressions.
94+
class CounterExpressionBuilder {
95+
/// \brief A list of all the counter expressions
96+
llvm::SmallVector<CounterExpression, 16> Expressions;
97+
/// \brief An array of terms used in expression simplification.
98+
llvm::SmallVector<int, 16> Terms;
99+
100+
/// \brief Return the counter which corresponds to the given expression.
101+
///
102+
/// If the given expression is already stored in the builder, a counter
103+
/// that references that expression is returned. Otherwise, the given
104+
/// expression is added to the builder's collection of expressions.
105+
Counter get(const CounterExpression &E);
106+
107+
/// \brief Convert the expression tree represented by a counter
108+
/// into a polynomial in the form of K1Counter1 + .. + KNCounterN
109+
/// where K1 .. KN are integer constants that are stored in the Terms array.
110+
void extractTerms(Counter C, int Sign = 1);
111+
112+
/// \brief Simplifies the given expression tree
113+
/// by getting rid of algebraically redundant operations.
114+
Counter simplify(Counter ExpressionTree);
115+
116+
public:
117+
CounterExpressionBuilder(unsigned NumCounterValues);
118+
119+
ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
120+
121+
/// \brief Return a counter that represents the expression
122+
/// that adds LHS and RHS.
123+
Counter add(Counter LHS, Counter RHS);
124+
125+
/// \brief Return a counter that represents the expression
126+
/// that subtracts RHS from LHS.
127+
Counter subtract(Counter LHS, Counter RHS);
128+
};
129+
130+
/// \brief A Counter mapping region associates a source range with
131+
/// a specific counter.
132+
struct CounterMappingRegion {
133+
enum RegionKind {
134+
/// \brief A CodeRegion associates some code with a counter
135+
CodeRegion,
136+
137+
/// \brief An ExpansionRegion represents a file expansion region that
138+
/// associates a source range with the expansion of a virtual source file,
139+
/// such as for a macro instantiation or #include file.
140+
ExpansionRegion,
141+
142+
/// \brief An EmptyRegion represents a source range without code,
143+
/// but with a distinct counter.
144+
EmptyRegion,
145+
146+
/// \brief A SkippedRegion represents a source range with code that
147+
/// was skipped by a preprocessor or similar means.
148+
SkippedRegion
149+
};
150+
151+
Counter Count;
152+
unsigned FileID, ExpandedFileID;
153+
unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
154+
RegionKind Kind;
155+
156+
CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart,
157+
unsigned ColumnStart, unsigned LineEnd,
158+
unsigned ColumnEnd, RegionKind Kind = CodeRegion)
159+
: Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart),
160+
ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
161+
Kind(Kind) {}
162+
163+
bool operator<(const CounterMappingRegion &Other) const {
164+
if (FileID != Other.FileID)
165+
return FileID < Other.FileID;
166+
if (LineStart == Other.LineStart)
167+
return ColumnStart < Other.ColumnStart;
168+
return LineStart < Other.LineStart;
169+
}
170+
};
171+
172+
/// \brief A Counter mapping context is used to connect the counters,
173+
/// expressions and the obtained counter values.
174+
class CounterMappingContext {
175+
ArrayRef<CounterExpression> Expressions;
176+
ArrayRef<uint64_t> CounterValues;
177+
178+
public:
179+
CounterMappingContext(ArrayRef<CounterExpression> Expressions,
180+
ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>())
181+
: Expressions(Expressions), CounterValues(CounterValues) {}
182+
183+
void dump(const Counter &C, llvm::raw_ostream &OS) const;
184+
void dump(const Counter &C) const { dump(C, llvm::outs()); }
185+
186+
/// \brief Return the number of times that a region of code
187+
/// associated with this counter was executed.
188+
int64_t evaluate(const Counter &C, std::error_code *Error) const;
189+
int64_t evaluate(const Counter &C, std::error_code &Error) const {
190+
Error.clear();
191+
return evaluate(C, &Error);
192+
}
193+
};
194+
195+
} // end namespace coverage
196+
} // end namespace llvm
197+
198+
#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_

0 commit comments

Comments
 (0)