LLVM 17.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/DenseMap.h"
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/ADT/Hashing.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/ADT/iterator.h"
24#include "llvm/Object/BuildID.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/Endian.h"
30#include "llvm/Support/Error.h"
32#include <cassert>
33#include <cstdint>
34#include <iterator>
35#include <memory>
36#include <string>
37#include <system_error>
38#include <tuple>
39#include <utility>
40#include <vector>
41
42namespace llvm {
43
44class IndexedInstrProfReader;
45
46namespace object {
47class BuildIDFetcher;
48} // namespace object
49
50namespace vfs {
51class FileSystem;
52} // namespace vfs
53
54namespace coverage {
55
58
60 success = 0,
61 eof,
68};
69
70const std::error_category &coveragemap_category();
71
72inline std::error_code make_error_code(coveragemap_error E) {
73 return std::error_code(static_cast<int>(E), coveragemap_category());
74}
75
76class CoverageMapError : public ErrorInfo<CoverageMapError> {
77public:
79 assert(Err != coveragemap_error::success && "Not an error");
80 }
81
82 std::string message() const override;
83
84 void log(raw_ostream &OS) const override { OS << message(); }
85
86 std::error_code convertToErrorCode() const override {
87 return make_error_code(Err);
88 }
89
90 coveragemap_error get() const { return Err; }
91
92 static char ID;
93
94private:
96};
97
98/// A Counter is an abstract value that describes how to compute the
99/// execution count for a region of code using the collected profile count data.
100struct Counter {
101 /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
102 /// the CounterKind. This means CounterKind has to leave bit 0 free.
104 static const unsigned EncodingTagBits = 2;
105 static const unsigned EncodingTagMask = 0x3;
107 EncodingTagBits + 1;
108
109private:
110 CounterKind Kind = Zero;
111 unsigned ID = 0;
112
113 Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
114
115public:
116 Counter() = default;
117
118 CounterKind getKind() const { return Kind; }
119
120 bool isZero() const { return Kind == Zero; }
121
122 bool isExpression() const { return Kind == Expression; }
123
124 unsigned getCounterID() const { return ID; }
125
126 unsigned getExpressionID() const { return ID; }
127
128 friend bool operator==(const Counter &LHS, const Counter &RHS) {
129 return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
130 }
131
132 friend bool operator!=(const Counter &LHS, const Counter &RHS) {
133 return !(LHS == RHS);
134 }
135
136 friend bool operator<(const Counter &LHS, const Counter &RHS) {
137 return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
138 }
139
140 /// Return the counter that represents the number zero.
141 static Counter getZero() { return Counter(); }
142
143 /// Return the counter that corresponds to a specific profile counter.
144 static Counter getCounter(unsigned CounterId) {
145 return Counter(CounterValueReference, CounterId);
146 }
147
148 /// Return the counter that corresponds to a specific addition counter
149 /// expression.
150 static Counter getExpression(unsigned ExpressionId) {
151 return Counter(Expression, ExpressionId);
152 }
153};
154
155/// A Counter expression is a value that represents an arithmetic operation
156/// with two counters.
161
163 : Kind(Kind), LHS(LHS), RHS(RHS) {}
164};
165
166/// A Counter expression builder is used to construct the counter expressions.
167/// It avoids unnecessary duplication and simplifies algebraic expressions.
169 /// A list of all the counter expressions
170 std::vector<CounterExpression> Expressions;
171
172 /// A lookup table for the index of a given expression.
174
175 /// Return the counter which corresponds to the given expression.
176 ///
177 /// If the given expression is already stored in the builder, a counter
178 /// that references that expression is returned. Otherwise, the given
179 /// expression is added to the builder's collection of expressions.
180 Counter get(const CounterExpression &E);
181
182 /// Represents a term in a counter expression tree.
183 struct Term {
184 unsigned CounterID;
185 int Factor;
186
187 Term(unsigned CounterID, int Factor)
188 : CounterID(CounterID), Factor(Factor) {}
189 };
190
191 /// Gather the terms of the expression tree for processing.
192 ///
193 /// This collects each addition and subtraction referenced by the counter into
194 /// a sequence that can be sorted and combined to build a simplified counter
195 /// expression.
196 void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms);
197
198 /// Simplifies the given expression tree
199 /// by getting rid of algebraically redundant operations.
200 Counter simplify(Counter ExpressionTree);
201
202public:
203 ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
204
205 /// Return a counter that represents the expression that adds LHS and RHS.
206 Counter add(Counter LHS, Counter RHS, bool Simplify = true);
207
208 /// Return a counter that represents the expression that subtracts RHS from
209 /// LHS.
210 Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
211};
212
213using LineColPair = std::pair<unsigned, unsigned>;
214
215/// A Counter mapping region associates a source range with a specific counter.
218 /// A CodeRegion associates some code with a counter
220
221 /// An ExpansionRegion represents a file expansion region that associates
222 /// a source range with the expansion of a virtual source file, such as
223 /// for a macro instantiation or #include file.
225
226 /// A SkippedRegion represents a source range with code that was skipped
227 /// by a preprocessor or similar means.
229
230 /// A GapRegion is like a CodeRegion, but its count is only set as the
231 /// line execution count when its the only region in the line.
233
234 /// A BranchRegion represents leaf-level boolean expressions and is
235 /// associated with two counters, each representing the number of times the
236 /// expression evaluates to true or false.
238 };
239
240 /// Primary Counter that is also used for Branch Regions (TrueCount).
242
243 /// Secondary Counter used for Branch Regions (FalseCount).
245
249
251 unsigned LineStart, unsigned ColumnStart,
252 unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
256
258 unsigned ExpandedFileID, unsigned LineStart,
259 unsigned ColumnStart, unsigned LineEnd,
260 unsigned ColumnEnd, RegionKind Kind)
264 Kind(Kind) {}
265
268 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
271 }
272
274 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
275 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
279 }
280
282 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
283 unsigned LineEnd, unsigned ColumnEnd) {
286 }
287
290 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
292 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
293 }
294
297 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
298 unsigned ColumnEnd) {
301 }
302
303 inline LineColPair startLoc() const {
305 }
306
307 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); }
308};
309
310/// Associates a source range with an execution count.
314 bool Folded;
315
319
324};
325
326/// A Counter mapping context is used to connect the counters, expressions
327/// and the obtained counter values.
329 ArrayRef<CounterExpression> Expressions;
330 ArrayRef<uint64_t> CounterValues;
331
332public:
334 ArrayRef<uint64_t> CounterValues = std::nullopt)
335 : Expressions(Expressions), CounterValues(CounterValues) {}
336
337 void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
338
339 void dump(const Counter &C, raw_ostream &OS) const;
340 void dump(const Counter &C) const { dump(C, dbgs()); }
341
342 /// Return the number of times that a region of code associated with this
343 /// counter was executed.
344 Expected<int64_t> evaluate(const Counter &C) const;
345
346 unsigned getMaxCounterID(const Counter &C) const;
347};
348
349/// Code coverage information for a single function.
351 /// Raw function name.
352 std::string Name;
353 /// Mapping from FileID (i.e. vector index) to filename. Used to support
354 /// macro expansions within a function in which the macro and function are
355 /// defined in separate files.
356 ///
357 /// TODO: Uniquing filenames across all function records may be a performance
358 /// optimization.
359 std::vector<std::string> Filenames;
360 /// Regions in the function along with their counts.
361 std::vector<CountedRegion> CountedRegions;
362 /// Branch Regions in the function along with their counts.
363 std::vector<CountedRegion> CountedBranchRegions;
364 /// The number of times this function was executed.
366
368 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
369
372
374 uint64_t FalseCount) {
376 CountedBranchRegions.emplace_back(Region, Count, FalseCount);
377 // If both counters are hard-coded to zero, then this region represents a
378 // constant-folded branch.
379 if (Region.Count.isZero() && Region.FalseCount.isZero())
380 CountedBranchRegions.back().Folded = true;
381 return;
382 }
383 if (CountedRegions.empty())
384 ExecutionCount = Count;
385 CountedRegions.emplace_back(Region, Count, FalseCount);
386 }
387};
388
389/// Iterator over Functions, optionally filtered to a single file.
391 : public iterator_facade_base<FunctionRecordIterator,
392 std::forward_iterator_tag, FunctionRecord> {
395 StringRef Filename;
396
397 /// Skip records whose primary file is not \c Filename.
398 void skipOtherFiles();
399
400public:
402 StringRef Filename = "")
403 : Records(Records_), Current(Records.begin()), Filename(Filename) {
404 skipOtherFiles();
405 }
406
407 FunctionRecordIterator() : Current(Records.begin()) {}
408
410 return Current == RHS.Current && Filename == RHS.Filename;
411 }
412
413 const FunctionRecord &operator*() const { return *Current; }
414
416 assert(Current != Records.end() && "incremented past end");
417 ++Current;
418 skipOtherFiles();
419 return *this;
420 }
421};
422
423/// Coverage information for a macro expansion or #included file.
424///
425/// When covered code has pieces that can be expanded for more detail, such as a
426/// preprocessor macro use and its definition, these are represented as
427/// expansions whose coverage can be looked up independently.
429 /// The abstract file this expansion covers.
430 unsigned FileID;
431 /// The region that expands to this record.
433 /// Coverage for the expansion.
435
438 : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
439};
440
441/// The execution count information starting at a point in a file.
442///
443/// A sequence of CoverageSegments gives execution counts for a file in format
444/// that's simple to iterate through for processing.
446 /// The line where this segment begins.
447 unsigned Line;
448 /// The column where this segment begins.
449 unsigned Col;
450 /// The execution count, or zero if no count was recorded.
452 /// When false, the segment was uninstrumented or skipped.
454 /// Whether this enters a new region or returns to a previous count.
456 /// Whether this enters a gap region.
458
459 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
460 : Line(Line), Col(Col), Count(0), HasCount(false),
462
463 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
464 bool IsRegionEntry, bool IsGapRegion = false,
465 bool IsBranchRegion = false)
468
469 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
470 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry,
471 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count,
472 R.HasCount, R.IsRegionEntry,
473 R.IsGapRegion);
474 }
475};
476
477/// An instantiation group contains a \c FunctionRecord list, such that each
478/// record corresponds to a distinct instantiation of the same function.
479///
480/// Note that it's possible for a function to have more than one instantiation
481/// (consider C++ template specializations or static inline functions).
483 friend class CoverageMapping;
484
485 unsigned Line;
486 unsigned Col;
487 std::vector<const FunctionRecord *> Instantiations;
488
489 InstantiationGroup(unsigned Line, unsigned Col,
490 std::vector<const FunctionRecord *> Instantiations)
491 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {}
492
493public:
496
497 /// Get the number of instantiations in this group.
498 size_t size() const { return Instantiations.size(); }
499
500 /// Get the line where the common function was defined.
501 unsigned getLine() const { return Line; }
502
503 /// Get the column where the common function was defined.
504 unsigned getColumn() const { return Col; }
505
506 /// Check if the instantiations in this group have a common mangled name.
507 bool hasName() const {
508 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I)
509 if (Instantiations[I]->Name != Instantiations[0]->Name)
510 return false;
511 return true;
512 }
513
514 /// Get the common mangled name for instantiations in this group.
516 assert(hasName() && "Instantiations don't have a shared name");
517 return Instantiations[0]->Name;
518 }
519
520 /// Get the total execution count of all instantiations in this group.
522 uint64_t Count = 0;
523 for (const FunctionRecord *F : Instantiations)
524 Count += F->ExecutionCount;
525 return Count;
526 }
527
528 /// Get the instantiations in this group.
530 return Instantiations;
531 }
532};
533
534/// Coverage information to be processed or displayed.
535///
536/// This represents the coverage of an entire file, expansion, or function. It
537/// provides a sequence of CoverageSegments to iterate through, as well as the
538/// list of expansions that can be further processed.
540 friend class CoverageMapping;
541
542 std::string Filename;
543 std::vector<CoverageSegment> Segments;
544 std::vector<ExpansionRecord> Expansions;
545 std::vector<CountedRegion> BranchRegions;
546
547public:
548 CoverageData() = default;
549
550 CoverageData(StringRef Filename) : Filename(Filename) {}
551
552 /// Get the name of the file this data covers.
553 StringRef getFilename() const { return Filename; }
554
555 /// Get an iterator over the coverage segments for this object. The segments
556 /// are guaranteed to be uniqued and sorted by location.
557 std::vector<CoverageSegment>::const_iterator begin() const {
558 return Segments.begin();
559 }
560
561 std::vector<CoverageSegment>::const_iterator end() const {
562 return Segments.end();
563 }
564
565 bool empty() const { return Segments.empty(); }
566
567 /// Expansions that can be further processed.
568 ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
569
570 /// Branches that can be further processed.
571 ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
572};
573
574/// The mapping of profile information to coverage data.
575///
576/// This is the main interface to get coverage information, using a profile to
577/// fill out execution counts.
579 DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
580 std::vector<FunctionRecord> Functions;
581 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
582 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
583
584 CoverageMapping() = default;
585
586 // Load coverage records from readers.
587 static Error loadFromReaders(
588 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
589 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage);
590
591 // Load coverage records from file.
592 static Error
593 loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
594 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage,
595 bool &DataFound,
596 SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
597
598 /// Add a function record corresponding to \p Record.
599 Error loadFunctionRecord(const CoverageMappingRecord &Record,
600 IndexedInstrProfReader &ProfileReader);
601
602 /// Look up the indices for function records which are at least partially
603 /// defined in the specified file. This is guaranteed to return a superset of
604 /// such records: extra records not in the file may be included if there is
605 /// a hash collision on the filename. Clients must be robust to collisions.
607 getImpreciseRecordIndicesForFilename(StringRef Filename) const;
608
609public:
612
613 /// Load the coverage mapping using the given readers.
615 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
616 IndexedInstrProfReader &ProfileReader);
617
618 /// Load the coverage mapping from the given object files and profile. If
619 /// \p Arches is non-empty, it must specify an architecture for each object.
620 /// Ignores non-instrumented object files unless all are not instrumented.
622 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
623 vfs::FileSystem &FS, ArrayRef<StringRef> Arches = std::nullopt,
624 StringRef CompilationDir = "",
625 const object::BuildIDFetcher *BIDFetcher = nullptr,
626 bool CheckBinaryIDs = false);
627
628 /// The number of functions that couldn't have their profiles mapped.
629 ///
630 /// This is a count of functions whose profile is out of date or otherwise
631 /// can't be associated with any coverage information.
632 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
633
634 /// A hash mismatch occurs when a profile record for a symbol does not have
635 /// the same hash as a coverage mapping record for the same symbol. This
636 /// returns a list of hash mismatches, where each mismatch is a pair of the
637 /// symbol name and its coverage mapping hash.
639 return FuncHashMismatches;
640 }
641
642 /// Returns a lexicographically sorted, unique list of files that are
643 /// covered.
644 std::vector<StringRef> getUniqueSourceFiles() const;
645
646 /// Get the coverage for a particular file.
647 ///
648 /// The given filename must be the name as recorded in the coverage
649 /// information. That is, only names returned from getUniqueSourceFiles will
650 /// yield a result.
652
653 /// Get the coverage for a particular function.
655
656 /// Get the coverage for an expansion within a coverage set.
658
659 /// Gets all of the functions covered by this profile.
661 return make_range(FunctionRecordIterator(Functions),
663 }
664
665 /// Gets all of the functions in a particular file.
668 return make_range(FunctionRecordIterator(Functions, Filename),
670 }
671
672 /// Get the list of function instantiation groups in a particular file.
673 ///
674 /// Every instantiation group in a program is attributed to exactly one file:
675 /// the file in which the definition for the common function begins.
676 std::vector<InstantiationGroup>
677 getInstantiationGroups(StringRef Filename) const;
678};
679
680/// Coverage statistics for a single line.
682 uint64_t ExecutionCount;
683 bool HasMultipleRegions;
684 bool Mapped;
685 unsigned Line;
687 const CoverageSegment *WrappedSegment;
688
690 LineCoverageStats() = default;
691
692public:
694 const CoverageSegment *WrappedSegment, unsigned Line);
695
696 uint64_t getExecutionCount() const { return ExecutionCount; }
697
698 bool hasMultipleRegions() const { return HasMultipleRegions; }
699
700 bool isMapped() const { return Mapped; }
701
702 unsigned getLine() const { return Line; }
703
705 return LineSegments;
706 }
707
708 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
709};
710
711/// An iterator over the \c LineCoverageStats objects for lines described by
712/// a \c CoverageData instance.
714 : public iterator_facade_base<LineCoverageIterator,
715 std::forward_iterator_tag,
716 const LineCoverageStats> {
717public:
719 : LineCoverageIterator(CD, CD.begin()->Line) {}
720
721 LineCoverageIterator(const CoverageData &CD, unsigned Line)
722 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
723 Line(Line) {
724 this->operator++();
725 }
726
727 bool operator==(const LineCoverageIterator &R) const {
728 return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
729 }
730
731 const LineCoverageStats &operator*() const { return Stats; }
732
734
736 auto EndIt = *this;
737 EndIt.Next = CD.end();
738 EndIt.Ended = true;
739 return EndIt;
740 }
741
742private:
743 const CoverageData &CD;
744 const CoverageSegment *WrappedSegment;
745 std::vector<CoverageSegment>::const_iterator Next;
746 bool Ended;
747 unsigned Line;
749 LineCoverageStats Stats;
750};
751
752/// Get a \c LineCoverageIterator range for the lines described by \p CD.
755 auto Begin = LineCoverageIterator(CD);
756 auto End = Begin.getEnd();
757 return make_range(Begin, End);
758}
759
760// Coverage mappping data (V2) has the following layout:
761// IPSK_covmap:
762// [CoverageMapFileHeader]
763// [ArrayStart]
764// [CovMapFunctionRecordV2]
765// [CovMapFunctionRecordV2]
766// ...
767// [ArrayEnd]
768// [Encoded Filenames and Region Mapping Data]
769//
770// Coverage mappping data (V3) has the following layout:
771// IPSK_covmap:
772// [CoverageMapFileHeader]
773// [Encoded Filenames]
774// IPSK_covfun:
775// [ArrayStart]
776// odr_name_1: [CovMapFunctionRecordV3]
777// odr_name_2: [CovMapFunctionRecordV3]
778// ...
779// [ArrayEnd]
780//
781// Both versions of the coverage mapping format encode the same information,
782// but the V3 format does so more compactly by taking advantage of linkonce_odr
783// semantics (it allows exactly 1 function record per name reference).
784
785/// This namespace defines accessors shared by different versions of coverage
786/// mapping records.
787namespace accessors {
788
789/// Return the structural hash associated with the function.
790template <class FuncRecordTy, support::endianness Endian>
791uint64_t getFuncHash(const FuncRecordTy *Record) {
792 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
793}
794
795/// Return the coverage map data size for the function.
796template <class FuncRecordTy, support::endianness Endian>
797uint64_t getDataSize(const FuncRecordTy *Record) {
798 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
799}
800
801/// Return the function lookup key. The value is considered opaque.
802template <class FuncRecordTy, support::endianness Endian>
803uint64_t getFuncNameRef(const FuncRecordTy *Record) {
804 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
805}
806
807/// Return the PGO name of the function. Used for formats in which the name is
808/// a hash.
809template <class FuncRecordTy, support::endianness Endian>
810Error getFuncNameViaRef(const FuncRecordTy *Record,
811 InstrProfSymtab &ProfileNames, StringRef &FuncName) {
812 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
813 FuncName = ProfileNames.getFuncName(NameRef);
814 return Error::success();
815}
816
817/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
818/// coverage mapping is attached to the file header, instead of to the function
819/// record.
820template <class FuncRecordTy, support::endianness Endian>
822 const char *MappingBuf) {
823 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
824}
825
826/// Advance to the next out-of-line coverage mapping and its associated
827/// function record.
828template <class FuncRecordTy, support::endianness Endian>
829std::pair<const char *, const FuncRecordTy *>
830advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
831 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
832}
833
834} // end namespace accessors
835
837template <class IntPtrT>
840
841#define COVMAP_V1
842#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
844#undef COVMAP_V1
846
847 template <support::endianness Endian> uint64_t getFuncHash() const {
848 return accessors::getFuncHash<ThisT, Endian>(this);
849 }
850
851 template <support::endianness Endian> uint64_t getDataSize() const {
852 return accessors::getDataSize<ThisT, Endian>(this);
853 }
854
855 /// Return function lookup key. The value is consider opaque.
856 template <support::endianness Endian> IntPtrT getFuncNameRef() const {
857 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
858 }
859
860 /// Return the PGO name of the function.
861 template <support::endianness Endian>
862 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
863 IntPtrT NameRef = getFuncNameRef<Endian>();
864 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
865 FuncName = ProfileNames.getFuncName(NameRef, NameS);
866 if (NameS && FuncName.empty())
867 return make_error<CoverageMapError>(coveragemap_error::malformed);
868 return Error::success();
869 }
870
871 template <support::endianness Endian>
872 std::pair<const char *, const ThisT *>
873 advanceByOne(const char *MappingBuf) const {
874 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
875 }
876
877 template <support::endianness Endian> uint64_t getFilenamesRef() const {
878 llvm_unreachable("V1 function format does not contain a filenames ref");
879 }
880
881 template <support::endianness Endian>
882 StringRef getCoverageMapping(const char *MappingBuf) const {
883 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
884 MappingBuf);
885 }
886};
887
890
891#define COVMAP_V2
892#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
894#undef COVMAP_V2
896
897 template <support::endianness Endian> uint64_t getFuncHash() const {
898 return accessors::getFuncHash<ThisT, Endian>(this);
899 }
900
901 template <support::endianness Endian> uint64_t getDataSize() const {
902 return accessors::getDataSize<ThisT, Endian>(this);
903 }
904
905 template <support::endianness Endian> uint64_t getFuncNameRef() const {
906 return accessors::getFuncNameRef<ThisT, Endian>(this);
907 }
908
909 template <support::endianness Endian>
910 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
911 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
912 FuncName);
913 }
914
915 template <support::endianness Endian>
916 std::pair<const char *, const ThisT *>
917 advanceByOne(const char *MappingBuf) const {
918 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
919 }
920
921 template <support::endianness Endian> uint64_t getFilenamesRef() const {
922 llvm_unreachable("V2 function format does not contain a filenames ref");
923 }
924
925 template <support::endianness Endian>
926 StringRef getCoverageMapping(const char *MappingBuf) const {
927 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
928 MappingBuf);
929 }
930};
931
934
935#define COVMAP_V3
936#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
938#undef COVMAP_V3
940
941 template <support::endianness Endian> uint64_t getFuncHash() const {
942 return accessors::getFuncHash<ThisT, Endian>(this);
943 }
944
945 template <support::endianness Endian> uint64_t getDataSize() const {
946 return accessors::getDataSize<ThisT, Endian>(this);
947 }
948
949 template <support::endianness Endian> uint64_t getFuncNameRef() const {
950 return accessors::getFuncNameRef<ThisT, Endian>(this);
951 }
952
953 template <support::endianness Endian>
954 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
955 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
956 FuncName);
957 }
958
959 /// Get the filename set reference.
960 template <support::endianness Endian> uint64_t getFilenamesRef() const {
961 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
962 }
963
964 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
965 /// out-of-line coverage mapping data only.
966 template <support::endianness Endian>
967 StringRef getCoverageMapping(const char *) const {
968 return StringRef(&CoverageMapping, getDataSize<Endian>());
969 }
970
971 // Advance to the next inline coverage mapping and its associated function
972 // record. Ignore the out-of-line coverage mapping buffer.
973 template <support::endianness Endian>
974 std::pair<const char *, const CovMapFunctionRecordV3 *>
975 advanceByOne(const char *) const {
976 assert(isAddrAligned(Align(8), this) && "Function record not aligned");
977 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
978 sizeof(char) + getDataSize<Endian>();
979 // Each function record has an alignment of 8, so we need to adjust
980 // alignment before reading the next record.
981 Next += offsetToAlignedAddr(Next, Align(8));
982 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
983 }
984};
985
986// Per module coverage mapping data header, i.e. CoverageMapFileHeader
987// documented above.
989#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
991 template <support::endianness Endian> uint32_t getNRecords() const {
992 return support::endian::byte_swap<uint32_t, Endian>(NRecords);
993 }
994
995 template <support::endianness Endian> uint32_t getFilenamesSize() const {
996 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
997 }
998
999 template <support::endianness Endian> uint32_t getCoverageSize() const {
1000 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
1001 }
1002
1003 template <support::endianness Endian> uint32_t getVersion() const {
1004 return support::endian::byte_swap<uint32_t, Endian>(Version);
1005 }
1006};
1007
1009
1012 // Function's name reference from CovMapFuncRecord is changed from raw
1013 // name string pointer to MD5 to support name section compression. Name
1014 // section is also compressed.
1016 // A new interpretation of the columnEnd field is added in order to mark
1017 // regions as gap areas.
1019 // Function records are named, uniqued, and moved to a dedicated section.
1021 // Branch regions referring to two counters are added
1023 // Compilation directory is stored separately and combined with relative
1024 // filenames to produce an absolute file path.
1026 // The current version is Version6.
1027 CurrentVersion = INSTR_PROF_COVMAP_VERSION
1029
1030template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1033};
1034
1035template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1038};
1039
1040template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1043};
1044
1045template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1048};
1049
1050} // end namespace coverage
1051
1052/// Provide DenseMapInfo for CounterExpression
1053template<> struct DenseMapInfo<coverage::CounterExpression> {
1055 using namespace coverage;
1056
1057 return CounterExpression(CounterExpression::ExprKind::Subtract,
1058 Counter::getCounter(~0U),
1059 Counter::getCounter(~0U));
1060 }
1061
1063 using namespace coverage;
1064
1065 return CounterExpression(CounterExpression::ExprKind::Add,
1066 Counter::getCounter(~0U),
1067 Counter::getCounter(~0U));
1068 }
1069
1070 static unsigned getHashValue(const coverage::CounterExpression &V) {
1071 return static_cast<unsigned>(
1072 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
1073 V.RHS.getKind(), V.RHS.getCounterID()));
1074 }
1075
1078 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1079 }
1080};
1081
1082} // end namespace llvm
1083
1084#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
basic Basic Alias true
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_PACKED_END
Definition: Compiler.h:386
#define LLVM_PACKED_START
Definition: Compiler.h:385
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
std::string Name
bool End
Definition: ELF_riscv.cpp:464
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
iterator end() const
Definition: ArrayRef.h:152
Base class for user error types.
Definition: Error.h:348
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Class representing an expression and its matching format.
Reader for the indexed binary instrprof format.
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
Definition: InstrProf.h:469
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
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...
CounterMappingContext(ArrayRef< CounterExpression > Expressions, ArrayRef< uint64_t > CounterValues=std::nullopt)
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.
unsigned getMaxCounterID(const Counter &C) const
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.
CoverageData(StringRef Filename)
std::string message() const override
Return the error message as a string.
CoverageMapError(coveragemap_error Err)
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.
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
static Expected< std::unique_ptr< CoverageMapping > > load(ArrayRef< std::unique_ptr< CoverageMappingReader > > CoverageReaders, IndexedInstrProfReader &ProfileReader)
Load the coverage mapping using the given readers.
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
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.
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.
std::pair< unsigned, unsigned > LineColPair
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1946
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:613
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition: Alignment.h:150
Definition: BitVector.h:858
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:51
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.
static CounterMappingRegion makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
static CounterMappingRegion makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd)
CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
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)
static CounterMappingRegion makeRegion(Counter Count, 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).
@ ExpansionRegion
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
@ 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
uint32_t getCoverageSize() const
uint32_t getFilenamesSize() 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
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)