29 using namespace coverage;
31 #define DEBUG_TYPE "coverage-mapping"
34 auto It = ExpressionIndices.find(E);
35 if (It != ExpressionIndices.end())
37 unsigned I = Expressions.size();
38 Expressions.push_back(E);
39 ExpressionIndices[E] =
I;
43 void CounterExpressionBuilder::extractTerms(
53 extractTerms(E.LHS, Sign, Terms);
60 Counter CounterExpressionBuilder::simplify(
Counter ExpressionTree) {
63 extractTerms(ExpressionTree, +1, Terms);
67 if (Terms.
size() == 0)
71 std::sort(Terms.
begin(), Terms.
end(),
72 [](
const std::pair<unsigned, int> &LHS,
73 const std::pair<unsigned, int> &RHS) {
74 return LHS.first < RHS.first;
78 auto Prev = Terms.
begin();
79 for (
auto I = Prev + 1, E = Terms.
end();
I != E; ++
I) {
80 if (
I->first == Prev->first) {
81 Prev->second +=
I->second;
92 for (
auto Term : Terms) {
95 for (
int I = 0;
I < Term.second; ++
I)
104 for (
auto Term : Terms) {
105 if (Term.second >= 0)
107 for (
int I = 0;
I < -Term.second; ++
I)
144 if (CounterValues.
empty())
149 OS <<
'[' << *Value <<
']';
176 void FunctionRecordIterator::skipOtherFiles() {
177 while (Current != Records.end() && !Filename.
empty() &&
178 Filename != Current->Filenames[0])
180 if (Current == Records.end())
199 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
201 std::vector<uint64_t> Counts;
202 for (
const auto &
Record : CoverageReader) {
209 Coverage->MismatchedFunctionCount++;
213 Counts.assign(
Record.MappingRegions.size(), 0);
217 assert(!
Record.MappingRegions.empty() &&
"Function has no regions");
224 Function.pushRegion(
Region, *ExecutionCount);
226 if (Function.CountedRegions.size() !=
Record.MappingRegions.size()) {
227 Coverage->MismatchedFunctionCount++;
231 Coverage->Functions.push_back(std::move(Function));
234 return std::move(Coverage);
241 if (std::error_code EC = CounterMappingBuff.getError())
243 auto CoverageReaderOrErr =
245 if (std::error_code EC = CoverageReaderOrErr.getError())
247 auto CoverageReader = std::move(CoverageReaderOrErr.get());
249 if (
auto EC = ProfileReaderOrErr.getError())
251 auto ProfileReader = std::move(ProfileReaderOrErr.get());
252 return load(*CoverageReader, *ProfileReader);
260 class FunctionInstantiationSetCollector {
262 std::vector<const FunctionRecord *>> MapT;
263 MapT InstantiatedFunctions;
268 while (
I != E &&
I->FileID != FileID)
270 assert(
I != E &&
"function does not cover the given file");
271 auto &Functions = InstantiatedFunctions[
I->startLoc()];
272 Functions.push_back(&Function);
275 MapT::iterator
begin() {
return InstantiatedFunctions.
begin(); }
277 MapT::iterator
end() {
return InstantiatedFunctions.
end(); }
280 class SegmentBuilder {
281 std::vector<CoverageSegment>
Segments;
285 void startSegment(
unsigned Line,
unsigned Col) {
286 DEBUG(
dbgs() <<
"Top level segment at " << Line <<
":" << Col <<
"\n");
287 Segments.emplace_back(Line, Col,
false);
291 void startSegment(
unsigned Line,
unsigned Col,
bool IsRegionEntry,
294 Segments.emplace_back(Line, Col, IsRegionEntry);
297 if (S.
Line != Line || S.
Col != Col) {
298 Segments.emplace_back(Line, Col, IsRegionEntry);
301 DEBUG(
dbgs() <<
"Segment at " << Line <<
":" << Col);
320 ActiveRegions.pop_back();
321 if (ActiveRegions.empty())
322 startSegment(Line, Col);
324 startSegment(Line, Col,
false, *ActiveRegions.back());
331 for (
const auto &Region : Regions) {
333 while (!ActiveRegions.empty() &&
334 ActiveRegions.back()->endLoc() <= Region.
startLoc())
342 ActiveRegions.push_back(&Region);
343 startSegment(Region);
345 PrevRegion = &Region;
348 while (!ActiveRegions.empty())
356 std::vector<StringRef> Filenames;
358 Filenames.insert(Filenames.end(), Function.
Filenames.begin(),
360 std::sort(Filenames.begin(), Filenames.end());
361 auto Last = std::unique(Filenames.begin(), Filenames.end());
362 Filenames.erase(Last, Filenames.end());
369 for (
unsigned I = 0, E = Function.
Filenames.size();
I < E; ++
I)
371 FilenameEquivalence[
I] =
true;
372 return FilenameEquivalence;
381 FilenameEquivalence[CR.FileID])
382 IsNotExpandedFile[CR.ExpandedFileID] =
false;
383 IsNotExpandedFile &= FilenameEquivalence;
384 int I = IsNotExpandedFile.find_first();
394 IsNotExpandedFile[CR.ExpandedFileID] =
false;
395 int I = IsNotExpandedFile.find_first();
403 std::sort(First, Last,
418 std::vector<coverage::CountedRegion> Regions;
420 for (
const auto &Function : Functions) {
426 if (FileIDs.test(CR.FileID)) {
427 Regions.push_back(CR);
429 FileCoverage.Expansions.emplace_back(CR, Function);
434 DEBUG(
dbgs() <<
"Emitting segments for file: " << Filename <<
"\n");
435 FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
440 std::vector<const FunctionRecord *>
442 FunctionInstantiationSetCollector InstantiationSetCollector;
443 for (
const auto &Function : Functions) {
447 InstantiationSetCollector.insert(Function, *MainFileID);
450 std::vector<const FunctionRecord *> Result;
451 for (
const auto &InstantiationSet : InstantiationSetCollector) {
452 if (InstantiationSet.second.size() < 2)
454 Result.insert(Result.end(), InstantiationSet.second.begin(),
455 InstantiationSet.second.end());
467 std::vector<coverage::CountedRegion> Regions;
469 if (CR.FileID == *MainFileID) {
470 Regions.push_back(CR);
472 FunctionCoverage.Expansions.emplace_back(CR, Function);
476 DEBUG(
dbgs() <<
"Emitting segments for function: " << Function.
Name <<
"\n");
477 FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
479 return FunctionCoverage;
486 std::vector<coverage::CountedRegion> Regions;
488 if (CR.FileID == Expansion.
FileID) {
489 Regions.push_back(CR);
491 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.
Function);
495 DEBUG(
dbgs() <<
"Emitting segments for expansion of file " << Expansion.
FileID
497 ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
499 return ExpansionCoverage;
505 std::string message(
int IE)
const override {
511 return "End of File";
513 return "No coverage data found";
515 return "Unsupported coverage format version";
517 return "Truncated coverage data";
519 return "Malformed coverage data";
static void sortNestedRegions(It First, It Last)
Sort a nested sequence of regions from a single file.
const_iterator end(StringRef path)
Get end iterator over path.
Represents either an error or a value T.
const std::error_category & coveragemap_category()
SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array), optimized for the case w...
size_t size() const
size - Get the string size.
static Counter getZero()
Return the counter that represents the number zero.
void setCounts(ArrayRef< uint64_t > Counts)
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
std::vector< const FunctionRecord * > getInstantiations(StringRef Filename)
Get the list of function instantiations in the file.
const_iterator begin(StringRef path)
Get begin iterator over path.
static ErrorOr< std::unique_ptr< CoverageMapping > > load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader)
Load the coverage mapping using the given readers.
A Counter expression is a value that represents an arithmetic operation with two counters.
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion)
Get the coverage for an expansion within a coverage set.
ErrorOr< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed...
unsigned Col
The column where this segment begins.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
std::error_code make_error_code(BitcodeError E)
Coverage information to be processed or displayed.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Counter add(Counter LHS, Counter RHS)
Return a counter that represents the expression that adds LHS and RHS.
iterator_range< FunctionRecordIterator > getCoveredFunctions() const
Gets all of the functions covered by this profile.
size_t size() const
size - Get the array size.
unsigned getExpressionID() const
The execution count information starting at a point in a file.
StringRef filename(StringRef path)
Get filename.
std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
ArrayRef< StringRef > Filenames
friend const_iterator end(StringRef path)
Get end iterator over path.
Coverage mapping information for a single function.
void dump(const Counter &C, llvm::raw_ostream &OS) const
CounterKind getKind() const
A CodeRegion associates some code with a counter.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
unsigned getCounterID() const
static ErrorOr< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
static ManagedStatic< _object_error_category > error_category
static ManagedStatic< CoverageMappingErrorCategoryType > ErrorCategory
Associates a source range with an execution count.
bool empty() const
empty - Check if the array is empty.
std::pair< unsigned, unsigned > startLoc() const
iterator erase(iterator I)
Counter subtract(Counter LHS, Counter RHS)
Return a counter that represents the expression that subtracts RHS from LHS.
CoverageData getCoverageForFile(StringRef Filename)
Get the coverage for a particular file.
Code coverage information for a single function.
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, int64_t FileSize=-1)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
friend const_iterator begin(StringRef path)
Get begin iterator over path.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static bool isExpansion(const CountedRegion &R, unsigned FileID)
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
static Optional< unsigned > findMainViewFileID(StringRef SourceFile, const FunctionRecord &Function)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static StringRef getFuncNameWithoutPrefix(const CoverageMappingRecord &Record)
Get the function name from the record, removing the filename prefix if necessary. ...
The mapping of profile information to coverage data.
unsigned Line
The line where this segment begins.
CoverageData getCoverageForFunction(const FunctionRecord &Function)
Get the coverage for a particular function.
std::vector< CountedRegion > CountedRegions
Regions in the function along with their counts.
std::string Name
Raw function name.
unsigned FileID
The abstract file this expansion covers.
LLVM Value Representation.
std::vector< std::string > Filenames
Associated files.
std::pair< unsigned, unsigned > endLoc() const
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
Reader for the indexed binary instrprof format.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
std::vector< StringRef > getUniqueSourceFiles() const
Returns the list of files that are covered.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
const FunctionRecord & Function
Coverage for the expansion.
static ErrorOr< std::unique_ptr< IndexedInstrProfReader > > create(std::string Path)
Factory method to create an indexed reader.
bool empty() const
empty - Check if the string is empty.
Coverage information for a macro expansion or #included file.