40#include <system_error>
45using namespace coverage;
47#define DEBUG_TYPE "coverage-mapping"
50 auto It = ExpressionIndices.find(
E);
51 if (It != ExpressionIndices.end())
53 unsigned I = Expressions.size();
54 Expressions.push_back(
E);
55 ExpressionIndices[
E] =
I;
59void CounterExpressionBuilder::extractTerms(
Counter C,
int Factor,
61 switch (
C.getKind()) {
68 const auto &
E = Expressions[
C.getExpressionID()];
69 extractTerms(
E.LHS, Factor, Terms);
76Counter CounterExpressionBuilder::simplify(
Counter ExpressionTree) {
79 extractTerms(ExpressionTree, +1, Terms);
83 if (Terms.
size() == 0)
87 llvm::sort(Terms, [](
const Term &LHS,
const Term &RHS) {
88 return LHS.CounterID <
RHS.CounterID;
92 auto Prev = Terms.
begin();
93 for (
auto I = Prev + 1,
E = Terms.
end();
I !=
E; ++
I) {
94 if (
I->CounterID == Prev->CounterID) {
95 Prev->Factor +=
I->Factor;
106 for (
auto T : Terms) {
109 for (
int I = 0;
I <
T.Factor; ++
I)
118 for (
auto T : Terms) {
121 for (
int I = 0;
I < -
T.Factor; ++
I)
140 switch (
C.getKind()) {
145 OS <<
'#' <<
C.getCounterID();
148 if (
C.getExpressionID() >= Expressions.size())
150 const auto &
E = Expressions[
C.getExpressionID()];
159 if (CounterValues.
empty())
162 if (
auto E =
Value.takeError()) {
170 switch (
C.getKind()) {
174 if (
C.getCounterID() >= CounterValues.
size())
176 return CounterValues[
C.getCounterID()];
178 if (
C.getExpressionID() >= Expressions.size())
180 const auto &
E = Expressions[
C.getExpressionID()];
194 switch (
C.getKind()) {
198 return C.getCounterID();
200 if (
C.getExpressionID() >= Expressions.size())
202 const auto &
E = Expressions[
C.getExpressionID()];
209void FunctionRecordIterator::skipOtherFiles() {
210 while (Current != Records.end() && !Filename.
empty() &&
211 Filename != Current->Filenames[0])
213 if (Current == Records.end())
220 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
221 if (RecordIt == FilenameHash2RecordIndices.end())
223 return RecordIt->second;
228 unsigned MaxCounterID = 0;
235Error CoverageMapping::loadFunctionRecord(
239 if (OrigFuncName.
empty())
242 if (
Record.Filenames.empty())
249 std::vector<uint64_t> Counts;
251 Record.FunctionHash, Counts)) {
254 FuncHashMismatches.emplace_back(std::string(
Record.FunctionName),
258 return make_error<InstrProfError>(IPE);
261 Ctx.setCounts(Counts);
263 assert(!
Record.MappingRegions.empty() &&
"Function has no regions");
270 if (
Record.MappingRegions.size() == 1 &&
271 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
292 if (!RecordProvenance[FilenamesHash].insert(
hash_value(OrigFuncName)).second)
295 Functions.push_back(std::move(
Function));
300 unsigned RecordIndex = Functions.size() - 1;
302 auto &RecordIndices = FilenameHash2RecordIndices[
hash_value(Filename)];
306 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
307 RecordIndices.push_back(RecordIndex);
315Error CoverageMapping::loadFromReaders(
316 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
318 for (
const auto &CoverageReader : CoverageReaders) {
319 for (
auto RecordOrErr : *CoverageReader) {
320 if (
Error E = RecordOrErr.takeError())
322 const auto &
Record = *RecordOrErr;
331 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
333 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
334 if (
Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
336 return std::move(Coverage);
345 return make_error<CoverageMapError>(CME.
get());
349Error CoverageMapping::loadFromFile(
354 Filename,
false,
false);
355 if (std::error_code EC = CovMappingBufOrErr.getError())
358 CovMappingBufOrErr.get()->getMemBufferRef();
363 CovMappingBufRef, Arch, Buffers, CompilationDir,
364 FoundBinaryIDs ? &BinaryIDs :
nullptr);
365 if (
Error E = CoverageReadersOrErr.takeError()) {
373 for (
auto &Reader : CoverageReadersOrErr.get())
375 if (FoundBinaryIDs && !Readers.
empty()) {
381 DataFound |= !Readers.
empty();
382 if (
Error E = loadFromReaders(Readers, ProfileReader, Coverage))
392 if (
Error E = ProfileReaderOrErr.takeError())
394 auto ProfileReader = std::move(ProfileReaderOrErr.get());
395 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
396 bool DataFound =
false;
398 auto GetArch = [&](
size_t Idx) {
401 if (Arches.
size() == 1)
402 return Arches.
front();
409 loadFromFile(File.value(), GetArch(File.index()), CompilationDir,
410 *ProfileReader, *Coverage, DataFound, &FoundBinaryIDs))
415 std::vector<object::BuildID> ProfileBinaryIDs;
420 if (!ProfileBinaryIDs.empty()) {
422 return std::lexicographical_compare(
A.begin(),
A.end(),
B.begin(),
427 ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(),
428 FoundBinaryIDs.
begin(), FoundBinaryIDs.
end(),
429 std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.
end()), Compare);
433 std::optional<std::string> PathOpt = BIDFetcher->
fetch(BinaryID);
435 std::string Path = std::move(*PathOpt);
437 if (
Error E = loadFromFile(Path, Arch, CompilationDir, *ProfileReader,
438 *Coverage, DataFound))
440 }
else if (CheckBinaryIDs) {
444 "Missing binary ID: " +
445 llvm::toHex(BinaryID,
true)));
452 join(ObjectFilenames.
begin(), ObjectFilenames.
end(),
", "),
454 return std::move(Coverage);
463class FunctionInstantiationSetCollector {
464 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
465 MapT InstantiatedFunctions;
470 while (
I !=
E &&
I->FileID != FileID)
472 assert(
I !=
E &&
"function does not cover the given file");
473 auto &Functions = InstantiatedFunctions[
I->startLoc()];
477 MapT::iterator begin() {
return InstantiatedFunctions.
begin(); }
478 MapT::iterator end() {
return InstantiatedFunctions.
end(); }
481class SegmentBuilder {
482 std::vector<CoverageSegment> &
Segments;
485 SegmentBuilder(std::vector<CoverageSegment> &Segments) :
Segments(
Segments) {}
492 bool IsRegionEntry,
bool EmitSkippedRegion =
false) {
493 bool HasCount = !EmitSkippedRegion &&
497 if (!
Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
499 if (
Last.HasCount == HasCount &&
Last.Count ==
Region.ExecutionCount &&
505 Segments.emplace_back(StartLoc.first, StartLoc.second,
506 Region.ExecutionCount, IsRegionEntry,
509 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
514 <<
" (count = " <<
Last.Count <<
")"
515 << (
Last.IsRegionEntry ?
", RegionEntry" :
"")
516 << (!
Last.HasCount ?
", Skipped" :
"")
517 << (
Last.IsGapRegion ?
", Gap" :
"") <<
"\n";
526 void completeRegionsUntil(std::optional<LineColPair> Loc,
527 unsigned FirstCompletedRegion) {
530 auto CompletedRegionsIt = ActiveRegions.
begin() + FirstCompletedRegion;
531 std::stable_sort(CompletedRegionsIt, ActiveRegions.
end(),
533 return L->endLoc() < R->endLoc();
537 for (
unsigned I = FirstCompletedRegion + 1,
E = ActiveRegions.
size();
I <
E;
539 const auto *CompletedRegion = ActiveRegions[
I];
540 assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
541 "Completed region ends after start of new region");
543 const auto *PrevCompletedRegion = ActiveRegions[
I - 1];
544 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
547 if (Loc && CompletedSegmentLoc == *Loc)
552 if (CompletedSegmentLoc == CompletedRegion->endLoc())
556 for (
unsigned J =
I + 1; J <
E; ++J)
557 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
558 CompletedRegion = ActiveRegions[J];
560 startSegment(*CompletedRegion, CompletedSegmentLoc,
false);
564 if (FirstCompletedRegion &&
Last->endLoc() != *Loc) {
567 startSegment(*ActiveRegions[FirstCompletedRegion - 1],
Last->endLoc(),
569 }
else if (!FirstCompletedRegion && (!Loc || *Loc !=
Last->endLoc())) {
572 startSegment(*
Last,
Last->endLoc(),
false,
true);
576 ActiveRegions.
erase(CompletedRegionsIt, ActiveRegions.
end());
580 for (
const auto &CR :
enumerate(Regions)) {
581 auto CurStartLoc = CR.value().startLoc();
584 auto CompletedRegions =
585 std::stable_partition(ActiveRegions.
begin(), ActiveRegions.
end(),
587 return !(Region->endLoc() <= CurStartLoc);
589 if (CompletedRegions != ActiveRegions.
end()) {
590 unsigned FirstCompletedRegion =
591 std::distance(ActiveRegions.
begin(), CompletedRegions);
592 completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
598 if (CurStartLoc == CR.value().endLoc()) {
602 (CR.index() + 1) == Regions.
size() ||
604 startSegment(ActiveRegions.
empty() ? CR.value() : *ActiveRegions.
back(),
605 CurStartLoc, !GapRegion, Skipped);
608 if (Skipped && !ActiveRegions.
empty())
609 startSegment(*ActiveRegions.
back(), CurStartLoc,
false);
612 if (CR.index() + 1 == Regions.
size() ||
613 CurStartLoc != Regions[CR.index() + 1].startLoc()) {
616 startSegment(CR.value(), CurStartLoc, !GapRegion);
624 if (!ActiveRegions.
empty())
625 completeRegionsUntil(std::nullopt, 0);
631 if (
LHS.startLoc() !=
RHS.startLoc())
632 return LHS.startLoc() <
RHS.startLoc();
635 return RHS.endLoc() <
LHS.endLoc();
645 "Unexpected order of region kind values");
646 return LHS.Kind <
RHS.Kind;
655 auto Active = Regions.
begin();
656 auto End = Regions.
end();
657 for (
auto I = Regions.
begin() + 1;
I != End; ++
I) {
658 if (Active->startLoc() !=
I->startLoc() ||
659 Active->endLoc() !=
I->endLoc()) {
678 if (
I->Kind == Active->Kind)
679 Active->ExecutionCount +=
I->ExecutionCount;
681 return Regions.
drop_back(std::distance(++Active, End));
686 static std::vector<CoverageSegment>
688 std::vector<CoverageSegment>
Segments;
689 SegmentBuilder
Builder(Segments);
691 sortNestedRegions(Regions);
695 dbgs() <<
"Combined regions:\n";
696 for (
const auto &CR : CombinedRegions)
697 dbgs() <<
" " << CR.LineStart <<
":" << CR.ColumnStart <<
" -> "
698 << CR.LineEnd <<
":" << CR.ColumnEnd
699 <<
" (count=" << CR.ExecutionCount <<
")\n";
702 Builder.buildSegmentsImpl(CombinedRegions);
708 if (!(
L.Line <
R.Line) && !(
L.Line ==
R.Line &&
L.Col <
R.Col)) {
709 if (
L.Line ==
R.Line &&
L.Col ==
R.Col && !
L.HasCount)
712 <<
" followed by " <<
R.Line <<
":" <<
R.Col <<
"\n");
713 assert(
false &&
"Coverage segments not unique or sorted");
725 std::vector<StringRef> Filenames;
729 auto Last = std::unique(Filenames.begin(), Filenames.end());
730 Filenames.erase(
Last, Filenames.end());
739 FilenameEquivalence[
I] =
true;
740 return FilenameEquivalence;
744static std::optional<unsigned>
747 for (
const auto &CR :
Function.CountedRegions)
749 IsNotExpandedFile[CR.ExpandedFileID] =
false;
759static std::optional<unsigned>
762 if (
I && SourceFile ==
Function.Filenames[*
I])
773 std::vector<CountedRegion> Regions;
778 getImpreciseRecordIndicesForFilename(Filename);
779 for (
unsigned RecordIndex : RecordIndices) {
783 for (
const auto &CR :
Function.CountedRegions)
784 if (FileIDs.test(CR.FileID)) {
785 Regions.push_back(CR);
787 FileCoverage.Expansions.emplace_back(CR,
Function);
790 for (
const auto &CR :
Function.CountedBranchRegions)
791 if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
792 FileCoverage.BranchRegions.push_back(CR);
795 LLVM_DEBUG(
dbgs() <<
"Emitting segments for file: " << Filename <<
"\n");
796 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
801std::vector<InstantiationGroup>
803 FunctionInstantiationSetCollector InstantiationSetCollector;
807 getImpreciseRecordIndicesForFilename(Filename);
808 for (
unsigned RecordIndex : RecordIndices) {
813 InstantiationSetCollector.insert(
Function, *MainFileID);
816 std::vector<InstantiationGroup> Result;
817 for (
auto &InstantiationSet : InstantiationSetCollector) {
819 InstantiationSet.first.second,
820 std::move(InstantiationSet.second)};
821 Result.emplace_back(std::move(IG));
833 std::vector<CountedRegion> Regions;
834 for (
const auto &CR :
Function.CountedRegions)
835 if (CR.FileID == *MainFileID) {
836 Regions.push_back(CR);
838 FunctionCoverage.Expansions.emplace_back(CR,
Function);
841 for (
const auto &CR :
Function.CountedBranchRegions)
842 if (CR.FileID == *MainFileID)
843 FunctionCoverage.BranchRegions.push_back(CR);
847 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
849 return FunctionCoverage;
856 std::vector<CountedRegion> Regions;
858 if (CR.FileID == Expansion.
FileID) {
859 Regions.push_back(CR);
861 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.
Function);
865 if (CR.FileID == Expansion.
FileID)
866 ExpansionCoverage.BranchRegions.push_back(CR);
869 << Expansion.
FileID <<
"\n");
870 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
872 return ExpansionCoverage;
875LineCoverageStats::LineCoverageStats(
878 : ExecutionCount(0), HasMultipleRegions(
false), Mapped(
false), Line(Line),
879 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
881 unsigned MinRegionCount = 0;
883 return !S->
IsGapRegion && S->HasCount && S->IsRegionEntry;
885 for (
unsigned I = 0;
I < LineSegments.
size() && MinRegionCount < 2; ++
I)
886 if (isStartOfRegion(LineSegments[
I]))
889 bool StartOfSkippedRegion = !LineSegments.
empty() &&
890 !LineSegments.
front()->HasCount &&
891 LineSegments.
front()->IsRegionEntry;
893 HasMultipleRegions = MinRegionCount > 1;
895 !StartOfSkippedRegion &&
896 ((WrappedSegment && WrappedSegment->
HasCount) || (MinRegionCount > 0));
904 ExecutionCount = WrappedSegment->
Count;
907 for (
const auto *LS : LineSegments)
908 if (isStartOfRegion(LS))
909 ExecutionCount = std::max(ExecutionCount, LS->Count);
913 if (Next == CD.
end()) {
919 WrappedSegment = Segments.back();
921 while (Next != CD.
end() && Next->Line == Line)
922 Segments.push_back(&*Next++);
933 return "End of File";
935 return "No coverage data found";
937 return "Unsupported coverage format version";
939 return "Truncated coverage data";
941 return "Malformed coverage data";
943 return "Failed to decompress coverage data (zlib)";
945 return "`-arch` specifier is invalid or missing for universal binary";
955class CoverageMappingErrorCategoryType :
public std::error_category {
956 const char *
name()
const noexcept
override {
return "llvm.coveragemap"; }
957 std::string message(
int IE)
const override {
969 static CoverageMappingErrorCategoryType ErrorCategory;
970 return ErrorCategory;
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
static std::optional< unsigned > findMainViewFileID(const FunctionRecord &Function)
Return the ID of the file where the definition of the function is located.
static bool isExpansion(const CountedRegion &R, unsigned FileID)
static std::string getCoverageMapErrString(coveragemap_error Err)
static Error handleMaybeNoDataFoundError(Error E)
static unsigned getMaxCounterID(const CounterMappingContext &Ctx, const CoverageMappingRecord &Record)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
This file defines the SmallString class.
This file defines the SmallVector class.
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
Reader for the indexed binary instrprof format.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Error readBinaryIds(std::vector< llvm::object::BuildID > &BinaryIds) override
Read a list of binary ids.
static instrprof_error take(Error E)
Consume an Error and return the raw enum value contained within it.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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 ...
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
LLVM Value Representation.
static Expected< std::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)
Counter subtract(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that subtracts RHS from LHS.
Counter add(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that adds LHS and RHS.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
Expected< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed.
unsigned getMaxCounterID(const Counter &C) const
void dump(const Counter &C, raw_ostream &OS) const
Coverage information to be processed or displayed.
std::vector< CoverageSegment >::const_iterator end() const
std::string message() const override
Return the error message as a string.
coveragemap_error get() const
The mapping of profile information to coverage data.
std::vector< StringRef > getUniqueSourceFiles() const
Returns a lexicographically sorted, unique list of files that are covered.
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const
Get the coverage for an expansion within a coverage set.
iterator_range< FunctionRecordIterator > getCoveredFunctions() const
Gets all of the functions covered by this profile.
CoverageData getCoverageForFunction(const FunctionRecord &Function) const
Get the coverage for a particular function.
std::vector< InstantiationGroup > getInstantiationGroups(StringRef Filename) const
Get the list of function instantiation groups in a particular file.
CoverageData getCoverageForFile(StringRef Filename) const
Get the coverage for a particular file.
static Expected< std::unique_ptr< CoverageMapping > > load(ArrayRef< std::unique_ptr< CoverageMappingReader > > CoverageReaders, IndexedInstrProfReader &ProfileReader)
Load the coverage mapping using the given readers.
An instantiation group contains a FunctionRecord list, such that each record corresponds to a distinc...
An iterator over the LineCoverageStats objects for lines described by a CoverageData instance.
LineCoverageIterator & operator++()
Coverage statistics for a single line.
BuildIDFetcher searches local cache directories for debug info.
virtual std::optional< std::string > fetch(BuildIDRef BuildID) const
Returns the path to the debug file with the given build ID.
This class implements an extremely fast bulk output stream that can only output to a stream.
friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
friend const_iterator end(StringRef path)
Get end iterator over path.
The virtual file system interface.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
const std::error_category & coveragemap_category()
@ invalid_or_missing_arch_specifier
std::pair< unsigned, unsigned > LineColPair
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
This is an optimization pass for GlobalISel generic memory operations.
hash_code hash_value(const FixedPointSemantics &Val)
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName="<unknown>")
Given a PGO function name, remove the filename prefix and return the original (static) function name.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto map_range(ContainerTy &&C, FuncTy F)
@ no_such_file_or_directory
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Associates a source range with an execution count.
A Counter expression is a value that represents an arithmetic operation with two counters.
@ ExpansionRegion
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
@ SkippedRegion
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
@ GapRegion
A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...
@ CodeRegion
A CodeRegion associates some code with a counter.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getZero()
Return the counter that represents the number zero.
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
Coverage mapping information for a single function.
The execution count information starting at a point in a file.
bool HasCount
When false, the segment was uninstrumented or skipped.
uint64_t Count
The execution count, or zero if no count was recorded.
bool IsGapRegion
Whether this enters a gap region.
Coverage information for a macro expansion or #included file.
unsigned FileID
The abstract file this expansion covers.
const FunctionRecord & Function
Coverage for the expansion.
Code coverage information for a single function.
std::vector< CountedRegion > CountedBranchRegions
Branch Regions in the function along with their counts.
std::vector< CountedRegion > CountedRegions
Regions in the function along with their counts.
std::vector< std::string > Filenames
Mapping from FileID (i.e.