LLVM 24.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"
35#include <algorithm>
36#include <cassert>
37#include <cstdint>
38#include <iterator>
39#include <map>
40#include <memory>
41#include <optional>
42#include <sstream>
43#include <string>
44#include <system_error>
45#include <utility>
46#include <vector>
47
48namespace llvm {
49
51
52namespace object {
53class BuildIDFetcher;
54} // namespace object
55
56namespace coverage {
57
60
71
72LLVM_ABI const 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 LLVM_ABI 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; }
96 static char ID;
98private:
100 std::string Msg;
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) {}
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);
145 /// Return the counter that represents the number zero.
146 static Counter getZero() { return Counter(); }
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.
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;
177 /// A lookup table for the index of a given expression.
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.
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 LLVM_ABI 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 LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
216
217 /// K to V map. K will be Counter in most cases. V may be Counter or
218 /// Expression.
219 using SubstMap = std::map<Counter, Counter>;
220
221 /// \return A counter equivalent to \C, with each term in its
222 /// expression replaced with term from \p Map.
223 LLVM_ABI Counter subst(Counter C, const SubstMap &Map);
224};
225
226using LineColPair = std::pair<unsigned, unsigned>;
227
228/// A Counter mapping region associates a source range with a specific counter.
231 /// A CodeRegion associates some code with a counter
233
234 /// An ExpansionRegion represents a file expansion region that associates
235 /// a source range with the expansion of a virtual source file, such as
236 /// for a macro instantiation or #include file.
238
239 /// A SkippedRegion represents a source range with code that was skipped
240 /// by a preprocessor or similar means.
242
243 /// A GapRegion is like a CodeRegion, but its count is only set as the
244 /// line execution count when its the only region in the line.
246
247 /// A BranchRegion represents leaf-level boolean expressions and is
248 /// associated with two counters, each representing the number of times the
249 /// expression evaluates to true or false.
251
252 /// A DecisionRegion represents a top-level boolean expression and is
253 /// associated with a variable length bitmap index and condition number.
255
256 /// A Branch Region can be extended to include IDs to facilitate MC/DC.
258 };
259
260 /// Primary Counter that is also used for Branch Regions (TrueCount).
262
263 /// Secondary Counter used for Branch Regions (FalseCount).
265
266 /// Parameters used for Modified Condition/Decision Coverage
268
272
276
277 unsigned FileID = 0;
278 unsigned ExpandedFileID = 0;
280
282
283 bool isBranch() const {
284 return (Kind == BranchRegion || Kind == MCDCBranchRegion);
285 }
286
293
303
311
314 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
317 }
318
320 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
321 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
325 }
326
328 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
329 unsigned LineEnd, unsigned ColumnEnd) {
332 }
333
336 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
338 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
339 }
340
343 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
344 unsigned ColumnEnd,
345 const mcdc::Parameters &MCDCParams = std::monostate()) {
348 ColumnEnd,
349 (std::get_if<mcdc::BranchParameters>(&MCDCParams) ? MCDCBranchRegion
350 : BranchRegion),
351 MCDCParams);
352 }
353
361
362 inline LineColPair startLoc() const {
364 }
365
366 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); }
367};
368
369/// Associates a source range with an execution count.
386
387/// MCDC Record grouping all information together.
389 /// CondState represents the evaluation of a condition in an executed test
390 /// vector, which can be True or False. A DontCare is used to mask an
391 /// unevaluatable condition resulting from short-circuit behavior of logical
392 /// operators in languages like C/C++. When comparing the evaluation of a
393 /// condition across executed test vectors, comparisons against a DontCare
394 /// are effectively ignored.
396
397 /// Emulate SmallVector<CondState> with a pair of BitVector.
398 ///
399 /// True False DontCare (Impossible)
400 /// Values: True False False True
401 /// Visited: True True False False
403 BitVector Values; /// True/False (False when DontCare)
404 BitVector Visited; /// ~DontCare
405
406 public:
407 /// Default values are filled with DontCare.
408 TestVector(unsigned N) : Values(N), Visited(N) {}
409
410 /// Emulate RHS SmallVector::operator[]
411 CondState operator[](int I) const {
412 return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False)
413 : MCDC_DontCare);
414 }
415
416 /// Equivalent to buildTestVector's Index.
417 auto getIndex() const { return Values.getData()[0]; }
418
419 /// Set the condition \p Val at position \p I.
420 /// This emulates LHS SmallVector::operator[].
421 void set(int I, CondState Val) {
422 Visited[I] = (Val != MCDC_DontCare);
423 Values[I] = (Val == MCDC_True);
424 }
425
426 /// Emulate SmallVector::push_back.
428 Visited.push_back(Val != MCDC_DontCare);
429 Values.push_back(Val == MCDC_True);
430 assert(Values.size() == Visited.size());
431 }
432
433 /// For each element:
434 /// - False if either is DontCare
435 /// - False if both have the same value
436 /// - True if both have the opposite value
437 /// ((A.Values ^ B.Values) & A.Visited & B.Visited)
438 /// Dedicated to findIndependencePairs().
439 auto getDifferences(const TestVector &B) const {
440 const auto &A = *this;
441 BitVector AB = A.Values;
442 AB ^= B.Values;
443 AB &= A.Visited;
444 AB &= B.Visited;
445 return AB;
446 }
447 };
448
450 using BoolVector = std::array<BitVector, 2>;
451 using TVRowPair = std::pair<unsigned, unsigned>;
455
456private:
458 TestVectors TV;
459 TestVectors NotExecutedTV;
460 std::optional<TVPairMap> IndependencePairs;
461 BoolVector Folded;
462 CondIDMap PosToID;
463 LineColPairMap CondLoc;
464
465 std::string formatTestVectorRow(const TestVector &Vec, CondState Result,
466 unsigned DisplayRowNumber) const {
467 std::ostringstream OS;
468 const auto NumConditions = getNumConditions();
469 // Add individual condition values to the string.
470 OS << " " << DisplayRowNumber << " { ";
471 for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
472 if (isCondFolded(Condition))
473 OS << "C";
474 else {
475 auto It = PosToID.find(Condition);
476 assert(It != PosToID.end() && "Ordinal without CondID mapping");
477 switch (Vec[It->second]) {
478 case MCDC_DontCare:
479 OS << "-";
480 break;
481 case MCDC_True:
482 OS << "T";
483 break;
484 case MCDC_False:
485 OS << "F";
486 break;
487 }
488 }
489 if (Condition != NumConditions - 1)
490 OS << ", ";
491 }
492
493 // Add result value to the string.
494 OS << " = ";
495 if (Result == MCDC_True)
496 OS << "T";
497 else
498 OS << "F";
499 OS << " }\n";
500 return OS.str();
501 }
502
503public:
505 TestVectors &&NotExecutedTV, BoolVector &&Folded,
506 CondIDMap &&PosToID, LineColPairMap &&CondLoc)
507 : Region(Region), TV(std::move(TV)),
508 NotExecutedTV(std::move(NotExecutedTV)), Folded(std::move(Folded)),
509 PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
511 }
512
513 // Compare executed test vectors against each other to find an independence
514 // pairs for each condition. This processing takes the most time.
516
517 const CounterMappingRegion &getDecisionRegion() const { return Region; }
518 unsigned getNumConditions() const {
519 return Region.getDecisionParams().NumConditions;
520 }
521 unsigned getNumTestVectors() const { return TV.size(); }
522 unsigned getNumNotExecutedTestVectors() const { return NotExecutedTV.size(); }
523
524 bool isCondFolded(unsigned Condition) const {
525 return Folded[false][Condition] || Folded[true][Condition];
526 }
527
528 /// Return the evaluation of a condition (indicated by Condition) in an
529 /// executed test vector (indicated by TestVectorIndex), which will be True,
530 /// False, or DontCare if the condition is unevaluatable. Because condition
531 /// IDs are not associated based on their position in the expression,
532 /// accessing conditions in the TestVectors requires a translation from a
533 /// ordinal position to actual condition ID. This is done via PosToID[].
534 CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) {
535 return TV[TestVectorIndex].first[PosToID[Condition]];
536 }
537
538 CondState getNotExecutedTVCondition(unsigned NotExecutedIndex,
539 unsigned Condition) {
540 return NotExecutedTV[NotExecutedIndex].first[PosToID[Condition]];
541 }
542
543 /// Return the number of True and False decisions for all executed test
544 /// vectors.
545 std::pair<unsigned, unsigned> getDecisions() const {
546 const unsigned TrueDecisions =
548
549 return {TrueDecisions, TV.size() - TrueDecisions};
550 }
551
552 /// Return the Result evaluation for an executed test vector.
553 /// See MCDCRecordProcessor::RecordTestVector().
554 CondState getTVResult(unsigned TestVectorIndex) {
555 return TV[TestVectorIndex].second;
556 }
557
558 CondState getNotExecutedTVResult(unsigned NotExecutedIndex) {
559 return NotExecutedTV[NotExecutedIndex].second;
560 }
561
562 /// Determine whether a given condition (indicated by Condition) is covered
563 /// by an Independence Pair. Because condition IDs are not associated based
564 /// on their position in the expression, accessing conditions in the
565 /// TestVectors requires a translation from a ordinal position to actual
566 /// condition ID. This is done via PosToID[].
567 bool isConditionIndependencePairCovered(unsigned Condition) const {
568 assert(IndependencePairs);
569 auto It = PosToID.find(Condition);
570 assert(It != PosToID.end() && "Condition ID without an Ordinal mapping");
571 return IndependencePairs->contains(It->second);
572 }
573
574 /// Return the Independence Pair that covers the given condition. Because
575 /// condition IDs are not associated based on their position in the
576 /// expression, accessing conditions in the TestVectors requires a
577 /// translation from a ordinal position to actual condition ID. This is done
578 /// via PosToID[].
581 assert(IndependencePairs);
582 return (*IndependencePairs)[PosToID[Condition]];
583 }
584
585 float getPercentCovered() const {
586 unsigned Folded = 0;
587 unsigned Covered = 0;
588 for (unsigned C = 0; C < getNumConditions(); C++) {
589 if (isCondFolded(C))
590 Folded++;
592 Covered++;
593 }
594
595 unsigned Total = getNumConditions() - Folded;
596 if (Total == 0)
597 return 0.0;
598 return (static_cast<double>(Covered) / static_cast<double>(Total)) * 100.0;
599 }
600
601 std::string getConditionHeaderString(unsigned Condition) {
602 std::ostringstream OS;
603 const auto &[Line, Col] = CondLoc[Condition];
604 OS << "Condition C" << Condition + 1 << " --> (" << Line << ":" << Col
605 << ")\n";
606 return OS.str();
607 }
608
609 std::string getTestVectorHeaderString() const {
610 std::ostringstream OS;
611 if (getNumTestVectors() == 0 && getNumNotExecutedTestVectors() == 0) {
612 OS << "None.\n";
613 return OS.str();
614 }
615 const auto NumConditions = getNumConditions();
616 for (unsigned I = 0; I < NumConditions; I++) {
617 OS << "C" << I + 1;
618 if (I != NumConditions - 1)
619 OS << ", ";
620 }
621 OS << " Result\n";
622 return OS.str();
623 }
624
625 std::string getTestVectorString(unsigned TestVectorIndex) {
626 assert(TestVectorIndex < getNumTestVectors() &&
627 "TestVector index out of bounds!");
628 const auto &[Vec, Res] = TV[TestVectorIndex];
629 return formatTestVectorRow(Vec, Res, TestVectorIndex + 1);
630 }
631
632 std::string getNotExecutedTestVectorString(unsigned NotExecutedIndex) {
633 assert(NotExecutedIndex < getNumNotExecutedTestVectors() &&
634 "Not-executed test vector index out of bounds!");
635 const auto &[Vec, Res] = NotExecutedTV[NotExecutedIndex];
636 return formatTestVectorRow(Vec, Res,
637 getNumTestVectors() + NotExecutedIndex + 1);
638 }
639
640 std::string getConditionCoverageString(unsigned Condition) {
641 assert(Condition < getNumConditions() &&
642 "Condition index is out of bounds!");
643 std::ostringstream OS;
644
645 OS << " C" << Condition + 1 << "-Pair: ";
646 if (isCondFolded(Condition)) {
647 OS << "constant folded\n";
648 } else if (isConditionIndependencePairCovered(Condition)) {
649 TVRowPair rows = getConditionIndependencePair(Condition);
650 OS << "covered: (" << rows.first << ",";
651 OS << rows.second << ")\n";
652 } else
653 OS << "not covered\n";
654
655 return OS.str();
656 }
657};
658
659namespace mcdc {
660/// Compute TestVector Indices "TVIdx" from the Conds graph.
661///
662/// Clang CodeGen handles the bitmap index based on TVIdx.
663/// llvm-cov reconstructs conditions from TVIdx.
664///
665/// For each leaf "The final decision",
666/// - TVIdx should be unique.
667/// - TVIdx has the Width.
668/// - The width represents the number of possible paths.
669/// - The minimum width is 1 "deterministic".
670/// - The order of leaves are sorted by Width DESC. It expects
671/// latter TVIdx(s) (with Width=1) could be pruned and altered to
672/// other simple branch conditions.
673///
675public:
676 struct MCDCNode {
677 int InCount = 0; /// Reference count; temporary use
678 int Width; /// Number of accumulated paths (>= 1)
680 };
681
682#ifndef NDEBUG
683 /// This is no longer needed after the assignment.
684 /// It may be used in assert() for reconfirmation.
686#endif
687
688 /// Output: Index for TestVectors bitmap (These are not CondIDs)
690
691 /// Output: The number of test vectors.
692 /// Error with HardMaxTVs if the number has exploded.
694
695 /// Hard limit of test vectors
696 static constexpr auto HardMaxTVs =
697 std::numeric_limits<decltype(NumTestVectors)>::max();
698
699public:
700 /// Calculate and assign Indices
701 /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
702 /// The first element [0] should be the root node.
703 /// \param Offset Offset of index to final decisions.
705 int Offset = 0);
706};
707} // namespace mcdc
708
709/// A Counter mapping context is used to connect the counters, expressions
710/// and the obtained counter values.
712 ArrayRef<CounterExpression> Expressions;
713 ArrayRef<uint64_t> CounterValues;
714 BitVector Bitmap;
715
716public:
718 ArrayRef<uint64_t> CounterValues = {})
719 : Expressions(Expressions), CounterValues(CounterValues) {}
720
721 void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
722 void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); }
723
724 LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const;
725 void dump(const Counter &C) const { dump(C, dbgs()); }
726
727 /// Return the number of times that a region of code associated with this
728 /// counter was executed.
730
731 /// Return an MCDC record that indicates executed test vectors and condition
732 /// pairs.
736 bool IsVersion11);
737
738 LLVM_ABI unsigned getMaxCounterID(const Counter &C) const;
739};
740
741/// Code coverage information for a single function.
743 /// Raw function name.
744 std::string Name;
745 /// Mapping from FileID (i.e. vector index) to filename. Used to support
746 /// macro expansions within a function in which the macro and function are
747 /// defined in separate files.
748 ///
749 /// TODO: Uniquing filenames across all function records may be a performance
750 /// optimization.
751 std::vector<std::string> Filenames;
752 /// Regions in the function along with their counts.
753 std::vector<CountedRegion> CountedRegions;
754 /// Branch Regions in the function along with their counts.
755 std::vector<CountedRegion> CountedBranchRegions;
756 /// MCDC Records record a DecisionRegion and associated BranchRegions.
757 std::vector<MCDCRecord> MCDCRecords;
758 /// The number of times this function was executed.
760
763
766
768 MCDCRecords.push_back(std::move(Record));
769 }
770
772 uint64_t FalseCount) {
773 if (Region.isBranch()) {
774 CountedBranchRegions.emplace_back(Region, Count, FalseCount);
775 // If either counter is hard-coded to zero, then this region represents a
776 // constant-folded branch.
777 CountedBranchRegions.back().TrueFolded = Region.Count.isZero();
778 CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero();
779 return;
780 }
781 if (CountedRegions.empty())
783 CountedRegions.emplace_back(Region, Count, FalseCount);
784 }
785};
786
787/// Iterator over Functions, optionally filtered to a single file.
788/// When filtering to a single file, the iterator requires a list of potential
789/// indices where to find the desired records to avoid quadratic behavior when
790/// repeatedly iterating over functions from different files.
792 : public iterator_facade_base<FunctionRecordIterator,
793 std::forward_iterator_tag, FunctionRecord> {
795 ArrayRef<unsigned> RecordIndices;
796 ArrayRef<unsigned>::iterator CurrentIndex;
798 StringRef Filename;
799
800 /// Skip records whose primary file is not \c Filename.
801 LLVM_ABI void skipOtherFiles();
802
803public:
805 StringRef Filename = "",
806 ArrayRef<unsigned> RecordIndices_ = {})
807 : Records(Records_), RecordIndices(RecordIndices_),
808 CurrentIndex(RecordIndices.begin()),
809 // If `RecordIndices` is provided, we can skip directly to the first
810 // index it provides.
811 Current(CurrentIndex == RecordIndices.end() ? Records.begin()
812 : &Records[*CurrentIndex]),
814 assert(Filename.empty() == RecordIndices_.empty() &&
815 "If `Filename` is specified, `RecordIndices` must also be provided");
816 skipOtherFiles();
817 }
818
819 FunctionRecordIterator() : Current(Records.begin()) {}
820
822 return Current == RHS.Current && Filename == RHS.Filename;
823 }
824
825 const FunctionRecord &operator*() const { return *Current; }
826
828 advanceOne();
829 skipOtherFiles();
830 return *this;
831 }
832
833private:
834 void advanceOne() {
835 if (RecordIndices.empty()) {
836 // Iteration over all entries, advance in the list of records.
837 assert(Current != Records.end() && "incremented past end");
838 ++Current;
839 } else {
840 // Iterator over entries filtered by file name. Advance in the list of
841 // indices, and adjust the cursor in the list of records accordingly.
842 assert(CurrentIndex != RecordIndices.end() && "incremented past end");
843 ++CurrentIndex;
844 if (CurrentIndex == RecordIndices.end()) {
845 Current = Records.end();
846 } else {
847 Current = &Records[*CurrentIndex];
848 }
849 }
850 }
851};
852
853/// Coverage information for a macro expansion or #included file.
854///
855/// When covered code has pieces that can be expanded for more detail, such as a
856/// preprocessor macro use and its definition, these are represented as
857/// expansions whose coverage can be looked up independently.
859 /// The abstract file this expansion covers.
860 unsigned FileID;
861 /// The region that expands to this record.
863 /// Coverage for the expansion.
865
869};
870
871/// The execution count information starting at a point in a file.
872///
873/// A sequence of CoverageSegments gives execution counts for a file in format
874/// that's simple to iterate through for processing.
876 /// The line where this segment begins.
877 unsigned Line;
878 /// The column where this segment begins.
879 unsigned Col;
880 /// The execution count, or zero if no count was recorded.
882 /// When false, the segment was uninstrumented or skipped.
884 /// Whether this enters a new region or returns to a previous count.
886 /// Whether this enters a gap region.
888
892
893 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
894 bool IsRegionEntry, bool IsGapRegion = false,
895 bool IsBranchRegion = false)
898
899 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
900 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry,
901 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count,
902 R.HasCount, R.IsRegionEntry,
903 R.IsGapRegion);
904 }
905};
906
907/// An instantiation group contains a \c FunctionRecord list, such that each
908/// record corresponds to a distinct instantiation of the same function.
909///
910/// Note that it's possible for a function to have more than one instantiation
911/// (consider C++ template specializations or static inline functions).
912class InstantiationGroup {
913 friend class CoverageMapping;
914
915 unsigned Line;
916 unsigned Col;
917 std::vector<const FunctionRecord *> Instantiations;
918
919 InstantiationGroup(unsigned Line, unsigned Col,
920 std::vector<const FunctionRecord *> Instantiations)
921 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {}
922
923public:
924 InstantiationGroup(const InstantiationGroup &) = delete;
925 InstantiationGroup(InstantiationGroup &&) = default;
926
927 /// Get the number of instantiations in this group.
928 size_t size() const { return Instantiations.size(); }
929
930 /// Get the line where the common function was defined.
931 unsigned getLine() const { return Line; }
932
933 /// Get the column where the common function was defined.
934 unsigned getColumn() const { return Col; }
935
936 /// Check if the instantiations in this group have a common mangled name.
937 bool hasName() const {
938 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I)
939 if (Instantiations[I]->Name != Instantiations[0]->Name)
940 return false;
941 return true;
942 }
943
944 /// Get the common mangled name for instantiations in this group.
946 assert(hasName() && "Instantiations don't have a shared name");
947 return Instantiations[0]->Name;
948 }
949
950 /// Get the total execution count of all instantiations in this group.
952 uint64_t Count = 0;
953 for (const FunctionRecord *F : Instantiations)
954 Count += F->ExecutionCount;
955 return Count;
956 }
957
958 /// Get the instantiations in this group.
960 return Instantiations;
961 }
962};
963
964/// Coverage information to be processed or displayed.
965///
966/// This represents the coverage of an entire file, expansion, or function. It
967/// provides a sequence of CoverageSegments to iterate through, as well as the
968/// list of expansions that can be further processed.
970 friend class CoverageMapping;
971
972protected:
973 std::string Filename;
974 std::vector<CoverageSegment> Segments;
975 std::vector<ExpansionRecord> Expansions;
976 std::vector<CountedRegion> BranchRegions;
977 std::vector<MCDCRecord> MCDCRecords;
978
979 bool SingleByteCoverage = false;
980
981public:
982 CoverageData() = default;
983
986
988
989 /// Get the name of the file this data covers.
990 StringRef getFilename() const { return Filename; }
991
993
994 /// Get an iterator over the coverage segments for this object. The segments
995 /// are guaranteed to be uniqued and sorted by location.
996 std::vector<CoverageSegment>::const_iterator begin() const {
997 return Segments.begin();
998 }
999
1000 std::vector<CoverageSegment>::const_iterator end() const {
1001 return Segments.end();
1002 }
1003
1004 bool empty() const { return Segments.empty(); }
1005
1006 /// Expansions that can be further processed.
1008
1009 /// Branches that can be further processed.
1011
1012 /// MCDC Records that can be further processed.
1014};
1015
1016/// The mapping of profile information to coverage data.
1017///
1018/// This is the main interface to get coverage information, using a profile to
1019/// fill out execution counts.
1020class CoverageMapping {
1021 DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
1022 std::vector<FunctionRecord> Functions;
1023 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
1024 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
1025
1026 std::optional<bool> SingleByteCoverage;
1027
1028 CoverageMapping() = default;
1029
1030 // Load coverage records from readers.
1031 static Error loadFromReaders(
1032 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
1033 std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1034 &ProfileReader,
1035 CoverageMapping &Coverage);
1036
1037 // Load coverage records from file.
1038 static Error
1039 loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
1040 std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1041 &ProfileReader,
1042 CoverageMapping &Coverage, bool &DataFound,
1043 SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
1044
1045 /// Add a function record corresponding to \p Record.
1046 Error loadFunctionRecord(
1048 const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1049 &ProfileReader);
1050
1051 /// Look up the indices for function records which are at least partially
1052 /// defined in the specified file. This is guaranteed to return a superset of
1053 /// such records: extra records not in the file may be included if there is
1054 /// a hash collision on the filename. Clients must be robust to collisions.
1056 getImpreciseRecordIndicesForFilename(StringRef Filename) const;
1057
1058public:
1059 CoverageMapping(const CoverageMapping &) = delete;
1060 CoverageMapping &operator=(const CoverageMapping &) = delete;
1061
1062 /// Load the coverage mapping using the given readers.
1064 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
1065 std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1066 &ProfileReader);
1067
1068 /// Load the coverage mapping from the given object files and profile. If
1069 /// \p Arches is non-empty, it must specify an architecture for each object.
1070 /// Ignores non-instrumented object files unless all are not instrumented.
1072 load(ArrayRef<StringRef> ObjectFilenames,
1073 std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
1074 ArrayRef<StringRef> Arches = {}, StringRef CompilationDir = "",
1075 const object::BuildIDFetcher *BIDFetcher = nullptr,
1076 bool CheckBinaryIDs = false);
1078 /// The number of functions that couldn't have their profiles mapped.
1079 ///
1080 /// This is a count of functions whose profile is out of date or otherwise
1081 /// can't be associated with any coverage information.
1082 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
1083
1084 /// A hash mismatch occurs when a profile record for a symbol does not have
1085 /// the same hash as a coverage mapping record for the same symbol. This
1086 /// returns a list of hash mismatches, where each mismatch is a pair of the
1087 /// symbol name and its coverage mapping hash.
1089 return FuncHashMismatches;
1090 }
1091
1092 /// Returns a lexicographically sorted, unique list of files that are
1093 /// covered.
1094 LLVM_ABI std::vector<StringRef> getUniqueSourceFiles() const;
1096 /// Get the coverage for a particular file.
1097 ///
1098 /// The given filename must be the name as recorded in the coverage
1099 /// information. That is, only names returned from getUniqueSourceFiles will
1100 /// yield a result.
1102
1103 /// Get the coverage for a particular function.
1106
1107 /// Get the coverage for an expansion within a coverage set.
1110
1111 /// Gets all of the functions covered by this profile.
1116
1117 /// Gets all of the functions in a particular file.
1120 return make_range(
1122 getImpreciseRecordIndicesForFilename(Filename)),
1124 }
1125
1126 /// Get the list of function instantiation groups in a particular file.
1127 ///
1128 /// Every instantiation group in a program is attributed to exactly one file:
1129 /// the file in which the definition for the common function begins.
1130 LLVM_ABI std::vector<InstantiationGroup>
1132};
1133
1134/// Coverage statistics for a single line.
1135class LineCoverageStats {
1136 uint64_t ExecutionCount;
1137 bool HasMultipleRegions;
1138 bool Mapped;
1139 unsigned Line;
1141 const CoverageSegment *WrappedSegment;
1142
1144 LineCoverageStats() = default;
1145
1146public:
1147 LLVM_ABI LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments,
1148 const CoverageSegment *WrappedSegment,
1149 unsigned Line);
1150
1151 uint64_t getExecutionCount() const { return ExecutionCount; }
1152
1153 bool hasMultipleRegions() const { return HasMultipleRegions; }
1154
1155 bool isMapped() const { return Mapped; }
1156
1157 unsigned getLine() const { return Line; }
1158
1160 return LineSegments;
1161 }
1162
1163 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
1164};
1165
1166/// An iterator over the \c LineCoverageStats objects for lines described by
1167/// a \c CoverageData instance.
1169 : public iterator_facade_base<LineCoverageIterator,
1170 std::forward_iterator_tag,
1171 const LineCoverageStats> {
1172public:
1174 : LineCoverageIterator(CD, CD.begin()->Line) {}
1175
1176 LineCoverageIterator(const CoverageData &CD, unsigned Line)
1177 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
1178 Line(Line) {
1179 this->operator++();
1180 }
1181
1182 bool operator==(const LineCoverageIterator &R) const {
1183 return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
1184 }
1185
1186 const LineCoverageStats &operator*() const { return Stats; }
1187
1189
1191 auto EndIt = *this;
1192 EndIt.Next = CD.end();
1193 EndIt.Ended = true;
1194 return EndIt;
1195 }
1196
1197private:
1198 const CoverageData &CD;
1199 const CoverageSegment *WrappedSegment;
1200 std::vector<CoverageSegment>::const_iterator Next;
1201 bool Ended;
1202 unsigned Line;
1205};
1206
1207/// Get a \c LineCoverageIterator range for the lines described by \p CD.
1210 auto Begin = LineCoverageIterator(CD);
1211 auto End = Begin.getEnd();
1212 return make_range(Begin, End);
1213}
1214
1215// Coverage mappping data (V2) has the following layout:
1216// IPSK_covmap:
1217// [CoverageMapFileHeader]
1218// [ArrayStart]
1219// [CovMapFunctionRecordV2]
1220// [CovMapFunctionRecordV2]
1221// ...
1222// [ArrayEnd]
1223// [Encoded Filenames and Region Mapping Data]
1224//
1225// Coverage mappping data (V3) has the following layout:
1226// IPSK_covmap:
1227// [CoverageMapFileHeader]
1228// [Encoded Filenames]
1229// IPSK_covfun:
1230// [ArrayStart]
1231// odr_name_1: [CovMapFunctionRecordV3]
1232// odr_name_2: [CovMapFunctionRecordV3]
1233// ...
1234// [ArrayEnd]
1235//
1236// Both versions of the coverage mapping format encode the same information,
1237// but the V3 format does so more compactly by taking advantage of linkonce_odr
1238// semantics (it allows exactly 1 function record per name reference).
1239
1240/// This namespace defines accessors shared by different versions of coverage
1241/// mapping records.
1242namespace accessors {
1243
1244/// Return the structural hash associated with the function.
1245template <class FuncRecordTy, llvm::endianness Endian>
1246uint64_t getFuncHash(const FuncRecordTy *Record) {
1247 return support::endian::byte_swap<uint64_t>(Record->FuncHash, Endian);
1248}
1249
1250/// Return the coverage map data size for the function.
1251template <class FuncRecordTy, llvm::endianness Endian>
1252uint64_t getDataSize(const FuncRecordTy *Record) {
1253 return support::endian::byte_swap<uint32_t>(Record->DataSize, Endian);
1254}
1255
1256/// Return the function lookup key. The value is considered opaque.
1257template <class FuncRecordTy, llvm::endianness Endian>
1258uint64_t getFuncNameRef(const FuncRecordTy *Record) {
1259 return support::endian::byte_swap<uint64_t>(Record->NameRef, Endian);
1260}
1261
1262/// Return the PGO name of the function. Used for formats in which the name is
1263/// a hash.
1264template <class FuncRecordTy, llvm::endianness Endian>
1265Error getFuncNameViaRef(const FuncRecordTy *Record,
1266 InstrProfSymtab &ProfileNames, StringRef &FuncName) {
1268 FuncName = ProfileNames.getFuncOrVarName(NameRef);
1269 return Error::success();
1270}
1271
1272/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
1273/// coverage mapping is attached to the file header, instead of to the function
1274/// record.
1275template <class FuncRecordTy, llvm::endianness Endian>
1277 const char *MappingBuf) {
1278 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
1279}
1280
1281/// Advance to the next out-of-line coverage mapping and its associated
1282/// function record.
1283template <class FuncRecordTy, llvm::endianness Endian>
1284std::pair<const char *, const FuncRecordTy *>
1285advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
1286 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
1287}
1288
1289} // end namespace accessors
1290
1292template <class IntPtrT>
1295
1296#define COVMAP_V1
1297#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1299#undef COVMAP_V1
1300 CovMapFunctionRecordV1() = delete;
1301
1302 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1304 }
1305
1306 template <llvm::endianness Endian> uint64_t getDataSize() const {
1308 }
1309
1310 /// Return function lookup key. The value is consider opaque.
1311 template <llvm::endianness Endian> IntPtrT getFuncNameRef() const {
1312 return support::endian::byte_swap<IntPtrT>(NamePtr, Endian);
1313 }
1314
1315 /// Return the PGO name of the function.
1316 template <llvm::endianness Endian>
1317 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1318 IntPtrT NameRef = getFuncNameRef<Endian>();
1319 uint32_t NameS = support::endian::byte_swap<uint32_t>(NameSize, Endian);
1320 FuncName = ProfileNames.getFuncName(NameRef, NameS);
1321 if (NameS && FuncName.empty())
1323 "function name is empty");
1324 return Error::success();
1325 }
1326
1327 template <llvm::endianness Endian>
1328 std::pair<const char *, const ThisT *>
1329 advanceByOne(const char *MappingBuf) const {
1330 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1331 }
1332
1333 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1334 llvm_unreachable("V1 function format does not contain a filenames ref");
1335 }
1336
1337 template <llvm::endianness Endian>
1338 StringRef getCoverageMapping(const char *MappingBuf) const {
1340 MappingBuf);
1341 }
1342};
1343
1346
1347#define COVMAP_V2
1348#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1350#undef COVMAP_V2
1351 CovMapFunctionRecordV2() = delete;
1352
1353 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1355 }
1356
1357 template <llvm::endianness Endian> uint64_t getDataSize() const {
1359 }
1360
1361 template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1363 }
1364
1365 template <llvm::endianness Endian>
1366 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1367 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1368 FuncName);
1369 }
1370
1371 template <llvm::endianness Endian>
1372 std::pair<const char *, const ThisT *>
1373 advanceByOne(const char *MappingBuf) const {
1374 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1375 }
1376
1377 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1378 llvm_unreachable("V2 function format does not contain a filenames ref");
1379 }
1380
1381 template <llvm::endianness Endian>
1382 StringRef getCoverageMapping(const char *MappingBuf) const {
1384 MappingBuf);
1385 }
1386};
1387
1390
1391#define COVMAP_V3
1392#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1394#undef COVMAP_V3
1395 CovMapFunctionRecordV3() = delete;
1396
1397 template <llvm::endianness Endian> uint64_t getFuncHash() const {
1399 }
1400
1401 template <llvm::endianness Endian> uint64_t getDataSize() const {
1403 }
1404
1405 template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1407 }
1408
1409 template <llvm::endianness Endian>
1410 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1411 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1412 FuncName);
1413 }
1414
1415 /// Get the filename set reference.
1416 template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1417 return support::endian::byte_swap<uint64_t>(FilenamesRef, Endian);
1418 }
1419
1420 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
1421 /// out-of-line coverage mapping data only.
1422 template <llvm::endianness Endian>
1423 StringRef getCoverageMapping(const char *) const {
1424 return StringRef(&CoverageMapping, getDataSize<Endian>());
1425 }
1426
1427 // Advance to the next inline coverage mapping and its associated function
1428 // record. Ignore the out-of-line coverage mapping buffer.
1429 template <llvm::endianness Endian>
1430 std::pair<const char *, const CovMapFunctionRecordV3 *>
1431 advanceByOne(const char *) const {
1432 assert(isAddrAligned(Align(8), this) && "Function record not aligned");
1433 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
1434 sizeof(char) + getDataSize<Endian>();
1435 // Each function record has an alignment of 8, so we need to adjust
1436 // alignment before reading the next record.
1438 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
1439 }
1440};
1441
1442// Per module coverage mapping data header, i.e. CoverageMapFileHeader
1443// documented above.
1445#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
1447 template <llvm::endianness Endian> uint32_t getNRecords() const {
1448 return support::endian::byte_swap<uint32_t>(NRecords, Endian);
1449 }
1450
1451 template <llvm::endianness Endian> uint32_t getFilenamesSize() const {
1452 return support::endian::byte_swap<uint32_t>(FilenamesSize, Endian);
1453 }
1454
1455 template <llvm::endianness Endian> uint32_t getCoverageSize() const {
1456 return support::endian::byte_swap<uint32_t>(CoverageSize, Endian);
1457 }
1458
1459 template <llvm::endianness Endian> uint32_t getVersion() const {
1461 }
1462};
1463
1465
1468 // Function's name reference from CovMapFuncRecord is changed from raw
1469 // name string pointer to MD5 to support name section compression. Name
1470 // section is also compressed.
1472 // A new interpretation of the columnEnd field is added in order to mark
1473 // regions as gap areas.
1475 // Function records are named, uniqued, and moved to a dedicated section.
1477 // Branch regions referring to two counters are added
1479 // Compilation directory is stored separately and combined with relative
1480 // filenames to produce an absolute file path.
1482 // Branch regions extended and Decision Regions added for MC/DC.
1484 // The current version is Version7.
1486};
1487
1488// Correspond to "llvmcovm", in little-endian.
1489constexpr uint64_t TestingFormatMagic = 0x6d766f636d766c6c;
1490
1492 // The first version's number corresponds to the string "testdata" in
1493 // little-endian. This is for a historical reason.
1494 Version1 = 0x6174616474736574,
1495 // Version1 has a defect that it can't store multiple file records. Version2
1496 // fix this problem by adding a new field before the file records section.
1498 // The current testing format version is Version2.
1500};
1501
1502template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1505};
1506
1507template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1510};
1511
1512template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1515};
1516
1517template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1519 using NameRefType = IntPtrT;
1520};
1521
1522} // end namespace coverage
1523
1524/// Provide DenseMapInfo for CounterExpression
1525template <> struct DenseMapInfo<coverage::CounterExpression> {
1526 static unsigned getHashValue(const coverage::CounterExpression &V) {
1527 return static_cast<unsigned>(
1528 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
1529 V.RHS.getKind(), V.RHS.getCounterID()));
1530 }
1531
1534 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1535 }
1536};
1537
1538} // end namespace llvm
1539
1540#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
AMDGPU Mark last scratch load
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_PACKED_START
Definition Compiler.h:571
DXIL Intrinsic Expansion
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
hexagon bit simplify
#define INSTR_PROF_COVMAP_VERSION
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
block placement Basic Block Placement Stats
static constexpr StringLiteral Filename
const char * Msg
Contains the forward declaration for vfs::FileSystem, as well as the IntrusiveRefCntPtrInfo specializ...
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
const_pointer iterator
Definition ArrayRef.h:47
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Base class for user error types.
Definition Error.h:354
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
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:519
StringRef getFuncOrVarName(uint64_t ValMD5Hash) const
Return name of functions or global variables from the name's md5 hash value.
Definition InstrProf.h:791
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
A Counter expression builder is used to construct the counter expressions.
ArrayRef< CounterExpression > getExpressions() const
LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that subtracts RHS from LHS.
LLVM_ABI Counter add(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that adds LHS and RHS.
LLVM_ABI Counter subst(Counter C, const SubstMap &Map)
std::map< Counter, Counter > SubstMap
K to V map.
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.
void setCounts(ArrayRef< uint64_t > Counts)
void dump(const Counter &C) const
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.
void setBitmap(BitVector &&Bitmap_)
LLVM_ABI unsigned getMaxCounterID(const Counter &C) const
CounterMappingContext(ArrayRef< CounterExpression > Expressions, ArrayRef< uint64_t > CounterValues={})
LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const
Coverage information to be processed or displayed.
CoverageData(CoverageData &&RHS)=default
std::vector< CountedRegion > BranchRegions
ArrayRef< ExpansionRecord > getExpansions() const
Expansions that can be further processed.
std::vector< CoverageSegment > Segments
std::vector< ExpansionRecord > Expansions
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
std::vector< MCDCRecord > MCDCRecords
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
unsigned getMismatchedCount() const
The number of functions that couldn't have their profiles mapped.
LLVM_ABI std::vector< StringRef > getUniqueSourceFiles() const
Returns a lexicographically sorted, unique list of files that are covered.
LLVM_ABI 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.
LLVM_ABI CoverageData getCoverageForFunction(const FunctionRecord &Function) const
Get the coverage for a particular function.
CoverageMapping(const CoverageMapping &)=delete
LLVM_ABI std::vector< InstantiationGroup > getInstantiationGroups(StringRef Filename) const
Get the list of function instantiation groups in a particular file.
LLVM_ABI 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(ArrayRef< FunctionRecord > Records_, StringRef Filename="", ArrayRef< unsigned > RecordIndices_={})
FunctionRecordIterator & operator++()
bool operator==(const FunctionRecordIterator &RHS) const
const FunctionRecord & operator*() const
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
LLVM_ABI LineCoverageIterator & operator++()
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.
static constexpr auto HardMaxTVs
Hard limit of test vectors.
LLVM_ABI TVIdxBuilder(const SmallVectorImpl< ConditionIDs > &NextIDs, int Offset=0)
Calculate and assign Indices.
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:41
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
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.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr size_t NameSize
Definition XCOFF.h:30
This namespace defines accessors shared by different versions of coverage mapping records.
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.
auto & getParams(MaybeConstMCDCParameters &MCDCParams)
Check and get underlying params in MCDCParams.
Definition MCDCTypes.h:64
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:26
LLVM_ABI const std::error_category & coveragemap_category()
std::error_code make_error_code(coveragemap_error E)
std::pair< unsigned, unsigned > LineColPair
static iterator_range< LineCoverageIterator > getLineCoverageStats(const coverage::CoverageData &CD)
Get a LineCoverageIterator range for the lines described by CD.
constexpr uint64_t TestingFormatMagic
value_type byte_swap(value_type value, endianness endian)
Swap the bytes of value to match the given endianness.
Definition Endian.h:45
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_PACKED_END
Definition VPlan.h:1122
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:192
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
constexpr NextUseDistance max(NextUseDistance A, NextUseDistance B)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2028
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1425
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:1933
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:307
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition Alignment.h:139
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
static bool isEqual(const coverage::CounterExpression &LHS, const coverage::CounterExpression &RHS)
static unsigned getHashValue(const coverage::CounterExpression &V)
An information struct used to provide DenseMap with the various necessary components for a given valu...
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.
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), Inc->getHash() ->getZExtValue())) INSTR_PROF_DATA(const IntPtrT
std::pair< const char *, const ThisT * > advanceByOne(const char *MappingBuf) const
StringRef getCoverageMapping(const char *MappingBuf) const
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersBegin(uintptr_t) UniformCountersBegin -(uintptr_t) DataBegin uint64_t getFuncHash() const
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const
Return the PGO name of the function.
CovMapFunctionRecordV1< IntPtrT > ThisT
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersBegin(uintptr_t) UniformCountersBegin -(uintptr_t) DataBegin uint64_t getFuncHash() const
std::pair< const char *, const CovMapFunctionRecordV3 * > advanceByOne(const char *) const
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr UniformCountersBegin(uintptr_t) UniformCountersBegin -(uintptr_t) DataBegin uint64_t getFuncHash() const
StringRef getCoverageMapping(const char *) const
Read the inline coverage mapping.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
uint64_t getFilenamesRef() const
Get the filename set reference.
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const
CovMapFunctionRecordV3 CovMapFuncRecordType
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.
std::pair< unsigned, unsigned > TVRowPair
MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV, TestVectors &&NotExecutedTV, BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
CondState getNotExecutedTVCondition(unsigned NotExecutedIndex, unsigned Condition)
CondState getNotExecutedTVResult(unsigned NotExecutedIndex)
std::string getConditionCoverageString(unsigned Condition)
std::pair< unsigned, unsigned > getDecisions() const
Return the number of True and False decisions for all executed test vectors.
std::string getConditionHeaderString(unsigned Condition)
unsigned getNumTestVectors() const
llvm::SmallVector< std::pair< TestVector, CondState > > TestVectors
unsigned getNumNotExecutedTestVectors() const
LLVM_ABI void findIndependencePairs()
std::string getTestVectorString(unsigned TestVectorIndex)
llvm::DenseMap< unsigned, unsigned > CondIDMap
llvm::DenseMap< unsigned, LineColPair > LineColPairMap
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...
std::string getNotExecutedTestVectorString(unsigned NotExecutedIndex)
unsigned getNumConditions() const
std::array< BitVector, 2 > BoolVector
const CounterMappingRegion & getDecisionRegion() const
llvm::DenseMap< unsigned, TVRowPair > TVPairMap
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.