38 #include <system_error>
43 using namespace coverage;
45 #define DEBUG_TYPE "coverage-mapping"
48 auto It = ExpressionIndices.find(
E);
49 if (It != ExpressionIndices.end())
51 unsigned I = Expressions.size();
52 Expressions.push_back(
E);
53 ExpressionIndices[
E] =
I;
57 void CounterExpressionBuilder::extractTerms(
Counter C,
int Factor,
59 switch (
C.getKind()) {
66 const auto &
E = Expressions[
C.getExpressionID()];
67 extractTerms(
E.LHS, Factor, Terms);
74 Counter CounterExpressionBuilder::simplify(
Counter ExpressionTree) {
77 extractTerms(ExpressionTree, +1, Terms);
81 if (Terms.size() == 0)
86 return LHS.CounterID <
RHS.CounterID;
90 auto Prev = Terms.begin();
91 for (
auto I = Prev + 1,
E = Terms.end();
I !=
E; ++
I) {
92 if (
I->CounterID == Prev->CounterID) {
93 Prev->Factor +=
I->Factor;
99 Terms.
erase(++Prev, Terms.end());
104 for (
auto T : Terms) {
107 for (
int I = 0;
I <
T.Factor; ++
I)
116 for (
auto T : Terms) {
119 for (
int I = 0;
I < -
T.Factor; ++
I)
136 switch (
C.getKind()) {
141 OS <<
'#' <<
C.getCounterID();
144 if (
C.getExpressionID() >= Expressions.size())
146 const auto &
E = Expressions[
C.getExpressionID()];
155 if (CounterValues.
empty())
158 if (
auto E =
Value.takeError()) {
162 OS <<
'[' << *
Value <<
']';
166 switch (
C.getKind()) {
170 if (
C.getCounterID() >= CounterValues.
size())
172 return CounterValues[
C.getCounterID()];
174 if (
C.getExpressionID() >= Expressions.size())
176 const auto &
E = Expressions[
C.getExpressionID()];
190 switch (
C.getKind()) {
194 return C.getCounterID();
196 if (
C.getExpressionID() >= Expressions.size())
198 const auto &
E = Expressions[
C.getExpressionID()];
205 void FunctionRecordIterator::skipOtherFiles() {
206 while (Current != Records.end() && !Filename.
empty() &&
207 Filename != Current->Filenames[0])
209 if (Current == Records.end())
216 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
217 if (RecordIt == FilenameHash2RecordIndices.end())
219 return RecordIt->second;
224 unsigned MaxCounterID = 0;
231 Error CoverageMapping::loadFunctionRecord(
235 if (OrigFuncName.
empty())
238 if (
Record.Filenames.empty())
245 std::vector<uint64_t> Counts;
247 Record.FunctionHash, Counts)) {
250 FuncHashMismatches.emplace_back(std::string(
Record.FunctionName),
254 return make_error<InstrProfError>(IPE);
257 Ctx.setCounts(Counts);
259 assert(!
Record.MappingRegions.empty() &&
"Function has no regions");
266 if (
Record.MappingRegions.size() == 1 &&
267 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
288 if (!RecordProvenance[FilenamesHash].insert(
hash_value(OrigFuncName)).second)
296 unsigned RecordIndex = Functions.size() - 1;
298 auto &RecordIndices = FilenameHash2RecordIndices[
hash_value(Filename)];
302 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
303 RecordIndices.push_back(RecordIndex);
311 Error CoverageMapping::loadFromReaders(
312 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
314 for (
const auto &CoverageReader : CoverageReaders) {
315 for (
auto RecordOrErr : *CoverageReader) {
316 if (
Error E = RecordOrErr.takeError())
318 const auto &
Record = *RecordOrErr;
319 if (
Error E = Coverage.loadFunctionRecord(
Record, ProfileReader))
327 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
329 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
330 if (
Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
341 return make_error<CoverageMapError>(CME.
get());
350 if (
Error E = ProfileReaderOrErr.takeError())
352 auto ProfileReader =
std::move(ProfileReaderOrErr.get());
353 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
354 bool DataFound =
false;
358 File.value(),
false,
false);
359 if (std::error_code EC = CovMappingBufOrErr.getError())
363 CovMappingBufOrErr.get()->getMemBufferRef();
366 CovMappingBufRef, Arch, Buffers, CompilationDir);
367 if (
Error E = CoverageReadersOrErr.takeError()) {
376 for (
auto &Reader : CoverageReadersOrErr.get())
378 DataFound |= !Readers.empty();
379 if (
Error E = loadFromReaders(Readers, *ProfileReader, *Coverage))
384 if (!DataFound && !ObjectFilenames.
empty())
395 class FunctionInstantiationSetCollector {
396 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
397 MapT InstantiatedFunctions;
402 while (
I !=
E &&
I->FileID != FileID)
404 assert(
I !=
E &&
"function does not cover the given file");
405 auto &Functions = InstantiatedFunctions[
I->startLoc()];
409 MapT::iterator
begin() {
return InstantiatedFunctions.
begin(); }
410 MapT::iterator
end() {
return InstantiatedFunctions.
end(); }
413 class SegmentBuilder {
414 std::vector<CoverageSegment> &
Segments;
417 SegmentBuilder(std::vector<CoverageSegment> &Segments) :
Segments(
Segments) {}
424 bool IsRegionEntry,
bool EmitSkippedRegion =
false) {
425 bool HasCount = !EmitSkippedRegion &&
429 if (!
Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
431 if (
Last.HasCount == HasCount &&
Last.Count ==
Region.ExecutionCount &&
437 Segments.emplace_back(StartLoc.first, StartLoc.second,
438 Region.ExecutionCount, IsRegionEntry,
441 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
446 <<
" (count = " <<
Last.Count <<
")"
447 << (
Last.IsRegionEntry ?
", RegionEntry" :
"")
448 << (!
Last.HasCount ?
", Skipped" :
"")
449 << (
Last.IsGapRegion ?
", Gap" :
"") <<
"\n";
459 unsigned FirstCompletedRegion) {
462 auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
465 return L->endLoc() < R->endLoc();
469 for (
unsigned I = FirstCompletedRegion + 1,
E = ActiveRegions.size();
I <
E;
471 const auto *CompletedRegion = ActiveRegions[
I];
472 assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
473 "Completed region ends after start of new region");
475 const auto *PrevCompletedRegion = ActiveRegions[
I - 1];
476 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
479 if (Loc && CompletedSegmentLoc == *Loc)
484 if (CompletedSegmentLoc == CompletedRegion->endLoc())
488 for (
unsigned J =
I + 1; J <
E; ++J)
489 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
490 CompletedRegion = ActiveRegions[J];
492 startSegment(*CompletedRegion, CompletedSegmentLoc,
false);
495 auto Last = ActiveRegions.back();
496 if (FirstCompletedRegion &&
Last->endLoc() != *Loc) {
499 startSegment(*ActiveRegions[FirstCompletedRegion - 1],
Last->endLoc(),
501 }
else if (!FirstCompletedRegion && (!Loc || *Loc !=
Last->endLoc())) {
504 startSegment(*Last,
Last->endLoc(),
false,
true);
508 ActiveRegions.
erase(CompletedRegionsIt, ActiveRegions.end());
512 for (
const auto &CR :
enumerate(Regions)) {
513 auto CurStartLoc = CR.value().startLoc();
516 auto CompletedRegions =
517 std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
519 return !(Region->endLoc() <= CurStartLoc);
521 if (CompletedRegions != ActiveRegions.end()) {
522 unsigned FirstCompletedRegion =
523 std::distance(ActiveRegions.begin(), CompletedRegions);
524 completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
530 if (CurStartLoc == CR.value().endLoc()) {
534 (CR.index() + 1) == Regions.
size() ||
536 startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
537 CurStartLoc, !GapRegion, Skipped);
540 if (Skipped && !ActiveRegions.empty())
541 startSegment(*ActiveRegions.back(), CurStartLoc,
false);
544 if (CR.index() + 1 == Regions.
size() ||
545 CurStartLoc != Regions[CR.index() + 1].startLoc()) {
548 startSegment(CR.value(), CurStartLoc, !GapRegion);
552 ActiveRegions.push_back(&CR.value());
556 if (!ActiveRegions.empty())
557 completeRegionsUntil(None, 0);
563 if (
LHS.startLoc() !=
RHS.startLoc())
564 return LHS.startLoc() <
RHS.startLoc();
567 return RHS.endLoc() <
LHS.endLoc();
577 "Unexpected order of region kind values");
578 return LHS.Kind <
RHS.Kind;
587 auto Active = Regions.
begin();
588 auto End = Regions.
end();
589 for (
auto I = Regions.
begin() + 1;
I != End; ++
I) {
590 if (Active->startLoc() !=
I->startLoc() ||
591 Active->endLoc() !=
I->endLoc()) {
610 if (
I->Kind == Active->Kind)
611 Active->ExecutionCount +=
I->ExecutionCount;
613 return Regions.
drop_back(std::distance(++Active, End));
618 static std::vector<CoverageSegment>
620 std::vector<CoverageSegment>
Segments;
621 SegmentBuilder
Builder(Segments);
623 sortNestedRegions(Regions);
627 dbgs() <<
"Combined regions:\n";
628 for (
const auto &CR : CombinedRegions)
629 dbgs() <<
" " << CR.LineStart <<
":" << CR.ColumnStart <<
" -> "
630 << CR.LineEnd <<
":" << CR.ColumnEnd
631 <<
" (count=" << CR.ExecutionCount <<
")\n";
634 Builder.buildSegmentsImpl(CombinedRegions);
640 if (!(L.Line <
R.Line) && !(L.Line ==
R.Line && L.Col <
R.Col)) {
641 if (L.Line ==
R.Line && L.Col ==
R.Col && !L.HasCount)
644 <<
" followed by " <<
R.Line <<
":" <<
R.Col <<
"\n");
645 assert(
false &&
"Coverage segments not unique or sorted");
657 std::vector<StringRef> Filenames;
661 auto Last =
std::unique(Filenames.begin(), Filenames.end());
662 Filenames.erase(Last, Filenames.end());
671 FilenameEquivalence[
I] =
true;
672 return FilenameEquivalence;
678 for (
const auto &CR :
Function.CountedRegions)
680 IsNotExpandedFile[CR.ExpandedFileID] =
false;
692 if (
I && SourceFile ==
Function.Filenames[*
I])
703 std::vector<CountedRegion> Regions;
708 getImpreciseRecordIndicesForFilename(Filename);
709 for (
unsigned RecordIndex : RecordIndices) {
713 for (
const auto &CR :
Function.CountedRegions)
714 if (FileIDs.test(CR.FileID)) {
715 Regions.push_back(CR);
717 FileCoverage.Expansions.emplace_back(CR,
Function);
720 for (
const auto &CR :
Function.CountedBranchRegions)
721 if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
722 FileCoverage.BranchRegions.push_back(CR);
725 LLVM_DEBUG(
dbgs() <<
"Emitting segments for file: " << Filename <<
"\n");
726 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
731 std::vector<InstantiationGroup>
733 FunctionInstantiationSetCollector InstantiationSetCollector;
737 getImpreciseRecordIndicesForFilename(Filename);
738 for (
unsigned RecordIndex : RecordIndices) {
743 InstantiationSetCollector.insert(
Function, *MainFileID);
746 std::vector<InstantiationGroup> Result;
747 for (
auto &InstantiationSet : InstantiationSetCollector) {
749 InstantiationSet.first.second,
763 std::vector<CountedRegion> Regions;
764 for (
const auto &CR :
Function.CountedRegions)
765 if (CR.FileID == *MainFileID) {
766 Regions.push_back(CR);
768 FunctionCoverage.Expansions.emplace_back(CR,
Function);
771 for (
const auto &CR :
Function.CountedBranchRegions)
772 if (CR.FileID == *MainFileID)
773 FunctionCoverage.BranchRegions.push_back(CR);
777 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
779 return FunctionCoverage;
786 std::vector<CountedRegion> Regions;
788 if (CR.FileID == Expansion.
FileID) {
789 Regions.push_back(CR);
791 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.
Function);
795 if (CR.FileID == Expansion.
FileID)
796 ExpansionCoverage.BranchRegions.push_back(CR);
799 << Expansion.
FileID <<
"\n");
800 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
802 return ExpansionCoverage;
805 LineCoverageStats::LineCoverageStats(
808 : ExecutionCount(0), HasMultipleRegions(
false), Mapped(
false), Line(Line),
809 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
811 unsigned MinRegionCount = 0;
813 return !
S->IsGapRegion &&
S->HasCount &&
S->IsRegionEntry;
815 for (
unsigned I = 0;
I < LineSegments.
size() && MinRegionCount < 2; ++
I)
816 if (isStartOfRegion(LineSegments[
I]))
819 bool StartOfSkippedRegion = !LineSegments.
empty() &&
823 HasMultipleRegions = MinRegionCount > 1;
825 !StartOfSkippedRegion &&
826 ((WrappedSegment && WrappedSegment->
HasCount) || (MinRegionCount > 0));
834 ExecutionCount = WrappedSegment->
Count;
837 for (
const auto *
LS : LineSegments)
838 if (isStartOfRegion(
LS))
839 ExecutionCount =
std::max(ExecutionCount,
LS->Count);
843 if (Next == CD.
end()) {
849 WrappedSegment = Segments.back();
851 while (Next != CD.
end() && Next->Line == Line)
852 Segments.push_back(&*Next++);
863 return "End of File";
865 return "No coverage data found";
867 return "Unsupported coverage format version";
869 return "Truncated coverage data";
871 return "Malformed coverage data";
873 return "Failed to decompress coverage data (zlib)";
875 return "`-arch` specifier is invalid or missing for universal binary";
886 const char *
name()
const noexcept
override {
return "llvm.coveragemap"; }
887 std::string
message(
int IE)
const override {