LLVM: lib/ProfileData/Coverage/CoverageMapping.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
32#include
33#include
34#include
35#include
36#include
37#include
38#include
39#include
40#include
41#include
42#include <system_error>
43#include
44#include
45
46using namespace llvm;
48
49#define DEBUG_TYPE "coverage-mapping"
50
52 auto [It, Inserted] = ExpressionIndices.try_emplace(E, Expressions.size());
53 if (Inserted)
54 Expressions.push_back(E);
56}
57
58void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
59 SmallVectorImpl &Terms) {
60 switch (C.getKind()) {
62 break;
65 break;
67 const auto &E = Expressions[C.getExpressionID()];
68 extractTerms(E.LHS, Factor, Terms);
69 extractTerms(
71 break;
72 }
73}
74
75Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
76
78 extractTerms(ExpressionTree, +1, Terms);
79
80
81
82 if (Terms.size() == 0)
84
85
87 return LHS.CounterID < RHS.CounterID;
88 });
89
90
91 auto Prev = Terms.begin();
92 for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
93 if (I->CounterID == Prev->CounterID) {
94 Prev->Factor += I->Factor;
95 continue;
96 }
97 ++Prev;
98 *Prev = *I;
99 }
100 Terms.erase(++Prev, Terms.end());
101
102 Counter C;
103
104
105 for (auto T : Terms) {
106 if (T.Factor <= 0)
107 continue;
108 for (int I = 0; I < T.Factor; ++I)
109 if (C.isZero())
111 else
114 }
115
116
117 for (auto T : Terms) {
118 if (T.Factor >= 0)
119 continue;
120 for (int I = 0; I < -T.Factor; ++I)
123 }
124 return C;
125}
126
129 return Simplify ? simplify(Cnt) : Cnt;
130}
131
133 bool Simplify) {
135 return Simplify ? simplify(Cnt) : Cnt;
136}
137
139
140 if (auto I = Map.find(C); I != Map.end())
141 return I->second;
142
143 if (.isExpression())
144 return C;
145
146 auto CE = Expressions[C.getExpressionID()];
147 auto NewLHS = subst(CE.LHS, Map);
148 auto NewRHS = subst(CE.RHS, Map);
149
150
151 switch (CE.Kind) {
154 break;
157 break;
158 }
159
160 return C;
161}
162
164 switch (C.getKind()) {
166 OS << '0';
167 return;
169 OS << '#' << C.getCounterID();
170 break;
172 if (C.getExpressionID() >= Expressions.size())
173 return;
174 const auto &E = Expressions[C.getExpressionID()];
175 OS << '(';
176 dump(E.LHS, OS);
178 dump(E.RHS, OS);
179 OS << ')';
180 break;
181 }
182 }
183 if (CounterValues.empty())
184 return;
186 if (auto E = Value.takeError()) {
188 return;
189 }
190 OS << '[' << *Value << ']';
191}
192
194 struct StackElem {
196 int64_t LHS = 0;
197 enum {
198 KNeverVisited = 0,
199 KVisitedOnce = 1,
200 KVisitedTwice = 2,
201 } VisitCount = KNeverVisited;
202 };
203
204 std::stack CounterStack;
205 CounterStack.push({C});
206
207 int64_t LastPoppedValue;
208
209 while (!CounterStack.empty()) {
210 StackElem &Current = CounterStack.top();
211
212 switch (Current.ICounter.getKind()) {
214 LastPoppedValue = 0;
215 CounterStack.pop();
216 break;
218 if (Current.ICounter.getCounterID() >= CounterValues.size())
220 LastPoppedValue = CounterValues[Current.ICounter.getCounterID()];
221 CounterStack.pop();
222 break;
224 if (Current.ICounter.getExpressionID() >= Expressions.size())
226 const auto &E = Expressions[Current.ICounter.getExpressionID()];
227 if (Current.VisitCount == StackElem::KNeverVisited) {
228 CounterStack.push(StackElem{E.LHS});
229 Current.VisitCount = StackElem::KVisitedOnce;
230 } else if (Current.VisitCount == StackElem::KVisitedOnce) {
231 Current.LHS = LastPoppedValue;
232 CounterStack.push(StackElem{E.RHS});
233 Current.VisitCount = StackElem::KVisitedTwice;
234 } else {
235 int64_t LHS = Current.LHS;
236 int64_t RHS = LastPoppedValue;
237 LastPoppedValue =
239 CounterStack.pop();
240 }
241 break;
242 }
243 }
244 }
245
246 return LastPoppedValue;
247}
248
249
250
251
252
254 if (IndependencePairs)
255 return;
256
257 IndependencePairs.emplace();
258
259 unsigned NumTVs = TV.size();
260
261 unsigned TVTrueIdx = std::distance(
262 TV.begin(),
264 [&](auto I) { return (I.second == MCDCRecord::MCDC_True); })
265
266 );
267 for (unsigned I = TVTrueIdx; I < NumTVs; ++I) {
268 const auto &[A, ACond] = TV[I];
270 for (unsigned J = 0; J < TVTrueIdx; ++J) {
271 const auto &[B, BCond] = TV[J];
273
274
275 auto AB = A.getDifferences(B);
276 if (AB.count() == 1)
277 IndependencePairs->insert(
278 {AB.find_first(), std::make_pair(J + 1, I + 1)});
279 }
280 }
281}
282
286
289 for (unsigned ID = 0; ID < N; ++ID) {
290 for (unsigned C = 0; C < 2; ++C) {
291#ifndef NDEBUG
293#endif
294 auto NextID = NextIDs[ID][C];
295 Nodes[ID].NextIDs[C] = NextID;
296 if (NextID >= 0)
297 ++Nodes[NextID].InCount;
298 }
299 }
300
301
304 int,
305 unsigned
306 >>
307 Decisions;
308
309
311 assert(Nodes[0].InCount == 0);
312 Nodes[0].Width = 1;
314
315 unsigned Ord = 0;
316 while (!Q.empty()) {
317 auto IID = Q.begin();
318 int ID = *IID;
322
323 for (unsigned I = 0; I < 2; ++I) {
324 auto NextID = Node.NextIDs[I];
325 assert(NextID != 0 && "NextID should not point to the top");
326 if (NextID < 0) {
327
328 Decisions.emplace_back(-Node.Width, Ord++, ID, I);
329 assert(Ord == Decisions.size());
330 continue;
331 }
332
333
334 auto &NextNode = Nodes[NextID];
335 assert(NextNode.InCount > 0);
336
337
340 auto NextWidth = int64_t(NextNode.Width) + Node.Width;
343 return;
344 }
345 NextNode.Width = NextWidth;
346
347
348
349 if (--NextNode.InCount == 0)
351 }
352 }
353
355
356
357 int64_t CurIdx = 0;
358 for (auto [NegWidth, Ord, ID, C] : Decisions) {
359 int Width = -NegWidth;
360 assert(Nodes[ID].Width == Width);
361 assert(Nodes[ID].NextIDs[C] < 0);
364 CurIdx += Width;
367 return;
368 }
369 }
370
373
374#ifndef NDEBUG
375 for (const auto &Idxs : Indices)
376 for (auto Idx : Idxs)
377 assert(Idx != INT_MIN);
379#endif
380}
381
382namespace {
383
384
385
386class NextIDsBuilder {
387protected:
389
390public:
392 : NextIDs(Branches.size()) {
393#ifndef NDEBUG
395#endif
396 for (const auto *Branch : Branches) {
397 const auto &BranchParams = Branch->getBranchParams();
398 assert(SeenIDs.insert(BranchParams.ID).second && "Duplicate CondID");
399 NextIDs[BranchParams.ID] = BranchParams.Conds;
400 }
401 assert(SeenIDs.size() == Branches.size());
402 }
403};
404
406
407
408
409
411
412
415
416
417
419
420
421 unsigned NumConditions;
422
423
425
426
428
429
430
431 std::array<MCDCRecord::TestVectors, 2> ExecVectorsByCond;
432
433
434
436
437#ifndef NDEBUG
439#endif
440
441 bool IsVersion11;
442
443public:
444 MCDCRecordProcessor(const BitVector &Bitmap,
447 bool IsVersion11)
448 : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
450 Branches(Branches), NumConditions(DecisionParams.NumConditions),
452 IndependencePairs(NumConditions), ExecVectors(ExecVectorsByCond[false]),
453 IsVersion11(IsVersion11) {}
454
455private:
456
457
458
460 int TVIdx) {
465 auto NextID = NextIDs[ID][MCDCCond];
466 auto NextTVIdx = TVIdx + Indices[ID][MCDCCond];
467 assert(NextID == SavedNodes[ID].NextIDs[MCDCCond]);
468 if (NextID >= 0) {
469 buildTestVector(TV, NextID, NextTVIdx);
470 continue;
471 }
472
473 assert(TVIdx < SavedNodes[ID].Width);
474 assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
475
476 if (!Bitmap[IsVersion11
477 ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
478 : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
479 continue;
480
481
482
483
484 ExecVectorsByCond[MCDCCond].push_back({TV, MCDCCond});
485 }
486
487
489 }
490
491
492
493 void findExecutedTestVectors() {
494
495
496
497
498 MCDCRecord::TestVector TV(NumConditions);
499 buildTestVector(TV, 0, 0);
500 assert(TVIdxs.size() == unsigned(NumTestVectors) &&
501 "TVIdxs wasn't fulfilled");
502
503
504
505
506 auto &ExecVectorsT = ExecVectorsByCond[true];
507 ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()),
508 std::make_move_iterator(ExecVectorsT.end()));
509 }
510
511public:
512
513
514
515
516
517
518
519
520
521 MCDCRecord processMCDCRecord() {
524
525
526
527
528
529
530
531
532
533
534
535 for (auto [I, B] : enumerate(Branches)) {
536 const auto &BranchParams = B->getBranchParams();
537 PosToID[I] = BranchParams.ID;
538 CondLoc[I] = B->startLoc();
539 Folded[false][I] = B->FalseCount.isZero();
540 Folded[true][I] = B->Count.isZero();
541 }
542
543
544 findExecutedTestVectors();
545
546
547 return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),
548 std::move(PosToID), std::move(CondLoc));
549 }
550};
551
552}
553
557
558 MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches, IsVersion11);
559 return MCDCProcessor.processMCDCRecord();
560}
561
563 struct StackElem {
565 int64_t LHS = 0;
566 enum {
567 KNeverVisited = 0,
568 KVisitedOnce = 1,
569 KVisitedTwice = 2,
570 } VisitCount = KNeverVisited;
571 };
572
573 std::stack CounterStack;
574 CounterStack.push({C});
575
576 int64_t LastPoppedValue;
577
578 while (!CounterStack.empty()) {
579 StackElem &Current = CounterStack.top();
580
581 switch (Current.ICounter.getKind()) {
583 LastPoppedValue = 0;
584 CounterStack.pop();
585 break;
587 LastPoppedValue = Current.ICounter.getCounterID();
588 CounterStack.pop();
589 break;
591 if (Current.ICounter.getExpressionID() >= Expressions.size()) {
592 LastPoppedValue = 0;
593 CounterStack.pop();
594 } else {
595 const auto &E = Expressions[Current.ICounter.getExpressionID()];
596 if (Current.VisitCount == StackElem::KNeverVisited) {
597 CounterStack.push(StackElem{E.LHS});
598 Current.VisitCount = StackElem::KVisitedOnce;
599 } else if (Current.VisitCount == StackElem::KVisitedOnce) {
600 Current.LHS = LastPoppedValue;
601 CounterStack.push(StackElem{E.RHS});
602 Current.VisitCount = StackElem::KVisitedTwice;
603 } else {
604 int64_t LHS = Current.LHS;
605 int64_t RHS = LastPoppedValue;
606 LastPoppedValue = std::max(LHS, RHS);
607 CounterStack.pop();
608 }
609 }
610 break;
611 }
612 }
613 }
614
615 return LastPoppedValue;
616}
617
618void FunctionRecordIterator::skipOtherFiles() {
619 while (Current != Records.end() && !Filename.empty() &&
620 Filename != Current->Filenames[0])
621 advanceOne();
622 if (Current == Records.end())
624}
625
626ArrayRef CoverageMapping::getImpreciseRecordIndicesForFilename(
628 size_t FilenameHash = hash_value(Filename);
629 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
630 if (RecordIt == FilenameHash2RecordIndices.end())
631 return {};
632 return RecordIt->second;
633}
634
637 unsigned MaxCounterID = 0;
638 for (const auto &Region : Record.MappingRegions) {
639 MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
640 }
641 return MaxCounterID;
642}
643
644
646 bool IsVersion11) {
647 unsigned MaxBitmapIdx = 0;
648 unsigned NumConditions = 0;
649
650
651
654 continue;
655 const auto &DecisionParams = Region.getDecisionParams();
656 if (MaxBitmapIdx <= DecisionParams.BitmapIdx) {
657 MaxBitmapIdx = DecisionParams.BitmapIdx;
658 NumConditions = DecisionParams.NumConditions;
659 }
660 }
661
662 if (IsVersion11)
663 MaxBitmapIdx = MaxBitmapIdx * CHAR_BIT +
665
666 return MaxBitmapIdx;
667}
668
669namespace {
670
671
672class MCDCDecisionRecorder {
673private:
674
675
676
677
678 struct DecisionRecord {
679 const CounterMappingRegion *DecisionRegion;
680
681
682 mcdc::DecisionParameters DecisionParams;
685
686
687
689
690
691
693
694
695
696
697
698 DenseSet ExpandedFileIDs;
699
700 DecisionRecord(const CounterMappingRegion &Decision)
701 : DecisionRegion(&Decision),
702 DecisionParams(Decision.getDecisionParams()),
703 DecisionStartLoc(Decision.startLoc()),
704 DecisionEndLoc(Decision.endLoc()) {
706 }
707
708
709 bool dominates(const CounterMappingRegion &R) const {
710
711 if (R.FileID == DecisionRegion->FileID &&
712 R.startLoc() >= DecisionStartLoc && R.endLoc() <= DecisionEndLoc)
713 return true;
714
715
716 return ExpandedFileIDs.contains(R.FileID);
717 }
718
720 NotProcessed = 0,
721 Processed,
722 Completed,
723 };
724
725
726
727
728 Result addBranch(const CounterMappingRegion &Branch) {
730
732
735 return NotProcessed;
736
738 return NotProcessed;
739
741
742
743
744 if (ConditionID == 0)
745 MCDCBranches.insert(MCDCBranches.begin(), &Branch);
746 else
748
749
751
752
753 return (MCDCBranches.size() == DecisionParams.NumConditions ? Completed
754 : Processed);
755 }
756
757
758
759
760 bool recordExpansion(const CounterMappingRegion &Expansion) {
762 return false;
763
765 return true;
766 }
767 };
768
769private:
770
771
772
774
775public:
776 ~MCDCDecisionRecorder() {
777 assert(Decisions.empty() && "All Decisions have not been resolved");
778 }
779
780
781 void registerDecision(const CounterMappingRegion &Decision) {
783 }
784
785 void recordExpansion(const CounterMappingRegion &Expansion) {
787 return Decision.recordExpansion(Expansion);
788 });
789 }
790
791 using DecisionAndBranches =
792 std::pair<const CounterMappingRegion *,
794 >;
795
796
797
798
799
800 std::optional
801 processBranch(const CounterMappingRegion &Branch) {
802
803 for (auto DecisionIter = Decisions.begin(), DecisionEnd = Decisions.end();
804 DecisionIter != DecisionEnd; ++DecisionIter)
805 switch (DecisionIter->addBranch(Branch)) {
806 case DecisionRecord::NotProcessed:
807 continue;
808 case DecisionRecord::Processed:
809 return std::nullopt;
810 case DecisionRecord::Completed:
811 DecisionAndBranches Result =
812 std::make_pair(DecisionIter->DecisionRegion,
813 std::move(DecisionIter->MCDCBranches));
814 Decisions.erase(DecisionIter);
816 }
817
819 }
820};
821
822}
823
824Error CoverageMapping::loadFunctionRecord(
825 const CoverageMappingRecord &Record,
826 const std::optional<std::reference_wrapper>
827 &ProfileReader) {
828 StringRef OrigFuncName = Record.FunctionName;
829 if (OrigFuncName.empty())
831 "record function name is empty");
832
835 else
837
838 CounterMappingContext Ctx(Record.Expressions);
839
840 std::vector<uint64_t> Counts;
841 if (ProfileReader) {
842 if (Error E = ProfileReader.value().get().getFunctionCounts(
846 FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
849 }
853 }
854 } else {
856 }
857 Ctx.setCounts(Counts);
858
859 bool IsVersion11 =
860 ProfileReader && ProfileReader.value().get().getVersion() <
862
863 BitVector Bitmap;
864 if (ProfileReader) {
865 if (Error E = ProfileReader.value().get().getFunctionBitmap(
869 FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
872 }
876 }
877 } else {
879 }
880 Ctx.setBitmap(std::move(Bitmap));
881
883
884
885
886
887
888
890 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
892
893 MCDCDecisionRecorder MCDCDecisions;
896
897
899 MCDCDecisions.registerDecision(Region);
900 continue;
901 }
902 Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
903 if (auto E = ExecutionCount.takeError()) {
906 }
907 Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
908 if (auto E = AltExecutionCount.takeError()) {
911 }
912 Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
913
914
916 MCDCDecisions.recordExpansion(Region);
917 continue;
918 }
919
920
922 continue;
923
924 auto Result = MCDCDecisions.processBranch(Region);
925 if (!Result)
926 continue;
927
928 auto MCDCDecision = Result->first;
929 auto &MCDCBranches = Result->second;
930
931
932
933
934 Expected Record =
935 Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
939 }
940
941
942 Function.pushMCDCRecord(std::move(*Record));
943 }
944
945
947 if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
949
950 Functions.push_back(std::move(Function));
951
952
953
954
955 unsigned RecordIndex = Functions.size() - 1;
956 for (StringRef Filename : Record.Filenames) {
957 auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
958
959
960
961 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
962 RecordIndices.push_back(RecordIndex);
963 }
964
966}
967
968
969
970Error CoverageMapping::loadFromReaders(
971 ArrayRef<std::unique_ptr> CoverageReaders,
972 std::optional<std::reference_wrapper>
973 &ProfileReader,
974 CoverageMapping &Coverage) {
975 assert(.SingleByteCoverage || !ProfileReader ||
976 *Coverage.SingleByteCoverage ==
977 ProfileReader.value().get().hasSingleByteCoverage());
978 Coverage.SingleByteCoverage =
979 !ProfileReader || ProfileReader.value().get().hasSingleByteCoverage();
980 for (const auto &CoverageReader : CoverageReaders) {
981 for (auto RecordOrErr : *CoverageReader) {
982 if (Error E = RecordOrErr.takeError())
983 return E;
984 const auto &Record = *RecordOrErr;
985 if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
986 return E;
987 }
988 }
990}
991
993 ArrayRef<std::unique_ptr> CoverageReaders,
994 std::optional<std::reference_wrapper>
995 &ProfileReader) {
996 auto Coverage = std::unique_ptr(new CoverageMapping());
997 if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
998 return std::move(E);
999 return std::move(Coverage);
1000}
1001
1002
1010
1011Error CoverageMapping::loadFromFile(
1012 StringRef Filename, StringRef Arch, StringRef CompilationDir,
1013 std::optional<std::reference_wrapper>
1014 &ProfileReader,
1015 CoverageMapping &Coverage, bool &DataFound,
1016 SmallVectorImplobject::BuildID *FoundBinaryIDs) {
1018 Filename, false, false);
1019 if (std::error_code EC = CovMappingBufOrErr.getError())
1021 MemoryBufferRef CovMappingBufRef =
1022 CovMappingBufOrErr.get()->getMemBufferRef();
1024
1027 CovMappingBufRef, Arch, Buffers, CompilationDir,
1028 FoundBinaryIDs ? &BinaryIDs : nullptr);
1029 if (Error E = CoverageReadersOrErr.takeError()) {
1031 if (E)
1033 return E;
1034 }
1035
1037 for (auto &Reader : CoverageReadersOrErr.get())
1038 Readers.push_back(std::move(Reader));
1039 if (FoundBinaryIDs && !Readers.empty()) {
1043 }));
1044 }
1045 DataFound |= !Readers.empty();
1046 if (Error E = loadFromReaders(Readers, ProfileReader, Coverage))
1049}
1050
1053 std::optional ProfileFilename, vfs::FileSystem &FS,
1056 std::unique_ptr ProfileReader;
1057 if (ProfileFilename) {
1058 auto ProfileReaderOrErr =
1060 if (Error E = ProfileReaderOrErr.takeError())
1061 return createFileError(ProfileFilename.value(), std::move(E));
1062 ProfileReader = std::move(ProfileReaderOrErr.get());
1063 }
1064 auto ProfileReaderRef =
1065 ProfileReader
1066 ? std::optional<std::reference_wrapper>(
1067 *ProfileReader)
1068 : std::nullopt;
1069 auto Coverage = std::unique_ptr(new CoverageMapping());
1070 bool DataFound = false;
1071
1072 auto GetArch = [&](size_t Idx) {
1073 if (Arches.empty())
1075 if (Arches.size() == 1)
1076 return Arches.front();
1077 return Arches[Idx];
1078 };
1079
1081 for (const auto &File : llvm::enumerate(ObjectFilenames)) {
1082 if (Error E = loadFromFile(File.value(), GetArch(File.index()),
1083 CompilationDir, ProfileReaderRef, *Coverage,
1084 DataFound, &FoundBinaryIDs))
1085 return std::move(E);
1086 }
1087
1088 if (BIDFetcher) {
1089 std::vectorobject::BuildID ProfileBinaryIDs;
1090 if (ProfileReader)
1091 if (Error E = ProfileReader->readBinaryIds(ProfileBinaryIDs))
1092 return createFileError(ProfileFilename.value(), std::move(E));
1093
1095 if (!ProfileBinaryIDs.empty()) {
1097 return std::lexicographical_compare(A.begin(), A.end(), B.begin(),
1098 B.end());
1099 };
1100 llvm::sort(FoundBinaryIDs, Compare);
1101 std::set_difference(
1102 ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(),
1103 FoundBinaryIDs.begin(), FoundBinaryIDs.end(),
1104 std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.end()), Compare);
1105 }
1106
1108 std::optionalstd::string PathOpt = BIDFetcher->fetch(BinaryID);
1109 if (PathOpt) {
1110 std::string Path = std::move(*PathOpt);
1112 if (Error E = loadFromFile(Path, Arch, CompilationDir, ProfileReaderRef,
1113 *Coverage, DataFound))
1114 return std::move(E);
1115 } else if (CheckBinaryIDs) {
1117 ProfileFilename.value(),
1119 "Missing binary ID: " +
1120 llvm::toHex(BinaryID, true)));
1121 }
1122 }
1123 }
1124
1125 if (!DataFound)
1127 join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "),
1129 return std::move(Coverage);
1130}
1131
1132namespace {
1133
1134
1135
1136
1137
1138class FunctionInstantiationSetCollector {
1139 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
1140 MapT InstantiatedFunctions;
1141
1142public:
1145 while (I != E && I->FileID != FileID)
1146 ++I;
1147 assert(I != E && "function does not cover the given file");
1148 auto &Functions = InstantiatedFunctions[I->startLoc()];
1149 Functions.push_back(&Function);
1150 }
1151
1152 MapT::iterator begin() { return InstantiatedFunctions.begin(); }
1153 MapT::iterator end() { return InstantiatedFunctions.end(); }
1154};
1155
1156class SegmentBuilder {
1157 std::vector &Segments;
1159
1160 SegmentBuilder(std::vector &Segments) : Segments(Segments) {}
1161
1162
1163
1164
1165
1166 void startSegment(const CountedRegion &Region, LineColPair StartLoc,
1167 bool IsRegionEntry, bool EmitSkippedRegion = false) {
1168 bool HasCount = !EmitSkippedRegion &&
1170
1171
1172 if (.empty() && !IsRegionEntry && !EmitSkippedRegion) {
1174 if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
1175 .IsRegionEntry)
1176 return;
1177 }
1178
1179 if (HasCount)
1180 Segments.emplace_back(StartLoc.first, StartLoc.second,
1181 Region.ExecutionCount, IsRegionEntry,
1183 else
1184 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
1185
1188 dbgs() << "Segment at " << Last.Line << ":" << Last.Col
1189 << " (count = " << Last.Count << ")"
1190 << (Last.IsRegionEntry ? ", RegionEntry" : "")
1191 << (.HasCount ? ", Skipped" : "")
1192 << (Last.IsGapRegion ? ", Gap" : "") << "\n";
1193 });
1194 }
1195
1196
1197
1198
1199
1200
1201 void completeRegionsUntil(std::optional Loc,
1202 unsigned FirstCompletedRegion) {
1203
1204
1205 auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
1206 std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
1207 [](const CountedRegion *L, const CountedRegion *R) {
1208 return L->endLoc() < R->endLoc();
1209 });
1210
1211
1212 for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
1213 ++I) {
1214 const auto *CompletedRegion = ActiveRegions[I];
1215 assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
1216 "Completed region ends after start of new region");
1217
1218 const auto *PrevCompletedRegion = ActiveRegions[I - 1];
1219 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
1220
1221
1222 if (Loc && CompletedSegmentLoc == *Loc)
1223 break;
1224
1225
1226
1227 if (CompletedSegmentLoc == CompletedRegion->endLoc())
1228 continue;
1229
1230
1231 for (unsigned J = I + 1; J < E; ++J)
1232 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
1233 CompletedRegion = ActiveRegions[J];
1234
1235 startSegment(*CompletedRegion, CompletedSegmentLoc, false);
1236 }
1237
1238 auto Last = ActiveRegions.back();
1239 if (FirstCompletedRegion && Last->endLoc() != *Loc) {
1240
1241
1242 startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
1243 false);
1244 } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
1245
1246
1247 startSegment(*Last, Last->endLoc(), false, true);
1248 }
1249
1250
1251 ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
1252 }
1253
1255 for (const auto &CR : enumerate(Regions)) {
1256 auto CurStartLoc = CR.value().startLoc();
1257
1258
1259 auto CompletedRegions =
1260 std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
1261 [&](const CountedRegion *Region) {
1262 return !(Region->endLoc() <= CurStartLoc);
1263 });
1264 if (CompletedRegions != ActiveRegions.end()) {
1265 unsigned FirstCompletedRegion =
1266 std::distance(ActiveRegions.begin(), CompletedRegions);
1267 completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
1268 }
1269
1271
1272
1273 if (CurStartLoc == CR.value().endLoc()) {
1274
1275
1277 (CR.index() + 1) == Regions.size() ||
1279 startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
1280 CurStartLoc, !GapRegion, Skipped);
1281
1282
1283 if (Skipped && !ActiveRegions.empty())
1284 startSegment(*ActiveRegions.back(), CurStartLoc, false);
1285 continue;
1286 }
1287 if (CR.index() + 1 == Regions.size() ||
1288 CurStartLoc != Regions[CR.index() + 1].startLoc()) {
1289
1290
1291 startSegment(CR.value(), CurStartLoc, !GapRegion);
1292 }
1293
1294
1295 ActiveRegions.push_back(&CR.value());
1296 }
1297
1298
1299 if (!ActiveRegions.empty())
1300 completeRegionsUntil(std::nullopt, 0);
1301 }
1302
1303
1305 llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
1306 if (LHS.startLoc() != RHS.startLoc())
1307 return LHS.startLoc() < RHS.startLoc();
1308 if (LHS.endLoc() != RHS.endLoc())
1309
1310 return RHS.endLoc() < LHS.endLoc();
1311
1312
1313
1314
1315
1320 "Unexpected order of region kind values");
1321 return LHS.Kind < RHS.Kind;
1322 });
1323 }
1324
1325
1328 if (Regions.empty())
1329 return Regions;
1331 auto End = Regions.end();
1332 for (auto I = Regions.begin() + 1; I != End; ++I) {
1333 if (Active->startLoc() != I->startLoc() ||
1334 Active->endLoc() != I->endLoc()) {
1335
1337 if (Active != I)
1339 continue;
1340 }
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 if (I->Kind == Active->Kind)
1354 Active->ExecutionCount += I->ExecutionCount;
1355 }
1356 return Regions.drop_back(std::distance(++Active, End));
1357 }
1358
1359public:
1360
1361 static std::vector
1363 std::vector Segments;
1364 SegmentBuilder Builder(Segments);
1365
1366 sortNestedRegions(Regions);
1368
1370 dbgs() << "Combined regions:\n";
1371 for (const auto &CR : CombinedRegions)
1372 dbgs() << " " << CR.LineStart << ":" << CR.ColumnStart << " -> "
1373 << CR.LineEnd << ":" << CR.ColumnEnd
1374 << " (count=" << CR.ExecutionCount << ")\n";
1375 });
1376
1377 Builder.buildSegmentsImpl(CombinedRegions);
1378
1379#ifndef NDEBUG
1380 for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
1383 if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
1384 if (L.Line == R.Line && L.Col == R.Col && .HasCount)
1385 continue;
1386 LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
1387 << " followed by " << R.Line << ":" << R.Col << "\n");
1388 assert(false && "Coverage segments not unique or sorted");
1389 }
1390 }
1391#endif
1392
1394 }
1395};
1396
1397}
1398
1400 std::vector Filenames;
1405 Filenames.erase(Last, Filenames.end());
1406 return Filenames;
1407}
1408
1413 if (SourceFile == Function.Filenames[I])
1414 FilenameEquivalence[I] = true;
1415 return FilenameEquivalence;
1416}
1417
1418
1419static std::optional
1422 for (const auto &CR : Function.CountedRegions)
1424 IsNotExpandedFile[CR.ExpandedFileID] = false;
1426 if (I == -1)
1427 return std::nullopt;
1428 return I;
1429}
1430
1431
1432
1433
1434static std::optional
1437 if (I && SourceFile == Function.Filenames[*I])
1438 return I;
1439 return std::nullopt;
1440}
1441
1445
1447 assert(SingleByteCoverage);
1448 CoverageData FileCoverage(*SingleByteCoverage, Filename);
1449 std::vector Regions;
1450
1451
1452
1454 getImpreciseRecordIndicesForFilename(Filename);
1455 for (unsigned RecordIndex : RecordIndices) {
1459 for (const auto &CR : Function.CountedRegions)
1460 if (FileIDs.test(CR.FileID)) {
1461 Regions.push_back(CR);
1462 if (MainFileID && isExpansion(CR, *MainFileID))
1463 FileCoverage.Expansions.emplace_back(CR, Function);
1464 }
1465
1466 for (const auto &CR : Function.CountedBranchRegions)
1467 if (FileIDs.test(CR.FileID))
1468 FileCoverage.BranchRegions.push_back(CR);
1469
1470 for (const auto &MR : Function.MCDCRecords)
1471 if (FileIDs.test(MR.getDecisionRegion().FileID))
1472 FileCoverage.MCDCRecords.push_back(MR);
1473 }
1474
1475 LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
1476 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1477
1478 return FileCoverage;
1479}
1480
1481std::vector
1483 FunctionInstantiationSetCollector InstantiationSetCollector;
1484
1485
1487 getImpreciseRecordIndicesForFilename(Filename);
1488 for (unsigned RecordIndex : RecordIndices) {
1491 if (!MainFileID)
1492 continue;
1493 InstantiationSetCollector.insert(Function, *MainFileID);
1494 }
1495
1496 std::vector Result;
1497 for (auto &InstantiationSet : InstantiationSetCollector) {
1499 InstantiationSet.first.second,
1500 std::move(InstantiationSet.second)};
1501 Result.emplace_back(std::move(IG));
1502 }
1503 return Result;
1504}
1505
1509 if (!MainFileID)
1511
1512 assert(SingleByteCoverage);
1513 CoverageData FunctionCoverage(*SingleByteCoverage,
1514 Function.Filenames[*MainFileID]);
1515 std::vector Regions;
1516 for (const auto &CR : Function.CountedRegions)
1517 if (CR.FileID == *MainFileID) {
1518 Regions.push_back(CR);
1520 FunctionCoverage.Expansions.emplace_back(CR, Function);
1521 }
1522
1523 for (const auto &CR : Function.CountedBranchRegions)
1524 if (CR.FileID == *MainFileID)
1525 FunctionCoverage.BranchRegions.push_back(CR);
1526
1527
1528 for (const auto &MR : Function.MCDCRecords)
1529 if (MR.getDecisionRegion().FileID == *MainFileID)
1530 FunctionCoverage.MCDCRecords.push_back(MR);
1531
1533 << "\n");
1534 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1535
1536 return FunctionCoverage;
1537}
1538
1541 assert(SingleByteCoverage);
1543 *SingleByteCoverage, Expansion.Function.Filenames[Expansion.FileID]);
1544 std::vector Regions;
1545 for (const auto &CR : Expansion.Function.CountedRegions)
1546 if (CR.FileID == Expansion.FileID) {
1547 Regions.push_back(CR);
1549 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
1550 }
1551 for (const auto &CR : Expansion.Function.CountedBranchRegions)
1552
1553 if (CR.FileID == Expansion.FileID)
1554 ExpansionCoverage.BranchRegions.push_back(CR);
1555
1556 LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
1558 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
1559
1560 return ExpansionCoverage;
1561}
1562
1563LineCoverageStats::LineCoverageStats(
1566 : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
1567 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
1568
1569 unsigned MinRegionCount = 0;
1571 return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
1572 };
1573 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
1574 if (isStartOfRegion(LineSegments[I]))
1575 ++MinRegionCount;
1576
1577 bool StartOfSkippedRegion = !LineSegments.empty() &&
1578 !LineSegments.front()->HasCount &&
1579 LineSegments.front()->IsRegionEntry;
1580
1581 HasMultipleRegions = MinRegionCount > 1;
1582 Mapped =
1583 !StartOfSkippedRegion &&
1584 ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
1585
1586
1587
1588 Mapped |= any_of(LineSegments, [](const auto *Seq) {
1589 return Seq->IsRegionEntry && Seq->HasCount;
1590 });
1591
1592 if (!Mapped) {
1593 return;
1594 }
1595
1596
1597
1598 if (WrappedSegment)
1599 ExecutionCount = WrappedSegment->Count;
1600 if (!MinRegionCount)
1601 return;
1602 for (const auto *LS : LineSegments)
1603 if (isStartOfRegion(LS))
1604 ExecutionCount = std::max(ExecutionCount, LS->Count);
1605}
1606
1608 if (Next == CD.end()) {
1610 Ended = true;
1611 return *this;
1612 }
1613 if (Segments.size())
1614 WrappedSegment = Segments.back();
1615 Segments.clear();
1616 while (Next != CD.end() && Next->Line == Line)
1617 Segments.push_back(&*Next++);
1619 ++Line;
1620 return *this;
1621}
1622
1624 const std::string &ErrMsg = "") {
1625 std::string Msg;
1627
1628 switch (Err) {
1630 OS << "success";
1631 break;
1633 OS << "end of File";
1634 break;
1636 OS << "no coverage data found";
1637 break;
1639 OS << "unsupported coverage format version";
1640 break;
1642 OS << "truncated coverage data";
1643 break;
1645 OS << "malformed coverage data";
1646 break;
1648 OS << "failed to decompress coverage data (zlib)";
1649 break;
1651 OS << "`-arch` specifier is invalid or missing for universal binary";
1652 break;
1653 }
1654
1655
1656 if (!ErrMsg.empty())
1657 OS << ": " << ErrMsg;
1658
1659 return Msg;
1660}
1661
1662namespace {
1663
1664
1665
1666
1667class CoverageMappingErrorCategoryType : public std::error_category {
1668 const char *name() const noexcept override { return "llvm.coveragemap"; }
1669 std::string message(int IE) const override {
1671 }
1672};
1673
1674}
1675
1679
1681 static CoverageMappingErrorCategoryType ErrorCategory;
1682 return ErrorCategory;
1683}
1684
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
Definition CoverageMapping.cpp:1409
static std::optional< unsigned > findMainViewFileID(const FunctionRecord &Function)
Return the ID of the file where the definition of the function is located.
Definition CoverageMapping.cpp:1420
static bool isExpansion(const CountedRegion &R, unsigned FileID)
Definition CoverageMapping.cpp:1442
static Error handleMaybeNoDataFoundError(Error E)
Definition CoverageMapping.cpp:1003
static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record, bool IsVersion11)
Returns the bit count.
Definition CoverageMapping.cpp:645
static std::string getCoverageMapErrString(coveragemap_error Err, const std::string &ErrMsg="")
Definition CoverageMapping.cpp:1623
static unsigned getMaxCounterID(const CounterMappingContext &Ctx, const CoverageMappingRecord &Record)
Definition CoverageMapping.cpp:635
This file defines the DenseMap class.
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
This file implements the SmallBitVector 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.
Implements a dense probed hash-table based set.
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.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
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.
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< 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)
iterator insert(iterator I, T &&Elt)
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)
LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that subtracts RHS from LHS.
Definition CoverageMapping.cpp:132
LLVM_ABI Counter add(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that adds LHS and RHS.
Definition CoverageMapping.cpp:127
LLVM_ABI Counter subst(Counter C, const SubstMap &Map)
Definition CoverageMapping.cpp:138
std::map< Counter, Counter > SubstMap
K to V map.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
LLVM_ABI Expected< MCDCRecord > evaluateMCDCRegion(const CounterMappingRegion &Region, ArrayRef< const CounterMappingRegion * > Branches, bool IsVersion11)
Return an MCDC record that indicates executed test vectors and condition pairs.
Definition CoverageMapping.cpp:554
LLVM_ABI Expected< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed.
Definition CoverageMapping.cpp:193
LLVM_ABI unsigned getMaxCounterID(const Counter &C) const
Definition CoverageMapping.cpp:562
LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const
Definition CoverageMapping.cpp:163
Coverage information to be processed or displayed.
std::string message() const override
Return the error message as a string.
Definition CoverageMapping.cpp:1676
coveragemap_error get() const
const std::string & getMessage() const
static LLVM_ABI Expected< std::unique_ptr< CoverageMapping > > load(ArrayRef< std::unique_ptr< CoverageMappingReader > > CoverageReaders, std::optional< std::reference_wrapper< IndexedInstrProfReader > > &ProfileReader)
Load the coverage mapping using the given readers.
Definition CoverageMapping.cpp:992
LLVM_ABI std::vector< StringRef > getUniqueSourceFiles() const
Returns a lexicographically sorted, unique list of files that are covered.
Definition CoverageMapping.cpp:1399
LLVM_ABI CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const
Get the coverage for an expansion within a coverage set.
Definition CoverageMapping.cpp:1539
iterator_range< FunctionRecordIterator > getCoveredFunctions() const
Gets all of the functions covered by this profile.
LLVM_ABI CoverageData getCoverageForFunction(const FunctionRecord &Function) const
Get the coverage for a particular function.
Definition CoverageMapping.cpp:1507
LLVM_ABI std::vector< InstantiationGroup > getInstantiationGroups(StringRef Filename) const
Get the list of function instantiation groups in a particular file.
Definition CoverageMapping.cpp:1482
LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const
Get the coverage for a particular file.
Definition CoverageMapping.cpp:1446
Iterator over Functions, optionally filtered to a single file.
An instantiation group contains a FunctionRecord list, such that each record corresponds to a distinc...
LineCoverageIterator(const CoverageData &CD)
LLVM_ABI LineCoverageIterator & operator++()
Definition CoverageMapping.cpp:1607
Coverage statistics for a single line.
auto getIndex() const
Equivalent to buildTestVector's Index.
void set(int I, CondState Val)
Set the condition Val at position I.
Compute TestVector Indices "TVIdx" from the Conds graph.
static constexpr auto HardMaxTVs
Hard limit of test vectors.
LLVM_ABI TVIdxBuilder(const SmallVectorImpl< ConditionIDs > &NextIDs, int Offset=0)
Calculate and assign Indices.
Definition CoverageMapping.cpp:283
SmallVector< std::array< int, 2 > > Indices
Output: Index for TestVectors bitmap (These are not CondIDs)
int NumTestVectors
Output: The number of test vectors.
SmallVector< MCDCNode > SavedNodes
This is no longer needed after the assignment.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
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.
@ Skipped
Validation was skipped, as it was not needed.
int16_t ConditionID
The ID for MCDCBranch.
std::array< ConditionID, 2 > ConditionIDs
LLVM_ABI const std::error_category & coveragemap_category()
Definition CoverageMapping.cpp:1680
std::pair< unsigned, unsigned > LineColPair
@ invalid_or_missing_arch_specifier
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
ArrayRef< uint8_t > BuildIDRef
A reference to a BuildID 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 size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
LLVM_ABI StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName="")
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 range R to container C.
auto unique(Range &&R, Predicate P)
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
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI 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.
A Counter mapping region associates a source range with a specific counter.
@ 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.
ArrayRef< CounterExpression > Expressions
ArrayRef< CounterMappingRegion > MappingRegions
ArrayRef< StringRef > Filenames
The execution count information starting at a point in a file.
Coverage information for a macro expansion or included file.
Code coverage information for a single function.
llvm::SmallVector< std::pair< TestVector, CondState > > TestVectors
LLVM_ABI void findIndependencePairs()
Definition CoverageMapping.cpp:253
llvm::DenseMap< unsigned, unsigned > CondIDMap
llvm::DenseMap< unsigned, LineColPair > LineColPairMap
std::array< BitVector, 2 > BoolVector
llvm::DenseMap< unsigned, TVRowPair > TVPairMap
uint16_t NumConditions
Number of Conditions used for a Decision Region.