LLVM 20.0.0git
CoverageMapping.h
Go to the documentation of this file.
1//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Code coverage mapping data is generated by clang and read by
10// llvm-cov to show code coverage statistics for a file.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
15#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
16
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/BitVector.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/DenseSet.h"
21#include "llvm/ADT/Hashing.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/ADT/iterator.h"
25#include "llvm/Object/BuildID.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/Endian.h"
32#include "llvm/Support/Error.h"
34#include <cassert>
35#include <cstdint>
36#include <iterator>
37#include <memory>
38#include <sstream>
39#include <string>
40#include <system_error>
41#include <utility>
42#include <vector>
43
44namespace llvm {
45
46class IndexedInstrProfReader;
47
48namespace object {
49class BuildIDFetcher;
50} // namespace object
51
52namespace vfs {
53class FileSystem;
54} // namespace vfs
55
56namespace coverage {
57
60
62 success = 0,
63 eof,
70};
71
72const std::error_category &coveragemap_category();
73
74inline std::error_code make_error_code(coveragemap_error E) {
75 return std::error_code(static_cast<int>(E), coveragemap_category());
76}
77
78class CoverageMapError : public ErrorInfo<CoverageMapError> {
79public:
81 : Err(Err), Msg(ErrStr.str()) {
82 assert(Err != coveragemap_error::success && "Not an error");
83 }
84
85 std::string message() const override;
86
87 void log(raw_ostream &OS) const override { OS << message(); }
88
89 std::error_code convertToErrorCode() const override {
90 return make_error_code(Err);
91 }
92
93 coveragemap_error get() const { return Err; }
94 const std::string &getMessage() const { return Msg; }
95
96 static char ID;
97
98private:
100 std::string Msg;
101};
102
103/// A Counter is an abstract value that describes how to compute the
104/// execution count for a region of code using the collected profile count data.
105struct Counter {
106 /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
107 /// the CounterKind. This means CounterKind has to leave bit 0 free.
109 static const unsigned EncodingTagBits = 2;
110 static const unsigned EncodingTagMask = 0x3;
112 EncodingTagBits + 1;
113
114private:
115 CounterKind Kind = Zero;
116 unsigned ID = 0;
117
118 Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
119
120public:
121 Counter() = default;
122
123 CounterKind getKind() const { return Kind; }
124
125 bool isZero() const { return Kind == Zero; }
126
127 bool isExpression() const { return Kind == Expression; }
128
129 unsigned getCounterID() const { return ID; }
130
131 unsigned getExpressionID() const { return ID; }
132
133 friend bool operator==(const Counter &LHS, const Counter &RHS) {
134 return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
135 }
136
137 friend bool operator!=(const Counter &LHS, const Counter &RHS) {
138 return !(LHS == RHS);
139 }
140
141 friend bool operator<(const Counter &LHS, const Counter &RHS) {
142 return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
143 }
144
145 /// Return the counter that represents the number zero.
146 static Counter getZero() { return Counter(); }
147
148 /// Return the counter that corresponds to a specific profile counter.
149 static Counter getCounter(unsigned CounterId) {
150 return Counter(CounterValueReference, CounterId);
151 }
152
153 /// Return the counter that corresponds to a specific addition counter
154 /// expression.
155 static Counter getExpression(unsigned ExpressionId) {
156 return Counter(Expression, ExpressionId);
157 }
158};
159
160/// A Counter expression is a value that represents an arithmetic operation
161/// with two counters.
166
168 : Kind(Kind), LHS(LHS), RHS(RHS) {}
169};
170
171/// A Counter expression builder is used to construct the counter expressions.
172/// It avoids unnecessary duplication and simplifies algebraic expressions.
174 /// A list of all the counter expressions
175 std::vector<CounterExpression> Expressions;
176
177 /// A lookup table for the index of a given expression.
179
180 /// Return the counter which corresponds to the given expression.
181 ///
182 /// If the given expression is already stored in the builder, a counter
183 /// that references that expression is returned. Otherwise, the given
184 /// expression is added to the builder's collection of expressions.
185 Counter get(const CounterExpression &E);
186
187 /// Represents a term in a counter expression tree.
188 struct Term {
189 unsigned CounterID;
190 int Factor;
191
192 Term(unsigned CounterID, int Factor)
193 : CounterID(CounterID), Factor(Factor) {}
194 };
195
196 /// Gather the terms of the expression tree for processing.
197 ///
198 /// This collects each addition and subtraction referenced by the counter into
199 /// a sequence that can be sorted and combined to build a simplified counter
200 /// expression.
201 void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms);
202
203 /// Simplifies the given expression tree
204 /// by getting rid of algebraically redundant operations.
205 Counter simplify(Counter ExpressionTree);
206
207public:
208 ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
209
210 /// Return a counter that represents the expression that adds LHS and RHS.
211 Counter add(Counter LHS, Counter RHS, bool Simplify = true);
212
213 /// Return a counter that represents the expression that subtracts RHS from
214 /// LHS.
215 Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
216};
217
218using LineColPair = std::pair<unsigned, unsigned>;
219
220/// A Counter mapping region associates a source range with a specific counter.
223 /// A CodeRegion associates some code with a counter
225
226 /// An ExpansionRegion represents a file expansion region that associates
227 /// a source range with the expansion of a virtual source file, such as
228 /// for a macro instantiation or #include file.
230
231 /// A SkippedRegion represents a source range with code that was skipped
232 /// by a preprocessor or similar means.
234
235 /// A GapRegion is like a CodeRegion, but its count is only set as the
236 /// line execution count when its the only region in the line.
238
239 /// A BranchRegion represents leaf-level boolean expressions and is
240 /// associated with two counters, each representing the number of times the
241 /// expression evaluates to true or false.
243
244 /// A DecisionRegion represents a top-level boolean expression and is
245 /// associated with a variable length bitmap index and condition number.
247
248 /// A Branch Region can be extended to include IDs to facilitate MC/DC.
250 };
251
252 /// Primary Counter that is also used for Branch Regions (TrueCount).
254
255 /// Secondary Counter used for Branch Regions (FalseCount).
257
258 /// Parameters used for Modified Condition/Decision Coverage
260
261 const auto &getDecisionParams() const {
262 return mcdc::getParams<const mcdc::DecisionParameters>(MCDCParams);
263 }
264
265 const auto &getBranchParams() const {
266 return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
267 }
268
269 unsigned FileID = 0;
270 unsigned ExpandedFileID = 0;
272
274
275 bool isBranch() const {
276 return (Kind == BranchRegion || Kind == MCDCBranchRegion);
277 }
278
280 unsigned LineStart, unsigned ColumnStart,
281 unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
285
287 unsigned ExpandedFileID, unsigned LineStart,
288 unsigned ColumnStart, unsigned LineEnd,
289 unsigned ColumnEnd, RegionKind Kind,
290 const mcdc::Parameters &MCDCParams = std::monostate())
294 Kind(Kind) {}
295
297 unsigned FileID, unsigned LineStart,
298 unsigned ColumnStart, unsigned LineEnd,
299 unsigned ColumnEnd, RegionKind Kind)
302 Kind(Kind) {}
303
306 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
309 }
310
312 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
313 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
317 }
318
320 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
321 unsigned LineEnd, unsigned ColumnEnd) {
324 }
325
328 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
330 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
331 }
332
335 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
336 unsigned ColumnEnd,
337 const mcdc::Parameters &MCDCParams = std::monostate()) {
340 ColumnEnd,
341 (std::get_if<mcdc::BranchParameters>(&MCDCParams) ? MCDCBranchRegion
342 : BranchRegion),
343 MCDCParams);
344 }
345
348 unsigned FileID, unsigned LineStart, unsigned ColumnStart,
349 unsigned LineEnd, unsigned ColumnEnd) {
352 }
353
354 inline LineColPair startLoc() const {
356 }
357
358 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); }
359};
360
361/// Associates a source range with an execution count.
367
371
377};
378
379/// MCDC Record grouping all information together.
381 /// CondState represents the evaluation of a condition in an executed test
382 /// vector, which can be True or False. A DontCare is used to mask an
383 /// unevaluatable condition resulting from short-circuit behavior of logical
384 /// operators in languages like C/C++. When comparing the evaluation of a
385 /// condition across executed test vectors, comparisons against a DontCare
386 /// are effectively ignored.
388
389 /// Emulate SmallVector<CondState> with a pair of BitVector.
390 ///
391 /// True False DontCare (Impossible)
392 /// Values: True False False True
393 /// Visited: True True False False
395 BitVector Values; /// True/False (False when DontCare)
396 BitVector Visited; /// ~DontCare
397
398 public:
399 /// Default values are filled with DontCare.
400 TestVector(unsigned N) : Values(N), Visited(N) {}
401
402 /// Emulate RHS SmallVector::operator[]
403 CondState operator[](int I) const {
404 return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False)
405 : MCDC_DontCare);
406 }
407
408 /// Equivalent to buildTestVector's Index.
409 auto getIndex() const { return Values.getData()[0]; }
410
411 /// Set the condition \p Val at position \p I.
412 /// This emulates LHS SmallVector::operator[].
413 void set(int I, CondState Val) {
414 Visited[I] = (Val != MCDC_DontCare);
415 Values[I] = (Val == MCDC_True);
416 }
417
418 /// Emulate SmallVector::push_back.
420 Visited.push_back(Val != MCDC_DontCare);
421 Values.push_back(Val == MCDC_True);
422 assert(Values.size() == Visited.size());
423 }
424
425 /// For each element:
426 /// - False if either is DontCare
427 /// - False if both have the same value
428 /// - True if both have the opposite value
429 /// ((A.Values ^ B.Values) & A.Visited & B.Visited)
430 /// Dedicated to findIndependencePairs().
431 auto getDifferences(const TestVector &B) const {
432 const auto &A = *this;
433 BitVector AB = A.Values;
434 AB ^= B.Values;
435 AB &= A.Visited;
436 AB &= B.Visited;
437 return AB;
438 }
439 };
440
442 using BoolVector = std::array<BitVector, 2>;
443 using TVRowPair = std::pair<unsigned, unsigned>;
447
448private:
450 TestVectors TV;
451 TVPairMap IndependencePairs;
452 BoolVector Folded;
453 CondIDMap PosToID;
454 LineColPairMap CondLoc;
455
456public:
458 TVPairMap &&IndependencePairs, BoolVector &&Folded,
459 CondIDMap &&PosToID, LineColPairMap &&CondLoc)
460 : Region(Region), TV(std::move(TV)),
461 IndependencePairs(std::move(IndependencePairs)),
462 Folded(std::move(Folded)), PosToID(std::move(PosToID)),
463 CondLoc(std::move(CondLoc)){};
464
466 unsigned getNumConditions() const {
467 return Region.getDecisionParams().NumConditions;
468 }
469 unsigned getNumTestVectors() const { return TV.size(); }
470 bool isCondFolded(unsigned Condition) const {
471 return Folded[false][Condition] || Folded[true][Condition];
472 }
473
474 /// Return the evaluation of a condition (indicated by Condition) in an
475 /// executed test vector (indicated by TestVectorIndex), which will be True,
476 /// False, or DontCare if the condition is unevaluatable. Because condition
477 /// IDs are not associated based on their position in the expression,
478 /// accessing conditions in the TestVectors requires a translation from a
479 /// ordinal position to actual condition ID. This is done via PosToID[].
480 CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) {
481 return TV[TestVectorIndex].first[PosToID[Condition]];
482 }
483
484 /// Return the Result evaluation for an executed test vector.
485 /// See MCDCRecordProcessor::RecordTestVector().
486 CondState getTVResult(unsigned TestVectorIndex) {
487 return TV[TestVectorIndex].second;
488 }
489
490 /// Determine whether a given condition (indicated by Condition) is covered
491 /// by an Independence Pair. Because condition IDs are not associated based
492 /// on their position in the expression, accessing conditions in the
493 /// TestVectors requires a translation from a ordinal position to actual
494 /// condition ID. This is done via PosToID[].
495 bool isConditionIndependencePairCovered(unsigned Condition) const {
496 auto It = PosToID.find(Condition);
497 if (It != PosToID.end())
498 return IndependencePairs.contains(It->second);
499 llvm_unreachable("Condition ID without an Ordinal mapping");
500 }
501
502 /// Return the Independence Pair that covers the given condition. Because
503 /// condition IDs are not associated based on their position in the
504 /// expression, accessing conditions in the TestVectors requires a
505 /// translation from a ordinal position to actual condition ID. This is done
506 /// via PosToID[].
509 return IndependencePairs[PosToID[Condition]];
510 }
511
512 float getPercentCovered() const {
513 unsigned Folded = 0;
514 unsigned Covered = 0;
515 for (unsigned C = 0; C < getNumConditions(); C++) {
516 if (isCondFolded(C))
517 Folded++;
519 Covered++;
520 }
521
522 unsigned Total = getNumConditions() - Folded;
523 if (Total == 0)
524 return 0.0;
525 return (static_cast<double>(Covered) / static_cast<double>(Total)) * 100.0;
526 }
527
528 std::string getConditionHeaderString(unsigned Condition) {
529 std::ostringstream OS;
530 OS << "Condition C" << Condition + 1 << " --> (";
531 OS << CondLoc[Condition].first << ":" << CondLoc[Condition].second;
532 OS << ")\n";
533 return OS.str();
534 }
535
536 std::string getTestVectorHeaderString() const {
537 std::ostringstream OS;
538 if (getNumTestVectors() == 0) {
539 OS << "None.\n";
540 return OS.str();
541 }
542 const auto NumConditions = getNumConditions();
543 for (unsigned I = 0; I < NumConditions; I++) {
544 OS << "C" << I + 1;
545 if (I != NumConditions - 1)
546 OS << ", ";
547 }
548 OS << " Result\n";
549 return OS.str();
550 }
551
552 std::string getTestVectorString(unsigned TestVectorIndex) {
553 assert(TestVectorIndex < getNumTestVectors() &&
554 "TestVector index out of bounds!");
555 std::ostringstream OS;
556 const auto NumConditions = getNumConditions();
557 // Add individual condition values to the string.
558 OS << " " << TestVectorIndex + 1 << " { ";
559 for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
560 if (isCondFolded(Condition))
561 OS << "C";
562 else {
563 switch (getTVCondition(TestVectorIndex, Condition)) {
565 OS << "-";
566 break;
568 OS << "T";
569 break;
571 OS << "F";
572 break;
573 }
574 }
575 if (Condition != NumConditions - 1)
576 OS << ", ";
577 }
578
579 // Add result value to the string.
580 OS << " = ";
581 if (getTVResult(TestVectorIndex) == MCDC_True)
582 OS << "T";
583 else
584 OS << "F";
585 OS << " }\n";
586
587 return OS.str();
588 }
589
590 std::string getConditionCoverageString(unsigned Condition) {
591 assert(Condition < getNumConditions() &&
592 "Condition index is out of bounds!");
593 std::ostringstream OS;
594
595 OS << " C" << Condition + 1 << "-Pair: ";
596 if (isCondFolded(Condition)) {
597 OS << "constant folded\n";
598 } else if (isConditionIndependencePairCovered(Condition)) {
599 TVRowPair rows = getConditionIndependencePair(Condition);
600 OS << "covered: (" << rows.first << ",";
601 OS << rows.second << ")\n";
602 } else
603 OS << "not covered\n";
604
605 return OS.str();
606 }
607};
608
609namespace mcdc {
610/// Compute TestVector Indices "TVIdx" from the Conds graph.
611///
612/// Clang CodeGen handles the bitmap index based on TVIdx.
613/// llvm-cov reconstructs conditions from TVIdx.
614///
615/// For each leaf "The final decision",
616/// - TVIdx should be unique.
617/// - TVIdx has the Width.
618/// - The width represents the number of possible paths.
619/// - The minimum width is 1 "deterministic".
620/// - The order of leaves are sorted by Width DESC. It expects
621/// latter TVIdx(s) (with Width=1) could be pruned and altered to
622/// other simple branch conditions.
623///
625public:
626 struct MCDCNode {
627 int InCount = 0; /// Reference count; temporary use
628 int Width; /// Number of accumulated paths (>= 1)
630 };
631
632#ifndef NDEBUG
633 /// This is no longer needed after the assignment.
634 /// It may be used in assert() for reconfirmation.
636#endif
637
638 /// Output: Index for TestVectors bitmap (These are not CondIDs)
640
641 /// Output: The number of test vectors.
642 /// Error with HardMaxTVs if the number has exploded.
644
645 /// Hard limit of test vectors
646 static constexpr auto HardMaxTVs =
647 std::numeric_limits<decltype(NumTestVectors)>::max();
648
649public:
650 /// Calculate and assign Indices
651 /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
652 /// The first element [0] should be the root node.
653 /// \param Offset Offset of index to final decisions.
654 TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs, int Offset = 0);
655};
656} // namespace mcdc
657
658/// A Counter mapping context is used to connect the counters, expressions
659/// and the obtained counter values.
661 ArrayRef<CounterExpression> Expressions;
662 ArrayRef<uint64_t> CounterValues;
663 BitVector Bitmap;
664
665public:
667 ArrayRef<uint64_t> CounterValues = {})
668 : Expressions(Expressions), CounterValues(CounterValues) {}
669
670 void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
671 void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); }
672
673 void dump(const Counter &C, raw_ostream &OS) const;
674 void dump(const Counter &C) const { dump(C, dbgs()); }
675
676 /// Return the number of times that a region of code associated with this
677 /// counter was executed.
678 Expected<int64_t> evaluate(const Counter &C) const;
679
680 /// Return an MCDC record that indicates executed test vectors and condition
681 /// pairs.
685 bool IsVersion11);
686
687 unsigned getMaxCounterID(const Counter &C) const;
688};
689
690/// Code coverage information for a single function.
692 /// Raw function name.
693 std::string Name;
694 /// Mapping from FileID (i.e. vector index) to filename. Used to support
695 /// macro expansions within a function in which the macro and function are
696 /// defined in separate files.
697 ///
698 /// TODO: Uniquing filenames across all function records may be a performance
699 /// optimization.
700 std::vector<std::string> Filenames;
701 /// Regions in the function along with their counts.
702 std::vector<CountedRegion> CountedRegions;
703 /// Branch Regions in the function along with their counts.
704 std::vector<CountedRegion> CountedBranchRegions;
705 /// MCDC Records record a DecisionRegion and associated BranchRegions.
706 std::vector<MCDCRecord> MCDCRecords;
707 /// The number of times this function was executed.
709
711 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
712
715
717 MCDCRecords.push_back(std::move(Record));
718 }
719
721 uint64_t FalseCount) {
722 if (Region.isBranch()) {
723 CountedBranchRegions.emplace_back(Region, Count, FalseCount);
724 // If either counter is hard-coded to zero, then this region represents a
725 // constant-folded branch.
726 CountedBranchRegions.back().TrueFolded = Region.Count.isZero();
727 CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero();
728 return;
729 }
730 if (CountedRegions.empty())
731 ExecutionCount = Count;
732 CountedRegions.emplace_back(Region, Count, FalseCount);
733 }
734};
735
736/// Iterator over Functions, optionally filtered to a single file.
738 : public iterator_facade_base<FunctionRecordIterator,
739 std::forward_iterator_tag, FunctionRecord> {
742 StringRef Filename;
743
744 /// Skip records whose primary file is not \c Filename.
745 void skipOtherFiles();
746
747public:
749 StringRef Filename = "")
750 : Records(Records_), Current(Records.begin()), Filename(Filename) {
751 skipOtherFiles();
752 }
753
754 FunctionRecordIterator() : Current(Records.begin()) {}
755
757 return Current == RHS.Current && Filename == RHS.Filename;
758 }
759
760 const FunctionRecord &operator*() const { return *Current; }
761
763 assert(Current != Records.end() && "incremented past end");
764 ++Current;
765 skipOtherFiles();
766 return *this;
767 }
768};
769
770/// Coverage information for a macro expansion or #included file.
771///
772/// When covered code has pieces that can be expanded for more detail, such as a
773/// preprocessor macro use and its definition, these are represented as
774/// expansions whose coverage can be looked up independently.
776 /// The abstract file this expansion covers.
777 unsigned FileID;
778 /// The region that expands to this record.
780 /// Coverage for the expansion.
782
785 : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
786};
787
788/// The execution count information starting at a point in a file.
789///
790/// A sequence of CoverageSegments gives execution counts for a file in format
791/// that's simple to iterate through for processing.
793 /// The line where this segment begins.
794 unsigned Line;
795 /// The column where this segment begins.
796 unsigned Col;
797 /// The execution count, or zero if no count was recorded.
799 /// When false, the segment was uninstrumented or skipped.
801 /// Whether this enters a new region or returns to a previous count.
803 /// Whether this enters a gap region.
805
806 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
807 : Line(Line), Col(Col), Count(0), HasCount(false),
809
810 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
811 bool IsRegionEntry, bool IsGapRegion = false,
812 bool IsBranchRegion = false)
815
816 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
817 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry,
818 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count,
819 R.HasCount, R.IsRegionEntry,
820 R.IsGapRegion);
821 }
822};
823
824/// An instantiation group contains a \c FunctionRecord list, such that each
825/// record corresponds to a distinct instantiation of the same function.
826///
827/// Note that it's possible for a function to have more than one instantiation
828/// (consider C++ template specializations or static inline functions).
830 friend class CoverageMapping;
831
832 unsigned Line;
833 unsigned Col;
834 std::vector<const FunctionRecord *> Instantiations;
835
836 InstantiationGroup(unsigned Line, unsigned Col,
837 std::vector<const FunctionRecord *> Instantiations)
838 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {}
839
840public:
843
844 /// Get the number of instantiations in this group.
845 size_t size() const { return Instantiations.size(); }
846
847 /// Get the line where the common function was defined.
848 unsigned getLine() const { return Line; }
849
850 /// Get the column where the common function was defined.
851 unsigned getColumn() const { return Col; }
852
853 /// Check if the instantiations in this group have a common mangled name.
854 bool hasName() const {
855 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I)
856 if (Instantiations[I]->Name != Instantiations[0]->Name)
857 return false;
858 return true;
859 }
860
861 /// Get the common mangled name for instantiations in this group.
863 assert(hasName() && "Instantiations don't have a shared name");
864 return Instantiations[0]->Name;
865 }
866
867 /// Get the total execution count of all instantiations in this group.
869 uint64_t Count = 0;
870 for (const FunctionRecord *F : Instantiations)
871 Count += F->ExecutionCount;
872 return Count;
873 }
874
875 /// Get the instantiations in this group.
877 return Instantiations;
878 }
879};
880
881/// Coverage information to be processed or displayed.
882///
883/// This represents the coverage of an entire file, expansion, or function. It
884/// provides a sequence of CoverageSegments to iterate through, as well as the
885/// list of expansions that can be further processed.
887 friend class CoverageMapping;
888
889 std::string Filename;
890 std::vector<CoverageSegment> Segments;
891 std::vector<ExpansionRecord> Expansions;
892 std::vector<CountedRegion> BranchRegions;
893 std::vector<MCDCRecord> MCDCRecords;
894
895 bool SingleByteCoverage = false;
896
897public:
898 CoverageData() = default;
899
900 CoverageData(bool Single, StringRef Filename)
901 : Filename(Filename), SingleByteCoverage(Single) {}
902
903 /// Get the name of the file this data covers.
904 StringRef getFilename() const { return Filename; }
905
907
908 /// Get an iterator over the coverage segments for this object. The segments
909 /// are guaranteed to be uniqued and sorted by location.
910 std::vector<CoverageSegment>::const_iterator begin() const {
911 return Segments.begin();
912 }
913
914 std::vector<CoverageSegment>::const_iterator end() const {
915 return Segments.end();
916 }
917
918 bool empty() const { return Segments.empty(); }
919
920 /// Expansions that can be further processed.
921 ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
922
923 /// Branches that can be further processed.
924 ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
925
926 /// MCDC Records that can be further processed.
927 ArrayRef<MCDCRecord> getMCDCRecords() const { return MCDCRecords; }
928};
929
930/// The mapping of profile information to coverage data.
931///
932/// This is the main interface to get coverage information, using a profile to
933/// fill out execution counts.
935 DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
936 std::vector<FunctionRecord> Functions;
937 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
938 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
939
940 std::optional<bool> SingleByteCoverage;
941
942 CoverageMapping() = default;
943
944 // Load coverage records from readers.
945 static Error loadFromReaders(
946 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
947 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage);
948
949 // Load coverage records from file.
950 static Error
951 loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
952 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage,
953 bool &DataFound,
954 SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
955
956 /// Add a function record corresponding to \p Record.
957 Error loadFunctionRecord(const CoverageMappingRecord &Record,
958 IndexedInstrProfReader &ProfileReader);
959
960 /// Look up the indices for function records which are at least partially
961 /// defined in the specified file. This is guaranteed to return a superset of
962 /// such records: extra records not in the file may be included if there is
963 /// a hash collision on the filename. Clients must be robust to collisions.
965 getImpreciseRecordIndicesForFilename(StringRef Filename) const;
966
967public:
970
971 /// Load the coverage mapping using the given readers.
973 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
974 IndexedInstrProfReader &ProfileReader);
975
976 /// Load the coverage mapping from the given object files and profile. If
977 /// \p Arches is non-empty, it must specify an architecture for each object.
978 /// Ignores non-instrumented object files unless all are not instrumented.
980 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
981 vfs::FileSystem &FS, ArrayRef<StringRef> Arches = {},
982 StringRef CompilationDir = "",
983 const object::BuildIDFetcher *BIDFetcher = nullptr,
984 bool CheckBinaryIDs = false);
985
986 /// The number of functions that couldn't have their profiles mapped.
987 ///
988 /// This is a count of functions whose profile is out of date or otherwise
989 /// can't be associated with any coverage information.
990 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
991
992 /// A hash mismatch occurs when a profile record for a symbol does not have
993 /// the same hash as a coverage mapping record for the same symbol. This
994 /// returns a list of hash mismatches, where each mismatch is a pair of the
995 /// symbol name and its coverage mapping hash.
997 return FuncHashMismatches;
998 }
999
1000 /// Returns a lexicographically sorted, unique list of files that are
1001 /// covered.
1002 std::vector<StringRef> getUniqueSourceFiles() const;
1003
1004 /// Get the coverage for a particular file.
1005 ///
1006 /// The given filename must be the name as recorded in the coverage
1007 /// information. That is, only names returned from getUniqueSourceFiles will
1008 /// yield a result.
1010
1011 /// Get the coverage for a particular function.
1013
1014 /// Get the coverage for an expansion within a coverage set.
1016
1017 /// Gets all of the functions covered by this profile.
1019 return make_range(FunctionRecordIterator(Functions),
1021 }
1022
1023 /// Gets all of the functions in a particular file.
1026 return make_range(FunctionRecordIterator(Functions, Filename),
1028 }
1029
1030 /// Get the list of function instantiation groups in a particular file.
1031 ///
1032 /// Every instantiation group in a program is attributed to exactly one file:
1033 /// the file in which the definition for the common function begins.
1034 std::vector<InstantiationGroup>
1035 getInstantiationGroups(StringRef Filename) const;
1036};
1037
1038/// Coverage statistics for a single line.
1040 uint64_t ExecutionCount;
1041 bool HasMultipleRegions;
1042 bool Mapped;
1043 unsigned Line;
1045 const CoverageSegment *WrappedSegment;
1046
1048 LineCoverageStats() = default;
1049
1050public:
1052 const CoverageSegment *WrappedSegment, unsigned Line);
1053
1054 uint64_t getExecutionCount() const { return ExecutionCount; }
1055
1056 bool hasMultipleRegions() const { return HasMultipleRegions; }
1057
1058 bool isMapped() const { return Mapped; }
1059
1060 unsigned getLine() const { return Line; }
1061
1063 return LineSegments;
1064 }
1065
1066 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
1067};
1068
1069/// An iterator over the \c LineCoverageStats objects for lines described by
1070/// a \c CoverageData instance.
1072 : public iterator_facade_base<LineCoverageIterator,
1073 std::forward_iterator_tag,
1074 const LineCoverageStats> {
1075public:
1077 : LineCoverageIterator(CD, CD.begin()->Line) {}
1078
1079 LineCoverageIterator(const CoverageData &CD, unsigned Line)
1080 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
1081 Line(Line) {
1082 this->operator++();
1083 }
1084
1085 bool operator==(const LineCoverageIterator &R) const {
1086 return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
1087 }
1088
1089 const LineCoverageStats &operator*() const { return Stats; }
1090
1092
1094 auto EndIt = *this;
1095 EndIt.Next = CD.end();
1096 EndIt.Ended = true;
1097 return EndIt;
1098 }
1099
1100private:
1101 const CoverageData &CD;
1102 const CoverageSegment *WrappedSegment;
1103 std::vector<CoverageSegment>::const_iterator Next;
1104 bool Ended;
1105 unsigned Line;
1107 LineCoverageStats Stats;
1108};
1109
1110/// Get a \c LineCoverageIterator range for the lines described by \p CD.
1113 auto Begin = LineCoverageIterator(CD);
1114 auto End = Begin.getEnd();
1115 return make_range(Begin, End);
1116}
1117
1118// Coverage mappping data (V2) has the following layout:
1119// IPSK_covmap:
1120// [CoverageMapFileHeader]
1121// [ArrayStart]
1122// [CovMapFunctionRecordV2]
1123// [CovMapFunctionRecordV2]
1124// ...
1125// [ArrayEnd]
1126// [Encoded Filenames and Region Mapping Data]
1127//
1128// Coverage mappping data (V3) has the following layout:
1129// IPSK_covmap:
1130// [CoverageMapFileHeader]
1131// [Encoded Filenames]
1132// IPSK_covfun:
1133// [ArrayStart]
1134// odr_name_1: [CovMapFunctionRecordV3]
1135// odr_name_2: [CovMapFunctionRecordV3]
1136// ...
1137// [ArrayEnd]
1138//
1139// Both versions of the coverage mapping format encode the same information,
1140// but the V3 format does so more compactly by taking advantage of linkonce_odr
1141// semantics (it allows exactly 1 function record per name reference).
1142
1143/// This namespace defines accessors shared by different versions of coverage
1144/// mapping records.
1145namespace accessors {
1146
1147/// Return the structural hash associated with the function.
1148template <class FuncRecordTy, llvm::endianness Endian>
1149uint64_t getFuncHash(const FuncRecordTy *Record) {
1150 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
1151}
1152
1153/// Return the coverage map data size for the function.
1154template <class FuncRecordTy, llvm::endianness Endian>
1155uint64_t getDataSize(const FuncRecordTy *Record) {
1156 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
1157}
1158
1159/// Return the function lookup key. The value is considered opaque.
1160template <class FuncRecordTy, llvm::endianness Endian>
1161uint64_t getFuncNameRef(const FuncRecordTy *Record) {
1162 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
1163}
1164
1165/// Return the PGO name of the function. Used for formats in which the name is
1166/// a hash.
1167template <class FuncRecordTy, llvm::endianness Endian>
1168Error getFuncNameViaRef(const FuncRecordTy *Record,
1169 InstrProfSymtab &ProfileNames, StringRef &FuncName) {
1170 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
1171 FuncName = ProfileNames.getFuncOrVarName(NameRef);
1172 return Error::success();
1173}
1174
1175/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
1176/// coverage mapping is attached to the file header, instead of to the function
1177/// record.
1178template <class FuncRecordTy, llvm::endianness Endian>
1180 const char *MappingBuf) {
1181 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
1182}
1183
1184/// Advance to the next out-of-line coverage mapping and its associated
1185/// function record.
1186template <class FuncRecordTy, llvm::endianness Endian>
1187std::pair<const char *, const FuncRecordTy *>
1188advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
1189 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
1190}
1191
1192} // end namespace accessors
1193
1195template <class IntPtrT>
1198
1199#define COVMAP_V1
1200#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1202#undef COVMAP_V1
1204
1205 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1206 return accessors::getFuncHash<ThisT, Endian>(this);
1207 }
1208
1209 template <llvm::endianness Endian> uint64_t getDataSize() const {
1210 return accessors::getDataSize<ThisT, Endian>(this);
1211 }
1212
1213 /// Return function lookup key. The value is consider opaque.
1214 template <llvm::endianness Endian> IntPtrT getFuncNameRef() const {
1215 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
1216 }
1217
1218 /// Return the PGO name of the function.
1219 template <llvm::endianness Endian>
1220 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1221 IntPtrT NameRef = getFuncNameRef<Endian>();
1222 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
1223 FuncName = ProfileNames.getFuncName(NameRef, NameS);
1224 if (NameS && FuncName.empty())
1225 return make_error<CoverageMapError>(coveragemap_error::malformed,
1226 "function name is empty");
1227 return Error::success();
1228 }
1229
1230 template <llvm::endianness Endian>
1231 std::pair<const char *, const ThisT *>
1232 advanceByOne(const char *MappingBuf) const {
1233 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1234 }
1235
1236 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1237 llvm_unreachable("V1 function format does not contain a filenames ref");
1238 }
1239
1240 template <llvm::endianness Endian>
1241 StringRef getCoverageMapping(const char *MappingBuf) const {
1242 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1243 MappingBuf);
1244 }
1245};
1246
1249
1250#define COVMAP_V2
1251#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1253#undef COVMAP_V2
1255
1256 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1257 return accessors::getFuncHash<ThisT, Endian>(this);
1258 }
1259
1260 template <llvm::endianness Endian> uint64_t getDataSize() const {
1261 return accessors::getDataSize<ThisT, Endian>(this);
1262 }
1263
1264 template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1265 return accessors::getFuncNameRef<ThisT, Endian>(this);
1266 }
1267
1268 template <llvm::endianness Endian>
1269 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1270 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1271 FuncName);
1272 }
1273
1274 template <llvm::endianness Endian>
1275 std::pair<const char *, const ThisT *>
1276 advanceByOne(const char *MappingBuf) const {
1277 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1278 }
1279
1280 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1281 llvm_unreachable("V2 function format does not contain a filenames ref");
1282 }
1283
1284 template <llvm::endianness Endian>
1285 StringRef getCoverageMapping(const char *MappingBuf) const {
1286 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1287 MappingBuf);
1288 }
1289};
1290
1293
1294#define COVMAP_V3
1295#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1297#undef COVMAP_V3
1299
1300 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1301 return accessors::getFuncHash<ThisT, Endian>(this);
1302 }
1303
1304 template <llvm::endianness Endian> uint64_t getDataSize() const {
1305 return accessors::getDataSize<ThisT, Endian>(this);
1306 }
1307
1308 template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1309 return accessors::getFuncNameRef<ThisT, Endian>(this);
1310 }
1311
1312 template <llvm::endianness Endian>
1313 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1314 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1315 FuncName);
1316 }
1317
1318 /// Get the filename set reference.
1319 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1320 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
1321 }
1322
1323 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
1324 /// out-of-line coverage mapping data only.
1325 template <llvm::endianness Endian>
1326 StringRef getCoverageMapping(const char *) const {
1327 return StringRef(&CoverageMapping, getDataSize<Endian>());
1328 }
1329
1330 // Advance to the next inline coverage mapping and its associated function
1331 // record. Ignore the out-of-line coverage mapping buffer.
1332 template <llvm::endianness Endian>
1333 std::pair<const char *, const CovMapFunctionRecordV3 *>
1334 advanceByOne(const char *) const {
1335 assert(isAddrAligned(Align(8), this) && "Function record not aligned");
1336 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
1337 sizeof(char) + getDataSize<Endian>();
1338 // Each function record has an alignment of 8, so we need to adjust
1339 // alignment before reading the next record.
1340 Next += offsetToAlignedAddr(Next, Align(8));
1341 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
1342 }
1343};
1344
1345// Per module coverage mapping data header, i.e. CoverageMapFileHeader
1346// documented above.
1348#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
1350 template <llvm::endianness Endian> uint32_t getNRecords() const {
1351 return support::endian::byte_swap<uint32_t, Endian>(NRecords);
1352 }
1353
1354 template <llvm::endianness Endian> uint32_t getFilenamesSize() const {
1355 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
1356 }
1357
1358 template <llvm::endianness Endian> uint32_t getCoverageSize() const {
1359 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
1360 }
1361
1362 template <llvm::endianness Endian> uint32_t getVersion() const {
1363 return support::endian::byte_swap<uint32_t, Endian>(Version);
1364 }
1365};
1366
1368
1371 // Function's name reference from CovMapFuncRecord is changed from raw
1372 // name string pointer to MD5 to support name section compression. Name
1373 // section is also compressed.
1375 // A new interpretation of the columnEnd field is added in order to mark
1376 // regions as gap areas.
1378 // Function records are named, uniqued, and moved to a dedicated section.
1380 // Branch regions referring to two counters are added
1382 // Compilation directory is stored separately and combined with relative
1383 // filenames to produce an absolute file path.
1385 // Branch regions extended and Decision Regions added for MC/DC.
1387 // The current version is Version7.
1388 CurrentVersion = INSTR_PROF_COVMAP_VERSION
1390
1391// Correspond to "llvmcovm", in little-endian.
1392constexpr uint64_t TestingFormatMagic = 0x6d766f636d766c6c;
1393
1395 // The first version's number corresponds to the string "testdata" in
1396 // little-endian. This is for a historical reason.
1397 Version1 = 0x6174616474736574,
1398 // Version1 has a defect that it can't store multiple file records. Version2
1399 // fix this problem by adding a new field before the file records section.
1400 Version2 = 1,
1401 // The current testing format version is Version2.
1403};
1404
1405template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1408};
1409
1410template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1413};
1414
1415template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1418};
1419
1420template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1423};
1424
1425} // end namespace coverage
1426
1427/// Provide DenseMapInfo for CounterExpression
1428template<> struct DenseMapInfo<coverage::CounterExpression> {
1430 using namespace coverage;
1431
1432 return CounterExpression(CounterExpression::ExprKind::Subtract,
1433 Counter::getCounter(~0U),
1434 Counter::getCounter(~0U));
1435 }
1436
1438 using namespace coverage;
1439
1440 return CounterExpression(CounterExpression::ExprKind::Add,
1441 Counter::getCounter(~0U),
1442 Counter::getCounter(~0U));
1443 }
1444
1445 static unsigned getHashValue(const coverage::CounterExpression &V) {
1446 return static_cast<unsigned>(
1447 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
1448 V.RHS.getKind(), V.RHS.getCounterID()));
1449 }
1450
1453 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1454 }
1455};
1456
1457} // end namespace llvm
1458
1459#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
AMDGPU Mark last scratch load
basic Basic Alias true
This file implements the BitVector class.
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")
#define LLVM_PACKED_END
Definition: Compiler.h:516
#define LLVM_PACKED_START
Definition: Compiler.h:515
DXIL Intrinsic Expansion
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
std::string Name
bool End
Definition: ELF_riscv.cpp:480
hexagon bit simplify
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
Value * RHS
Value * LHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
ArrayRef< BitWord > getData() const
Definition: BitVector.h:691
void push_back(bool Val)
Definition: BitVector.h:466
size_type size() const
size - Returns the number of bits in this bitvector.
Definition: BitVector.h:159
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:156
iterator end()
Definition: DenseMap.h:84
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition: DenseMap.h:147
Base class for user error types.
Definition: Error.h:355
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Class representing an expression and its matching format.
Reader for the indexed binary instrprof format.
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Definition: InstrProf.h:460
StringRef getFuncOrVarName(uint64_t ValMD5Hash)
Return name of functions or global variables from the name's md5 hash value.
Definition: InstrProf.h:720
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
A Counter expression builder is used to construct the counter expressions.
ArrayRef< CounterExpression > getExpressions() const
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< MCDCRecord > evaluateMCDCRegion(const CounterMappingRegion &Region, ArrayRef< const CounterMappingRegion * > Branches, bool IsVersion11)
Return an MCDC record that indicates executed test vectors and condition pairs.
void setCounts(ArrayRef< uint64_t > Counts)
void dump(const Counter &C) const
Expected< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed.
void setBitmap(BitVector &&Bitmap_)
unsigned getMaxCounterID(const Counter &C) const
CounterMappingContext(ArrayRef< CounterExpression > Expressions, ArrayRef< uint64_t > CounterValues={})
void dump(const Counter &C, raw_ostream &OS) const
Coverage information to be processed or displayed.
ArrayRef< ExpansionRecord > getExpansions() const
Expansions that can be further processed.
ArrayRef< CountedRegion > getBranches() const
Branches that can be further processed.
std::vector< CoverageSegment >::const_iterator begin() const
Get an iterator over the coverage segments for this object.
std::vector< CoverageSegment >::const_iterator end() const
StringRef getFilename() const
Get the name of the file this data covers.
ArrayRef< MCDCRecord > getMCDCRecords() const
MCDC Records that can be further processed.
CoverageData(bool Single, StringRef Filename)
std::string message() const override
Return the error message as a string.
CoverageMapError(coveragemap_error Err, const Twine &ErrStr=Twine())
void log(raw_ostream &OS) const override
Print an error message to an output stream.
coveragemap_error get() const
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
const std::string & getMessage() const
The mapping of profile information to coverage data.
unsigned getMismatchedCount() const
The number of functions that couldn't have their profiles mapped.
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.
ArrayRef< std::pair< std::string, uint64_t > > getHashMismatches() const
A hash mismatch occurs when a profile record for a symbol does not have the same hash as a coverage m...
iterator_range< FunctionRecordIterator > getCoveredFunctions(StringRef Filename) const
Gets all of the functions in a particular file.
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.
CoverageMapping(const CoverageMapping &)=delete
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.
CoverageMapping & operator=(const CoverageMapping &)=delete
Iterator over Functions, optionally filtered to a single file.
FunctionRecordIterator & operator++()
bool operator==(const FunctionRecordIterator &RHS) const
const FunctionRecord & operator*() const
FunctionRecordIterator(ArrayRef< FunctionRecord > Records_, StringRef Filename="")
An instantiation group contains a FunctionRecord list, such that each record corresponds to a distinc...
InstantiationGroup(const InstantiationGroup &)=delete
unsigned getLine() const
Get the line where the common function was defined.
unsigned getColumn() const
Get the column where the common function was defined.
bool hasName() const
Check if the instantiations in this group have a common mangled name.
size_t size() const
Get the number of instantiations in this group.
ArrayRef< const FunctionRecord * > getInstantiations() const
Get the instantiations in this group.
uint64_t getTotalExecutionCount() const
Get the total execution count of all instantiations in this group.
InstantiationGroup(InstantiationGroup &&)=default
StringRef getName() const
Get the common mangled name for instantiations in this group.
An iterator over the LineCoverageStats objects for lines described by a CoverageData instance.
LineCoverageIterator(const CoverageData &CD)
const LineCoverageStats & operator*() const
bool operator==(const LineCoverageIterator &R) const
LineCoverageIterator getEnd() const
LineCoverageIterator(const CoverageData &CD, unsigned Line)
Coverage statistics for a single line.
const CoverageSegment * getWrappedSegment() const
ArrayRef< const CoverageSegment * > getLineSegments() const
Emulate SmallVector<CondState> with a pair of BitVector.
auto getIndex() const
Equivalent to buildTestVector's Index.
CondState operator[](int I) const
Emulate RHS SmallVector::operator[].
void set(int I, CondState Val)
Set the condition Val at position I.
auto getDifferences(const TestVector &B) const
For each element:
void push_back(CondState Val)
Emulate SmallVector::push_back.
Compute TestVector Indices "TVIdx" from the Conds graph.
static constexpr auto HardMaxTVs
Hard limit of test vectors.
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.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Definition: iterator.h:80
A range adaptor for a pair of iterators.
BuildIDFetcher searches local cache directories for debug info.
Definition: BuildID.h:39
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
The virtual file system interface.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
constexpr size_t NameSize
Definition: XCOFF.h:29
uint64_t getFuncNameRef(const FuncRecordTy *Record)
Return the function lookup key. The value is considered opaque.
StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record, const char *MappingBuf)
Read coverage mapping out-of-line, from MappingBuf.
uint64_t getDataSize(const FuncRecordTy *Record)
Return the coverage map data size for the function.
Error getFuncNameViaRef(const FuncRecordTy *Record, InstrProfSymtab &ProfileNames, StringRef &FuncName)
Return the PGO name of the function.
std::pair< const char *, const FuncRecordTy * > advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf)
Advance to the next out-of-line coverage mapping and its associated function record.
uint64_t getFuncHash(const FuncRecordTy *Record)
Return the structural hash associated with the function.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition: MCDCTypes.h:56
std::array< ConditionID, 2 > ConditionIDs
Definition: MCDCTypes.h:25
const std::error_category & coveragemap_category()
std::error_code make_error_code(coveragemap_error E)
static iterator_range< LineCoverageIterator > getLineCoverageStats(const coverage::CoverageData &CD)
Get a LineCoverageIterator range for the lines described by CD.
constexpr uint64_t TestingFormatMagic
std::pair< unsigned, unsigned > LineColPair
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
@ Offset
Definition: DWP.cpp:480
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment)
Returns the necessary adjustment for aligning Addr to Alignment bytes, rounding up.
Definition: Alignment.h:203
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1873
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:590
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition: Alignment.h:150
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
static coverage::CounterExpression getTombstoneKey()
static bool isEqual(const coverage::CounterExpression &LHS, const coverage::CounterExpression &RHS)
static unsigned getHashValue(const coverage::CounterExpression &V)
static coverage::CounterExpression getEmptyKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:52
Associates a source range with an execution count.
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, uint64_t FalseExecutionCount)
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
A Counter expression is a value that represents an arithmetic operation with two counters.
CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
A Counter mapping region associates a source range with a specific counter.
CounterMappingRegion(const mcdc::DecisionParameters &MCDCParams, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
static CounterMappingRegion makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
static CounterMappingRegion makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind, const mcdc::Parameters &MCDCParams=std::monostate())
static CounterMappingRegion makeRegion(Counter Count, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
static CounterMappingRegion makeDecisionRegion(const mcdc::DecisionParameters &MCDCParams, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
Counter FalseCount
Secondary Counter used for Branch Regions (FalseCount).
static CounterMappingRegion makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
Counter Count
Primary Counter that is also used for Branch Regions (TrueCount).
static CounterMappingRegion makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd, const mcdc::Parameters &MCDCParams=std::monostate())
mcdc::Parameters 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 ...
@ BranchRegion
A BranchRegion represents leaf-level boolean expressions and is associated with two counters,...
@ 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 const unsigned EncodingTagBits
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.
friend bool operator==(const Counter &LHS, const Counter &RHS)
unsigned getCounterID() const
CounterKind
The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to the CounterKind.
unsigned getExpressionID() const
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
CounterKind getKind() const
friend bool operator!=(const Counter &LHS, const Counter &RHS)
friend bool operator<(const Counter &LHS, const Counter &RHS)
static const unsigned EncodingTagMask
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
std::pair< const char *, const ThisT * > advanceByOne(const char *MappingBuf) const
StringRef getCoverageMapping(const char *MappingBuf) const
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const
Return the PGO name of the function.
IntPtrT getFuncNameRef() const
Return function lookup key. The value is consider opaque.
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const
std::pair< const char *, const ThisT * > advanceByOne(const char *MappingBuf) const
StringRef getCoverageMapping(const char *MappingBuf) const
std::pair< const char *, const CovMapFunctionRecordV3 * > advanceByOne(const char *) const
StringRef getCoverageMapping(const char *) const
Read the inline coverage mapping.
uint64_t getFilenamesRef() const
Get the filename set reference.
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const
Coverage mapping information for a single function.
The execution count information starting at a point in a file.
CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
bool HasCount
When false, the segment was uninstrumented or skipped.
unsigned Col
The column where this segment begins.
friend bool operator==(const CoverageSegment &L, const CoverageSegment &R)
bool IsRegionEntry
Whether this enters a new region or returns to a previous count.
uint64_t Count
The execution count, or zero if no count was recorded.
unsigned Line
The line where this segment begins.
CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, bool IsRegionEntry, bool IsGapRegion=false, bool IsBranchRegion=false)
bool IsGapRegion
Whether this enters a gap region.
Coverage information for a macro expansion or #included file.
const CountedRegion & Region
The region that expands to this record.
unsigned FileID
The abstract file this expansion covers.
ExpansionRecord(const CountedRegion &Region, const FunctionRecord &Function)
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::string Name
Raw function name.
std::vector< CountedRegion > CountedRegions
Regions in the function along with their counts.
FunctionRecord & operator=(FunctionRecord &&)=default
void pushMCDCRecord(MCDCRecord &&Record)
std::vector< MCDCRecord > MCDCRecords
MCDC Records record a DecisionRegion and associated BranchRegions.
std::vector< std::string > Filenames
Mapping from FileID (i.e.
FunctionRecord(FunctionRecord &&FR)=default
FunctionRecord(StringRef Name, ArrayRef< StringRef > Filenames)
uint64_t ExecutionCount
The number of times this function was executed.
void pushRegion(CounterMappingRegion Region, uint64_t Count, uint64_t FalseCount)
MCDC Record grouping all information together.
MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV, TVPairMap &&IndependencePairs, BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
std::pair< unsigned, unsigned > TVRowPair
std::string getConditionCoverageString(unsigned Condition)
std::string getConditionHeaderString(unsigned Condition)
unsigned getNumTestVectors() const
std::string getTestVectorString(unsigned TestVectorIndex)
TVRowPair getConditionIndependencePair(unsigned Condition)
Return the Independence Pair that covers the given condition.
bool isConditionIndependencePairCovered(unsigned Condition) const
Determine whether a given condition (indicated by Condition) is covered by an Independence Pair.
CondState
CondState represents the evaluation of a condition in an executed test vector, which can be True or F...
std::string getTestVectorHeaderString() const
CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition)
Return the evaluation of a condition (indicated by Condition) in an executed test vector (indicated b...
unsigned getNumConditions() const
std::array< BitVector, 2 > BoolVector
const CounterMappingRegion & getDecisionRegion() const
CondState getTVResult(unsigned TestVectorIndex)
Return the Result evaluation for an executed test vector.
bool isCondFolded(unsigned Condition) const
ConditionIDs NextIDs
Number of accumulated paths (>= 1)
int Width
Reference count; temporary use.