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())
151 OS <<
'[' << *Value <<
']';
178 void FunctionRecordIterator::skipOtherFiles() {
179 while (Current != Records.end() && !Filename.
empty() &&
180 Filename != Current->Filenames[0])
182 if (Current == Records.end())
186 Error CoverageMapping::loadFunctionRecord(
196 if (!FunctionNames.
insert(OrigFuncName).second)
201 std::vector<uint64_t> Counts;
206 MismatchedFunctionCount++;
209 return make_error<InstrProfError>(IPE);
212 Ctx.setCounts(Counts);
226 MismatchedFunctionCount++;
230 Functions.push_back(std::move(
Function));
237 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
239 for (
const auto &Record : CoverageReader)
240 if (
Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
243 return std::move(Coverage);
247 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
249 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
251 for (
const auto &CoverageReader : CoverageReaders)
252 for (
const auto &Record : *CoverageReader)
253 if (
Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
256 return std::move(Coverage);
263 if (
Error E = ProfileReaderOrErr.takeError())
265 auto ProfileReader = std::move(ProfileReaderOrErr.get());
269 for (
StringRef ObjectFilename : ObjectFilenames) {
271 if (std::error_code EC = CovMappingBufOrErr.getError())
273 auto CoverageReaderOrErr =
275 if (
Error E = CoverageReaderOrErr.takeError())
277 Readers.push_back(std::move(CoverageReaderOrErr.get()));
278 Buffers.
push_back(std::move(CovMappingBufOrErr.get()));
280 return load(Readers, *ProfileReader);
288 class FunctionInstantiationSetCollector {
290 std::vector<const FunctionRecord *>> MapT;
291 MapT InstantiatedFunctions;
296 while (
I !=
E &&
I->FileID != FileID)
298 assert(
I !=
E &&
"function does not cover the given file");
299 auto &Functions = InstantiatedFunctions[
I->startLoc()];
300 Functions.push_back(&Function);
303 MapT::iterator
begin() {
return InstantiatedFunctions.
begin(); }
305 MapT::iterator
end() {
return InstantiatedFunctions.
end(); }
308 class SegmentBuilder {
309 std::vector<CoverageSegment> &
Segments;
312 SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
315 void startSegment(
unsigned Line,
unsigned Col) {
316 DEBUG(
dbgs() <<
"Top level segment at " << Line <<
":" << Col <<
"\n");
317 Segments.emplace_back(Line, Col,
false);
321 void startSegment(
unsigned Line,
unsigned Col,
bool IsRegionEntry,
327 DEBUG(
dbgs() <<
"Segment at " << Line <<
":" << Col);
333 Segments.emplace_back(Line, Col, IsRegionEntry);
347 ActiveRegions.pop_back();
348 if (ActiveRegions.empty())
349 startSegment(Line, Col);
351 startSegment(Line, Col,
false, *ActiveRegions.back());
355 for (
const auto &Region : Regions) {
357 while (!ActiveRegions.empty() &&
358 ActiveRegions.back()->endLoc() <= Region.
startLoc())
361 ActiveRegions.push_back(&Region);
362 startSegment(Region);
365 while (!ActiveRegions.empty())
373 if (LHS.
startLoc() != RHS.startLoc())
374 return LHS.
startLoc() < RHS.startLoc();
375 if (LHS.
endLoc() != RHS.endLoc())
377 return RHS.endLoc() < LHS.
endLoc();
387 "Unexpected order of region kind values");
388 return LHS.
Kind < RHS.Kind;
397 auto Active = Regions.
begin();
399 for (
auto I = Regions.
begin() + 1;
I !=
End; ++
I) {
400 if (Active->
startLoc() !=
I->startLoc() ||
401 Active->
endLoc() !=
I->endLoc()) {
420 if (
I->Kind == Active->
Kind)
428 static std::vector<CoverageSegment>
430 std::vector<CoverageSegment>
Segments;
431 SegmentBuilder Builder(Segments);
433 sortNestedRegions(Regions);
436 Builder.buildSegmentsImpl(CombinedRegions);
443 std::vector<StringRef> Filenames;
445 Filenames.insert(Filenames.end(), Function.
Filenames.begin(),
447 std::sort(Filenames.begin(), Filenames.end());
448 auto Last = std::unique(Filenames.begin(), Filenames.end());
449 Filenames.erase(Last, Filenames.end());
458 FilenameEquivalence[
I] =
true;
459 return FilenameEquivalence;
467 IsNotExpandedFile[CR.ExpandedFileID] =
false;
468 int I = IsNotExpandedFile.find_first();
479 if (I && SourceFile == Function.
Filenames[*I])
490 std::vector<coverage::CountedRegion> Regions;
492 for (
const auto &Function : Functions) {
496 if (FileIDs.test(CR.FileID)) {
497 Regions.push_back(CR);
499 FileCoverage.Expansions.emplace_back(CR, Function);
503 DEBUG(
dbgs() <<
"Emitting segments for file: " << Filename <<
"\n");
504 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
509 std::vector<const FunctionRecord *>
511 FunctionInstantiationSetCollector InstantiationSetCollector;
512 for (
const auto &Function : Functions) {
516 InstantiationSetCollector.insert(Function, *MainFileID);
519 std::vector<const FunctionRecord *> Result;
520 for (
const auto &InstantiationSet : InstantiationSetCollector) {
521 if (InstantiationSet.second.size() < 2)
523 Result.insert(Result.end(), InstantiationSet.second.begin(),
524 InstantiationSet.second.end());
536 std::vector<coverage::CountedRegion> Regions;
538 if (CR.FileID == *MainFileID) {
539 Regions.push_back(CR);
541 FunctionCoverage.Expansions.emplace_back(CR, Function);
544 DEBUG(
dbgs() <<
"Emitting segments for function: " << Function.
Name <<
"\n");
545 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
547 return FunctionCoverage;
554 std::vector<coverage::CountedRegion> Regions;
556 if (CR.FileID == Expansion.
FileID) {
557 Regions.push_back(CR);
559 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.
Function);
562 DEBUG(
dbgs() <<
"Emitting segments for expansion of file " << Expansion.
FileID
564 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
566 return ExpansionCoverage;
575 return "End of File";
577 return "No coverage data found";
579 return "Unsupported coverage format version";
581 return "Truncated coverage data";
583 return "Malformed coverage data";
592 const char *
name()
const noexcept
override {
return "llvm.coveragemap"; }
593 std::string message(
int IE)
const override {
594 return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
600 return getCoverageMapErrString(Err);
void push_back(const T &Elt)
const_iterator end(StringRef path)
Get end iterator over path.
MutableArrayRef< T > drop_back(size_t N=1) const
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
static Counter getZero()
Return the counter that represents the number zero.
std::vector< const FunctionRecord * > getInstantiations(StringRef Filename) const
Get the list of function instantiations in the file.
Expected< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed...
static instrprof_error take(Error E)
Consume an Error and return the raw enum value contained within it.
CoverageData getCoverageForFunction(const FunctionRecord &Function) const
Get the coverage for a particular function.
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
const_iterator begin(StringRef path)
Get begin iterator over path.
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const
Get the coverage for an expansion within a coverage set.
A Counter expression is a value that represents an arithmetic operation with two counters.
Error takeError()
Take ownership of the stored error.
ArrayRef< CounterMappingRegion > MappingRegions
static Expected< std::unique_ptr< CoverageMapping > > load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader)
Load the coverage mapping using the given readers.
ArrayRef< CounterExpression > Expressions
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Tagged union holding either a T or a Error.
StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName="<unknown>")
Given a PGO function name, remove the filename prefix and return the original (static) function name...
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const std::error_category & coveragemap_category()
unsigned getExpressionID() const
ArrayRef< StringRef > Filenames
friend const_iterator end(StringRef path)
Get end iterator over path.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Coverage mapping information for a single function.
void dump(const Counter &C, llvm::raw_ostream &OS) const
CounterKind getKind() const
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
CoverageData getCoverageForFile(StringRef Filename) const
Get the coverage for a particular file.
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 ManagedStatic< _object_error_category > error_category
static const unsigned End
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(const_iterator CI)
void consumeError(Error Err)
Consume a Error without doing anything.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< typename base::iterator, bool > insert(StringRef Key)
Counter subtract(Counter LHS, Counter RHS)
Return a counter that represents the expression that subtracts RHS from LHS.
Code coverage information for a single function.
static ErrorSuccess success()
Create a success value.
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)
static Expected< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
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 GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
The mapping of profile information to coverage data.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
std::string message() const override
Return the error message as a string.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
static Optional< unsigned > findMainViewFileID(const FunctionRecord &Function)
Return the ID of the file where the definition of the function is located.
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
std::vector< std::string > Filenames
Associated files.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path)
Factory method to create an indexed reader.
Lightweight error class with error context and mandatory checking.
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 a lexicographically sorted, unique 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.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Coverage information for a macro expansion or #included file.