41#include <system_error>
46using namespace coverage;
48#define DEBUG_TYPE "coverage-mapping"
51 auto It = ExpressionIndices.find(
E);
52 if (It != ExpressionIndices.end())
54 unsigned I = Expressions.size();
55 Expressions.push_back(
E);
56 ExpressionIndices[
E] =
I;
60void CounterExpressionBuilder::extractTerms(
Counter C,
int Factor,
62 switch (
C.getKind()) {
69 const auto &
E = Expressions[
C.getExpressionID()];
70 extractTerms(
E.LHS, Factor, Terms);
77Counter CounterExpressionBuilder::simplify(
Counter ExpressionTree) {
80 extractTerms(ExpressionTree, +1, Terms);
84 if (Terms.
size() == 0)
88 llvm::sort(Terms, [](
const Term &LHS,
const Term &RHS) {
89 return LHS.CounterID <
RHS.CounterID;
93 auto Prev = Terms.
begin();
94 for (
auto I = Prev + 1,
E = Terms.
end();
I !=
E; ++
I) {
95 if (
I->CounterID == Prev->CounterID) {
96 Prev->Factor +=
I->Factor;
107 for (
auto T : Terms) {
110 for (
int I = 0;
I <
T.Factor; ++
I)
119 for (
auto T : Terms) {
122 for (
int I = 0;
I < -
T.Factor; ++
I)
131 return Simplify ?
simplify(Cnt) : Cnt;
137 return Simplify ?
simplify(Cnt) : Cnt;
141 switch (
C.getKind()) {
146 OS <<
'#' <<
C.getCounterID();
149 if (
C.getExpressionID() >= Expressions.size())
151 const auto &
E = Expressions[
C.getExpressionID()];
160 if (CounterValues.
empty())
163 if (
auto E =
Value.takeError()) {
171 switch (
C.getKind()) {
175 if (
C.getCounterID() >= CounterValues.
size())
177 return CounterValues[
C.getCounterID()];
179 if (
C.getExpressionID() >= Expressions.size())
181 const auto &
E = Expressions[
C.getExpressionID()];
199 unsigned SizeInBytes = SizeInBits / CHAR_BIT;
206 for (
auto Byte = std::rbegin(Bytes); Byte != std::rend(Bytes); ++Byte) {
209 Result.setBitsInMask(&
Data, 1);
229 unsigned NumConditions;
250 : ExecutedTestVectorBitmap(Bitmap),
Region(
Region), Branches(Branches),
251 NumConditions(
Region.MCDCParams.NumConditions),
252 Folded(NumConditions,
false), IndependencePairs(NumConditions),
253 TestVectors(pow(2, NumConditions)) {}
262 for (
auto Cond = std::rbegin(TV);
Cond != std::rend(TV); ++
Cond) {
268 TestVectors[
Index] = TV;
281 if (
Branch->MCDCParams.TrueID > 0)
282 buildTestVector(TV,
Branch->MCDCParams.TrueID);
293 if (
Branch->MCDCParams.FalseID > 0)
294 buildTestVector(TV,
Branch->MCDCParams.FalseID);
300 shouldCopyOffTestVectorForTruePath(TV,
ID);
301 shouldCopyOffTestVectorForFalsePath(TV,
ID);
307 void findExecutedTestVectors(
BitVector &ExecutedTestVectorBitmap) {
310 for (
unsigned Idx = 0;
Idx < ExecutedTestVectorBitmap.
size();
Idx++) {
311 if (ExecutedTestVectorBitmap[
Idx] == 0)
313 assert(!TestVectors[
Idx].empty() &&
"Test Vector doesn't exist.");
324 bool matchTestVectors(
unsigned Aidx,
unsigned Bidx,
unsigned ConditionIdx) {
329 if (!((
A[ConditionIdx] ^
B[ConditionIdx]) == 1))
333 if (!((
A[NumConditions] ^
B[NumConditions]) == 1))
336 for (
unsigned Idx = 0;
Idx < NumConditions;
Idx++) {
339 const auto ARecordTyForCond =
A[
Idx];
340 const auto BRecordTyForCond =
B[
Idx];
341 if (
Idx == ConditionIdx ||
348 if (ARecordTyForCond != BRecordTyForCond)
359 void findIndependencePairs() {
360 unsigned NumTVs = ExecVectors.
size();
363 for (
unsigned C = 0;
C < NumConditions;
C++) {
364 bool PairFound =
false;
367 for (
unsigned I = 0; !PairFound &&
I < NumTVs;
I++) {
370 for (
unsigned J = 0; !PairFound && J < NumTVs; J++) {
375 if ((PairFound = matchTestVectors(
I, J,
C)))
376 IndependencePairs[
C] = std::make_pair(
I + 1, J + 1);
407 for (
const auto &
B : Branches) {
408 Map[
B.MCDCParams.ID] = &
B;
409 PosToID[
I] =
B.MCDCParams.ID - 1;
410 CondLoc[
I] =
B.startLoc();
411 Folded[
I++] = (
B.Count.isZero() &&
B.FalseCount.isZero());
421 findExecutedTestVectors(ExecutedTestVectorBitmap);
425 findIndependencePairs();
443 switch (
C.getKind()) {
447 return C.getCounterID();
449 if (
C.getExpressionID() >= Expressions.size())
451 const auto &
E = Expressions[
C.getExpressionID()];
458void FunctionRecordIterator::skipOtherFiles() {
459 while (Current != Records.end() && !Filename.
empty() &&
460 Filename != Current->Filenames[0])
462 if (Current == Records.end())
469 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
470 if (RecordIt == FilenameHash2RecordIndices.end())
472 return RecordIt->second;
477 unsigned MaxCounterID = 0;
486 unsigned MaxBitmapID = 0;
487 unsigned NumConditions = 0;
493 MaxBitmapID =
Region.MCDCParams.BitmapIdx;
494 NumConditions =
Region.MCDCParams.NumConditions;
498 unsigned SizeInBits =
llvm::alignTo(1L << NumConditions, CHAR_BIT);
499 return MaxBitmapID + (SizeInBits / CHAR_BIT);
502Error CoverageMapping::loadFunctionRecord(
506 if (OrigFuncName.
empty())
508 "record function name is empty");
510 if (
Record.Filenames.empty())
517 std::vector<uint64_t> Counts;
519 Record.FunctionHash, Counts)) {
522 FuncHashMismatches.emplace_back(std::string(
Record.FunctionName),
527 return make_error<InstrProfError>(IPE);
530 Ctx.setCounts(Counts);
532 std::vector<uint8_t> BitmapBytes;
534 Record.FunctionName,
Record.FunctionHash, BitmapBytes)) {
537 FuncHashMismatches.emplace_back(std::string(
Record.FunctionName),
542 return make_error<InstrProfError>(IPE);
545 Ctx.setBitmapBytes(BitmapBytes);
547 assert(!
Record.MappingRegions.empty() &&
"Function has no regions");
554 if (
Record.MappingRegions.size() == 1 &&
555 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
558 unsigned NumConds = 0;
560 std::vector<CounterMappingRegion> MCDCBranches;
569 NumConds =
Region.MCDCParams.NumConditions;
588 MCDCBranches.push_back(
Region);
593 if (--NumConds == 0) {
600 Ctx.evaluateBitmap(MCDCDecision);
601 if (
auto E = ExecutedTestVectorBitmap.
takeError()) {
610 *MCDCDecision, *ExecutedTestVectorBitmap, MCDCBranches);
611 if (
auto E =
Record.takeError()) {
618 MCDCBranches.clear();
626 if (!RecordProvenance[FilenamesHash].insert(
hash_value(OrigFuncName)).second)
629 Functions.push_back(std::move(
Function));
634 unsigned RecordIndex = Functions.size() - 1;
636 auto &RecordIndices = FilenameHash2RecordIndices[
hash_value(Filename)];
640 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
641 RecordIndices.push_back(RecordIndex);
649Error CoverageMapping::loadFromReaders(
650 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
652 for (
const auto &CoverageReader : CoverageReaders) {
653 for (
auto RecordOrErr : *CoverageReader) {
654 if (
Error E = RecordOrErr.takeError())
656 const auto &
Record = *RecordOrErr;
665 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
667 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
668 if (
Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
670 return std::move(Coverage);
679 return make_error<CoverageMapError>(CME.
get(), CME.
getMessage());
683Error CoverageMapping::loadFromFile(
688 Filename,
false,
false);
689 if (std::error_code EC = CovMappingBufOrErr.getError())
692 CovMappingBufOrErr.get()->getMemBufferRef();
698 CovMappingBufRef, Arch, Buffers, ProfSymTab,
699 CompilationDir, FoundBinaryIDs ? &BinaryIDs :
nullptr);
700 if (
Error E = CoverageReadersOrErr.takeError()) {
708 for (
auto &Reader : CoverageReadersOrErr.get())
710 if (FoundBinaryIDs && !Readers.
empty()) {
716 DataFound |= !Readers.
empty();
717 if (
Error E = loadFromReaders(Readers, ProfileReader, Coverage))
727 if (
Error E = ProfileReaderOrErr.takeError())
729 auto ProfileReader = std::move(ProfileReaderOrErr.get());
730 auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
731 bool DataFound =
false;
733 auto GetArch = [&](
size_t Idx) {
736 if (Arches.
size() == 1)
737 return Arches.
front();
744 loadFromFile(File.value(), GetArch(File.index()), CompilationDir,
745 *ProfileReader, *Coverage, DataFound, &FoundBinaryIDs))
750 std::vector<object::BuildID> ProfileBinaryIDs;
755 if (!ProfileBinaryIDs.empty()) {
757 return std::lexicographical_compare(
A.begin(),
A.end(),
B.begin(),
762 ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(),
763 FoundBinaryIDs.
begin(), FoundBinaryIDs.
end(),
764 std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.
end()), Compare);
768 std::optional<std::string> PathOpt = BIDFetcher->
fetch(BinaryID);
770 std::string Path = std::move(*PathOpt);
772 if (
Error E = loadFromFile(Path, Arch, CompilationDir, *ProfileReader,
773 *Coverage, DataFound))
775 }
else if (CheckBinaryIDs) {
779 "Missing binary ID: " +
780 llvm::toHex(BinaryID,
true)));
787 join(ObjectFilenames.
begin(), ObjectFilenames.
end(),
", "),
789 return std::move(Coverage);
798class FunctionInstantiationSetCollector {
799 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
800 MapT InstantiatedFunctions;
805 while (
I !=
E &&
I->FileID != FileID)
807 assert(
I !=
E &&
"function does not cover the given file");
808 auto &Functions = InstantiatedFunctions[
I->startLoc()];
812 MapT::iterator begin() {
return InstantiatedFunctions.begin(); }
813 MapT::iterator end() {
return InstantiatedFunctions.end(); }
816class SegmentBuilder {
817 std::vector<CoverageSegment> &
Segments;
820 SegmentBuilder(std::vector<CoverageSegment> &Segments) :
Segments(
Segments) {}
827 bool IsRegionEntry,
bool EmitSkippedRegion =
false) {
828 bool HasCount = !EmitSkippedRegion &&
832 if (!
Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
834 if (
Last.HasCount == HasCount &&
Last.Count ==
Region.ExecutionCount &&
840 Segments.emplace_back(StartLoc.first, StartLoc.second,
841 Region.ExecutionCount, IsRegionEntry,
844 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
849 <<
" (count = " <<
Last.Count <<
")"
850 << (
Last.IsRegionEntry ?
", RegionEntry" :
"")
851 << (!
Last.HasCount ?
", Skipped" :
"")
852 << (
Last.IsGapRegion ?
", Gap" :
"") <<
"\n";
861 void completeRegionsUntil(std::optional<LineColPair> Loc,
862 unsigned FirstCompletedRegion) {
865 auto CompletedRegionsIt = ActiveRegions.
begin() + FirstCompletedRegion;
866 std::stable_sort(CompletedRegionsIt, ActiveRegions.
end(),
868 return L->endLoc() < R->endLoc();
872 for (
unsigned I = FirstCompletedRegion + 1,
E = ActiveRegions.
size();
I <
E;
874 const auto *CompletedRegion = ActiveRegions[
I];
875 assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
876 "Completed region ends after start of new region");
878 const auto *PrevCompletedRegion = ActiveRegions[
I - 1];
879 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
882 if (Loc && CompletedSegmentLoc == *Loc)
887 if (CompletedSegmentLoc == CompletedRegion->endLoc())
891 for (
unsigned J =
I + 1; J <
E; ++J)
892 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
893 CompletedRegion = ActiveRegions[J];
895 startSegment(*CompletedRegion, CompletedSegmentLoc,
false);
899 if (FirstCompletedRegion &&
Last->endLoc() != *Loc) {
902 startSegment(*ActiveRegions[FirstCompletedRegion - 1],
Last->endLoc(),
904 }
else if (!FirstCompletedRegion && (!Loc || *Loc !=
Last->endLoc())) {
907 startSegment(*
Last,
Last->endLoc(),
false,
true);
911 ActiveRegions.
erase(CompletedRegionsIt, ActiveRegions.
end());
915 for (
const auto &CR :
enumerate(Regions)) {
916 auto CurStartLoc = CR.value().startLoc();
919 auto CompletedRegions =
920 std::stable_partition(ActiveRegions.
begin(), ActiveRegions.
end(),
922 return !(Region->endLoc() <= CurStartLoc);
924 if (CompletedRegions != ActiveRegions.
end()) {
925 unsigned FirstCompletedRegion =
926 std::distance(ActiveRegions.
begin(), CompletedRegions);
927 completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
933 if (CurStartLoc == CR.value().endLoc()) {
937 (CR.index() + 1) == Regions.
size() ||
939 startSegment(ActiveRegions.
empty() ? CR.value() : *ActiveRegions.
back(),
940 CurStartLoc, !GapRegion, Skipped);
943 if (Skipped && !ActiveRegions.
empty())
944 startSegment(*ActiveRegions.
back(), CurStartLoc,
false);
947 if (CR.index() + 1 == Regions.
size() ||
948 CurStartLoc != Regions[CR.index() + 1].startLoc()) {
951 startSegment(CR.value(), CurStartLoc, !GapRegion);
959 if (!ActiveRegions.
empty())
960 completeRegionsUntil(std::nullopt, 0);
966 if (
LHS.startLoc() !=
RHS.startLoc())
967 return LHS.startLoc() <
RHS.startLoc();
970 return RHS.endLoc() <
LHS.endLoc();
980 "Unexpected order of region kind values");
981 return LHS.Kind <
RHS.Kind;
990 auto Active = Regions.
begin();
992 for (
auto I = Regions.
begin() + 1;
I !=
End; ++
I) {
993 if (Active->startLoc() !=
I->startLoc() ||
994 Active->endLoc() !=
I->endLoc()) {
1013 if (
I->Kind == Active->Kind)
1014 Active->ExecutionCount +=
I->ExecutionCount;
1016 return Regions.
drop_back(std::distance(++Active,
End));
1021 static std::vector<CoverageSegment>
1023 std::vector<CoverageSegment>
Segments;
1024 SegmentBuilder
Builder(Segments);
1026 sortNestedRegions(Regions);
1030 dbgs() <<
"Combined regions:\n";
1031 for (
const auto &CR : CombinedRegions)
1032 dbgs() <<
" " << CR.LineStart <<
":" << CR.ColumnStart <<
" -> "
1033 << CR.LineEnd <<
":" << CR.ColumnEnd
1034 <<
" (count=" << CR.ExecutionCount <<
")\n";
1037 Builder.buildSegmentsImpl(CombinedRegions);
1043 if (!(
L.Line <
R.Line) && !(
L.Line ==
R.Line &&
L.Col <
R.Col)) {
1044 if (
L.Line ==
R.Line &&
L.Col ==
R.Col && !
L.HasCount)
1047 <<
" followed by " <<
R.Line <<
":" <<
R.Col <<
"\n");
1048 assert(
false &&
"Coverage segments not unique or sorted");
1060 std::vector<StringRef> Filenames;
1064 auto Last = std::unique(Filenames.begin(), Filenames.end());
1065 Filenames.erase(
Last, Filenames.end());
1073 if (SourceFile ==
Function.Filenames[
I])
1074 FilenameEquivalence[
I] =
true;
1075 return FilenameEquivalence;
1079static std::optional<unsigned>
1082 for (
const auto &CR :
Function.CountedRegions)
1084 IsNotExpandedFile[CR.ExpandedFileID] =
false;
1087 return std::nullopt;
1094static std::optional<unsigned>
1097 if (
I && SourceFile ==
Function.Filenames[*
I])
1099 return std::nullopt;
1108 std::vector<CountedRegion> Regions;
1113 getImpreciseRecordIndicesForFilename(Filename);
1114 for (
unsigned RecordIndex : RecordIndices) {
1118 for (
const auto &CR :
Function.CountedRegions)
1119 if (FileIDs.test(CR.FileID)) {
1120 Regions.push_back(CR);
1122 FileCoverage.Expansions.emplace_back(CR,
Function);
1125 for (
const auto &CR :
Function.CountedBranchRegions)
1126 if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
1127 FileCoverage.BranchRegions.push_back(CR);
1129 for (
const auto &MR :
Function.MCDCRecords)
1130 if (FileIDs.test(MR.getDecisionRegion().FileID))
1131 FileCoverage.MCDCRecords.push_back(MR);
1134 LLVM_DEBUG(
dbgs() <<
"Emitting segments for file: " << Filename <<
"\n");
1135 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1137 return FileCoverage;
1140std::vector<InstantiationGroup>
1142 FunctionInstantiationSetCollector InstantiationSetCollector;
1146 getImpreciseRecordIndicesForFilename(Filename);
1147 for (
unsigned RecordIndex : RecordIndices) {
1152 InstantiationSetCollector.insert(
Function, *MainFileID);
1155 std::vector<InstantiationGroup> Result;
1156 for (
auto &InstantiationSet : InstantiationSetCollector) {
1158 InstantiationSet.first.second,
1159 std::move(InstantiationSet.second)};
1160 Result.emplace_back(std::move(IG));
1172 std::vector<CountedRegion> Regions;
1173 for (
const auto &CR :
Function.CountedRegions)
1174 if (CR.FileID == *MainFileID) {
1175 Regions.push_back(CR);
1177 FunctionCoverage.Expansions.emplace_back(CR,
Function);
1180 for (
const auto &CR :
Function.CountedBranchRegions)
1181 if (CR.FileID == *MainFileID)
1182 FunctionCoverage.BranchRegions.push_back(CR);
1185 for (
const auto &MR :
Function.MCDCRecords)
1186 if (MR.getDecisionRegion().FileID == *MainFileID)
1187 FunctionCoverage.MCDCRecords.push_back(MR);
1191 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1193 return FunctionCoverage;
1200 std::vector<CountedRegion> Regions;
1202 if (CR.FileID == Expansion.
FileID) {
1203 Regions.push_back(CR);
1205 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.
Function);
1209 if (CR.FileID == Expansion.
FileID)
1210 ExpansionCoverage.BranchRegions.push_back(CR);
1213 << Expansion.
FileID <<
"\n");
1214 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1216 return ExpansionCoverage;
1219LineCoverageStats::LineCoverageStats(
1222 : ExecutionCount(0), HasMultipleRegions(
false), Mapped(
false), Line(Line),
1223 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
1225 unsigned MinRegionCount = 0;
1227 return !S->
IsGapRegion && S->HasCount && S->IsRegionEntry;
1229 for (
unsigned I = 0;
I < LineSegments.
size() && MinRegionCount < 2; ++
I)
1230 if (isStartOfRegion(LineSegments[
I]))
1233 bool StartOfSkippedRegion = !LineSegments.
empty() &&
1234 !LineSegments.
front()->HasCount &&
1235 LineSegments.
front()->IsRegionEntry;
1237 HasMultipleRegions = MinRegionCount > 1;
1239 !StartOfSkippedRegion &&
1240 ((WrappedSegment && WrappedSegment->
HasCount) || (MinRegionCount > 0));
1248 ExecutionCount = WrappedSegment->
Count;
1249 if (!MinRegionCount)
1251 for (
const auto *LS : LineSegments)
1252 if (isStartOfRegion(LS))
1253 ExecutionCount = std::max(ExecutionCount, LS->Count);
1257 if (Next == CD.
end()) {
1262 if (Segments.size())
1263 WrappedSegment = Segments.back();
1265 while (Next != CD.
end() && Next->Line == Line)
1266 Segments.push_back(&*Next++);
1273 const std::string &ErrMsg =
"") {
1282 OS <<
"end of File";
1285 OS <<
"no coverage data found";
1288 OS <<
"unsupported coverage format version";
1291 OS <<
"truncated coverage data";
1294 OS <<
"malformed coverage data";
1297 OS <<
"failed to decompress coverage data (zlib)";
1300 OS <<
"`-arch` specifier is invalid or missing for universal binary";
1307 if (!ErrMsg.empty())
1308 OS <<
": " << ErrMsg;
1318class CoverageMappingErrorCategoryType :
public std::error_category {
1319 const char *
name()
const noexcept
override {
return "llvm.coveragemap"; }
1320 std::string message(
int IE)
const override {
1332 static CoverageMappingErrorCategoryType ErrorCategory;
1333 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 Error handleMaybeNoDataFoundError(Error E)
static std::string getCoverageMapErrString(coveragemap_error Err, const std::string &ErrMsg="")
static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx, const CoverageMappingRecord &Record)
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.
const SmallVectorImpl< MachineOperand > & Cond
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.
MCDCRecordProcessor(BitVector &Bitmap, CounterMappingRegion &Region, ArrayRef< CounterMappingRegion > Branches)
MCDCRecord processMCDCRecord()
Process the MC/DC Record in order to produce a result for a boolean expression.
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.
size_type size() const
size - Returns the number of bits in this bitvector.
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.
InstrProfSymtab & getSymtab() override
Return the PGO symtab.
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
Error getFunctionBitmapBytes(StringRef FuncName, uint64_t FuncHash, std::vector< uint8_t > &BitmapBytes)
Fill Bitmap Bytes 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 std::pair< instrprof_error, std::string > take(Error E)
Consume an Error and return the raw enum value contained within it, and the optional error message.
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
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, InstrProfSymtab &IndexedProfSymTab, 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< BitVector > evaluateBitmap(const CounterMappingRegion *MCDCDecision) const
Return the number of times that a region of code associated with this counter was executed.
Expected< MCDCRecord > evaluateMCDCRegion(CounterMappingRegion Region, BitVector Bitmap, ArrayRef< CounterMappingRegion > Branches)
Return an MCDC record that indicates executed test vectors and condition pairs.
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
const std::string & getMessage() 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.
A raw_ostream that writes to an std::string.
The virtual file system interface.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
unsigned NumConditions
Number of Conditions used for a Decision Region (MC/DC only).
unsigned BitmapIdx
Byte Index of Bitmap Coverage Object for a Decision Region (MC/DC only).
A Counter mapping region associates a source range with a specific counter.
MCDCParameters MCDCParams
Parameters used for Modified Condition/Decision Coverage.
@ ExpansionRegion
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
@ MCDCDecisionRegion
A DecisionRegion represents a top-level boolean expression and is associated with a variable length b...
@ MCDCBranchRegion
A Branch Region can be extended to include IDs to facilitate MC/DC.
@ 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.
MCDC Record grouping all information together.