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:
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.
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
627 /// The number of functions that couldn't have their profiles mapped.
628 ///
629 /// This is a count of functions whose profile is out of date or otherwise
630 /// can't be associated with any coverage information.
631 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
632
633 /// A hash mismatch occurs when a profile record for a symbol does not have
634 /// the same hash as a coverage mapping record for the same symbol. This
635 /// returns a list of hash mismatches, where each mismatch is a pair of the
636 /// symbol name and its coverage mapping hash.
638 return FuncHashMismatches;
639 }
640
641 /// Returns a lexicographically sorted, unique list of files that are
642 /// covered.
643 std::vector<StringRef> getUniqueSourceFiles() const;
644
645 /// Get the coverage for a particular file.
646 ///
647 /// The given filename must be the name as recorded in the coverage
648 /// information. That is, only names returned from getUniqueSourceFiles will
649 /// yield a result.
651
652 /// Get the coverage for a particular function.
654
655 /// Get the coverage for an expansion within a coverage set.
657
658 /// Gets all of the functions covered by this profile.
660 return make_range(FunctionRecordIterator(Functions),
662 }
663
664 /// Gets all of the functions in a particular file.
667 return make_range(FunctionRecordIterator(Functions, Filename),
669 }
670
671 /// Get the list of function instantiation groups in a particular file.
672 ///
673 /// Every instantiation group in a program is attributed to exactly one file:
674 /// the file in which the definition for the common function begins.
675 std::vector<InstantiationGroup>
676 getInstantiationGroups(StringRef Filename) const;
677};
678
679/// Coverage statistics for a single line.
681 uint64_t ExecutionCount;
682 bool HasMultipleRegions;
683 bool Mapped;
684 unsigned Line;
686 const CoverageSegment *WrappedSegment;
687
689 LineCoverageStats() = default;
690
691public:
693 const CoverageSegment *WrappedSegment, unsigned Line);
694
695 uint64_t getExecutionCount() const { return ExecutionCount; }
696
697 bool hasMultipleRegions() const { return HasMultipleRegions; }
698
699 bool isMapped() const { return Mapped; }
700
701 unsigned getLine() const { return Line; }
702
704 return LineSegments;
705 }
706
707 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
708};
709
710/// An iterator over the \c LineCoverageStats objects for lines described by
711/// a \c CoverageData instance.
713 : public iterator_facade_base<LineCoverageIterator,
714 std::forward_iterator_tag,
715 const LineCoverageStats> {
716public:
718 : LineCoverageIterator(CD, CD.begin()->Line) {}
719
720 LineCoverageIterator(const CoverageData &CD, unsigned Line)
721 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
722 Line(Line) {
723 this->operator++();
724 }
725
726 bool operator==(const LineCoverageIterator &R) const {
727 return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
728 }
729
730 const LineCoverageStats &operator*() const { return Stats; }
731
733
735 auto EndIt = *this;
736 EndIt.Next = CD.end();
737 EndIt.Ended = true;
738 return EndIt;
739 }
740
741private:
742 const CoverageData &CD;
743 const CoverageSegment *WrappedSegment;
744 std::vector<CoverageSegment>::const_iterator Next;
745 bool Ended;
746 unsigned Line;
748 LineCoverageStats Stats;
749};
750
751/// Get a \c LineCoverageIterator range for the lines described by \p CD.
754 auto Begin = LineCoverageIterator(CD);
755 auto End = Begin.getEnd();
756 return make_range(Begin, End);
757}
758
759// Coverage mappping data (V2) has the following layout:
760// IPSK_covmap:
761// [CoverageMapFileHeader]
762// [ArrayStart]
763// [CovMapFunctionRecordV2]
764// [CovMapFunctionRecordV2]
765// ...
766// [ArrayEnd]
767// [Encoded Filenames and Region Mapping Data]
768//
769// Coverage mappping data (V3) has the following layout:
770// IPSK_covmap:
771// [CoverageMapFileHeader]
772// [Encoded Filenames]
773// IPSK_covfun:
774// [ArrayStart]
775// odr_name_1: [CovMapFunctionRecordV3]
776// odr_name_2: [CovMapFunctionRecordV3]
777// ...
778// [ArrayEnd]
779//
780// Both versions of the coverage mapping format encode the same information,
781// but the V3 format does so more compactly by taking advantage of linkonce_odr
782// semantics (it allows exactly 1 function record per name reference).
783
784/// This namespace defines accessors shared by different versions of coverage
785/// mapping records.
786namespace accessors {
787
788/// Return the structural hash associated with the function.
789template <class FuncRecordTy, support::endianness Endian>
790uint64_t getFuncHash(const FuncRecordTy *Record) {
791 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
792}
793
794/// Return the coverage map data size for the function.
795template <class FuncRecordTy, support::endianness Endian>
796uint64_t getDataSize(const FuncRecordTy *Record) {
797 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
798}
799
800/// Return the function lookup key. The value is considered opaque.
801template <class FuncRecordTy, support::endianness Endian>
802uint64_t getFuncNameRef(const FuncRecordTy *Record) {
803 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
804}
805
806/// Return the PGO name of the function. Used for formats in which the name is
807/// a hash.
808template <class FuncRecordTy, support::endianness Endian>
809Error getFuncNameViaRef(const FuncRecordTy *Record,
810 InstrProfSymtab &ProfileNames, StringRef &FuncName) {
811 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
812 FuncName = ProfileNames.getFuncName(NameRef);
813 return Error::success();
814}
815
816/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
817/// coverage mapping is attached to the file header, instead of to the function
818/// record.
819template <class FuncRecordTy, support::endianness Endian>
821 const char *MappingBuf) {
822 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
823}
824
825/// Advance to the next out-of-line coverage mapping and its associated
826/// function record.
827template <class FuncRecordTy, support::endianness Endian>
828std::pair<const char *, const FuncRecordTy *>
829advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
830 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
831}
832
833} // end namespace accessors
834
836template <class IntPtrT>
839
840#define COVMAP_V1
841#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
843#undef COVMAP_V1
845
846 template <support::endianness Endian> uint64_t getFuncHash() const {
847 return accessors::getFuncHash<ThisT, Endian>(this);
848 }
849
850 template <support::endianness Endian> uint64_t getDataSize() const {
851 return accessors::getDataSize<ThisT, Endian>(this);
852 }
853
854 /// Return function lookup key. The value is consider opaque.
855 template <support::endianness Endian> IntPtrT getFuncNameRef() const {
856 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
857 }
858
859 /// Return the PGO name of the function.
860 template <support::endianness Endian>
861 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
862 IntPtrT NameRef = getFuncNameRef<Endian>();
863 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
864 FuncName = ProfileNames.getFuncName(NameRef, NameS);
865 if (NameS && FuncName.empty())
866 return make_error<CoverageMapError>(coveragemap_error::malformed);
867 return Error::success();
868 }
869
870 template <support::endianness Endian>
871 std::pair<const char *, const ThisT *>
872 advanceByOne(const char *MappingBuf) const {
873 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
874 }
875
876 template <support::endianness Endian> uint64_t getFilenamesRef() const {
877 llvm_unreachable("V1 function format does not contain a filenames ref");
878 }
879
880 template <support::endianness Endian>
881 StringRef getCoverageMapping(const char *MappingBuf) const {
882 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
883 MappingBuf);
884 }
885};
886
889
890#define COVMAP_V2
891#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
893#undef COVMAP_V2
895
896 template <support::endianness Endian> uint64_t getFuncHash() const {
897 return accessors::getFuncHash<ThisT, Endian>(this);
898 }
899
900 template <support::endianness Endian> uint64_t getDataSize() const {
901 return accessors::getDataSize<ThisT, Endian>(this);
902 }
903
904 template <support::endianness Endian> uint64_t getFuncNameRef() const {
905 return accessors::getFuncNameRef<ThisT, Endian>(this);
906 }
907
908 template <support::endianness Endian>
909 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
910 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
911 FuncName);
912 }
913
914 template <support::endianness Endian>
915 std::pair<const char *, const ThisT *>
916 advanceByOne(const char *MappingBuf) const {
917 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
918 }
919
920 template <support::endianness Endian> uint64_t getFilenamesRef() const {
921 llvm_unreachable("V2 function format does not contain a filenames ref");
922 }
923
924 template <support::endianness Endian>
925 StringRef getCoverageMapping(const char *MappingBuf) const {
926 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
927 MappingBuf);
928 }
929};
930
933
934#define COVMAP_V3
935#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
937#undef COVMAP_V3
939
940 template <support::endianness Endian> uint64_t getFuncHash() const {
941 return accessors::getFuncHash<ThisT, Endian>(this);
942 }
943
944 template <support::endianness Endian> uint64_t getDataSize() const {
945 return accessors::getDataSize<ThisT, Endian>(this);
946 }
947
948 template <support::endianness Endian> uint64_t getFuncNameRef() const {
949 return accessors::getFuncNameRef<ThisT, Endian>(this);
950 }
951
952 template <support::endianness Endian>
953 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
954 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
955 FuncName);
956 }
957
958 /// Get the filename set reference.
959 template <support::endianness Endian> uint64_t getFilenamesRef() const {
960 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
961 }
962
963 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
964 /// out-of-line coverage mapping data only.
965 template <support::endianness Endian>
966 StringRef getCoverageMapping(const char *) const {
967 return StringRef(&CoverageMapping, getDataSize<Endian>());
968 }
969
970 // Advance to the next inline coverage mapping and its associated function
971 // record. Ignore the out-of-line coverage mapping buffer.
972 template <support::endianness Endian>
973 std::pair<const char *, const CovMapFunctionRecordV3 *>
974 advanceByOne(const char *) const {
975 assert(isAddrAligned(Align(8), this) && "Function record not aligned");
976 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
977 sizeof(char) + getDataSize<Endian>();
978 // Each function record has an alignment of 8, so we need to adjust
979 // alignment before reading the next record.
980 Next += offsetToAlignedAddr(Next, Align(8));
981 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
982 }
983};
984
985// Per module coverage mapping data header, i.e. CoverageMapFileHeader
986// documented above.
988#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
990 template <support::endianness Endian> uint32_t getNRecords() const {
991 return support::endian::byte_swap<uint32_t, Endian>(NRecords);
992 }
993
994 template <support::endianness Endian> uint32_t getFilenamesSize() const {
995 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
996 }
997
998 template <support::endianness Endian> uint32_t getCoverageSize() const {
999 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
1000 }
1001
1002 template <support::endianness Endian> uint32_t getVersion() const {
1003 return support::endian::byte_swap<uint32_t, Endian>(Version);
1004 }
1005};
1006
1008
1011 // Function's name reference from CovMapFuncRecord is changed from raw
1012 // name string pointer to MD5 to support name section compression. Name
1013 // section is also compressed.
1015 // A new interpretation of the columnEnd field is added in order to mark
1016 // regions as gap areas.
1018 // Function records are named, uniqued, and moved to a dedicated section.
1020 // Branch regions referring to two counters are added
1022 // Compilation directory is stored separately and combined with relative
1023 // filenames to produce an absolute file path.
1025 // The current version is Version6.
1026 CurrentVersion = INSTR_PROF_COVMAP_VERSION
1028
1029template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1032};
1033
1034template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1037};
1038
1039template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1042};
1043
1044template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1047};
1048
1049} // end namespace coverage
1050
1051/// Provide DenseMapInfo for CounterExpression
1052template<> struct DenseMapInfo<coverage::CounterExpression> {
1054 using namespace coverage;
1055
1056 return CounterExpression(CounterExpression::ExprKind::Subtract,
1057 Counter::getCounter(~0U),
1058 Counter::getCounter(~0U));
1059 }
1060
1062 using namespace coverage;
1063
1064 return CounterExpression(CounterExpression::ExprKind::Add,
1065 Counter::getCounter(~0U),
1066 Counter::getCounter(~0U));
1067 }
1068
1069 static unsigned getHashValue(const coverage::CounterExpression &V) {
1070 return static_cast<unsigned>(
1072 V.RHS.getKind(), V.RHS.getCounterID()));
1073 }
1074
1077 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1078 }
1079};
1080
1081} // end namespace llvm
1082
1083#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
assume Assume Simplify
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
gvn Early GVN Hoisting of Expressions
Definition: GVNHoist.cpp:1265
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())
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:446
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:36
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:1862
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:608
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition: Alignment.h:150
Definition: BitVector.h:851
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)