CoverageMapping.h revision 353358
1321369Sdim//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// Code coverage mapping data is generated by clang and read by 10303231Sdim// llvm-cov to show code coverage statistics for a file. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14321369Sdim#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 15321369Sdim#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 16303231Sdim 17303231Sdim#include "llvm/ADT/ArrayRef.h" 18303231Sdim#include "llvm/ADT/DenseMap.h" 19341825Sdim#include "llvm/ADT/DenseSet.h" 20303231Sdim#include "llvm/ADT/Hashing.h" 21321369Sdim#include "llvm/ADT/None.h" 22321369Sdim#include "llvm/ADT/StringRef.h" 23314564Sdim#include "llvm/ADT/StringSet.h" 24303231Sdim#include "llvm/ADT/iterator.h" 25321369Sdim#include "llvm/ADT/iterator_range.h" 26303231Sdim#include "llvm/ProfileData/InstrProf.h" 27321369Sdim#include "llvm/Support/Compiler.h" 28303231Sdim#include "llvm/Support/Debug.h" 29303231Sdim#include "llvm/Support/Endian.h" 30321369Sdim#include "llvm/Support/Error.h" 31303231Sdim#include "llvm/Support/raw_ostream.h" 32321369Sdim#include <cassert> 33321369Sdim#include <cstdint> 34321369Sdim#include <iterator> 35321369Sdim#include <memory> 36321369Sdim#include <string> 37303231Sdim#include <system_error> 38303231Sdim#include <tuple> 39321369Sdim#include <utility> 40321369Sdim#include <vector> 41303231Sdim 42303231Sdimnamespace llvm { 43321369Sdim 44321369Sdimclass IndexedInstrProfReader; 45321369Sdim 46303231Sdimnamespace coverage { 47303231Sdim 48321369Sdimclass CoverageMappingReader; 49321369Sdimstruct CoverageMappingRecord; 50321369Sdim 51303231Sdimenum class coveragemap_error { 52303231Sdim success = 0, 53303231Sdim eof, 54303231Sdim no_data_found, 55303231Sdim unsupported_version, 56303231Sdim truncated, 57303231Sdim malformed 58303231Sdim}; 59303231Sdim 60303231Sdimconst std::error_category &coveragemap_category(); 61303231Sdim 62303231Sdiminline std::error_code make_error_code(coveragemap_error E) { 63303231Sdim return std::error_code(static_cast<int>(E), coveragemap_category()); 64303231Sdim} 65303231Sdim 66303231Sdimclass CoverageMapError : public ErrorInfo<CoverageMapError> { 67303231Sdimpublic: 68303231Sdim CoverageMapError(coveragemap_error Err) : Err(Err) { 69303231Sdim assert(Err != coveragemap_error::success && "Not an error"); 70303231Sdim } 71303231Sdim 72303231Sdim std::string message() const override; 73303231Sdim 74303231Sdim void log(raw_ostream &OS) const override { OS << message(); } 75303231Sdim 76303231Sdim std::error_code convertToErrorCode() const override { 77303231Sdim return make_error_code(Err); 78303231Sdim } 79303231Sdim 80303231Sdim coveragemap_error get() const { return Err; } 81303231Sdim 82303231Sdim static char ID; 83303231Sdim 84303231Sdimprivate: 85303231Sdim coveragemap_error Err; 86303231Sdim}; 87303231Sdim 88327952Sdim/// A Counter is an abstract value that describes how to compute the 89303231Sdim/// execution count for a region of code using the collected profile count data. 90303231Sdimstruct Counter { 91303231Sdim enum CounterKind { Zero, CounterValueReference, Expression }; 92303231Sdim static const unsigned EncodingTagBits = 2; 93303231Sdim static const unsigned EncodingTagMask = 0x3; 94303231Sdim static const unsigned EncodingCounterTagAndExpansionRegionTagBits = 95303231Sdim EncodingTagBits + 1; 96303231Sdim 97303231Sdimprivate: 98321369Sdim CounterKind Kind = Zero; 99321369Sdim unsigned ID = 0; 100303231Sdim 101303231Sdim Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} 102303231Sdim 103303231Sdimpublic: 104321369Sdim Counter() = default; 105303231Sdim 106303231Sdim CounterKind getKind() const { return Kind; } 107303231Sdim 108303231Sdim bool isZero() const { return Kind == Zero; } 109303231Sdim 110303231Sdim bool isExpression() const { return Kind == Expression; } 111303231Sdim 112303231Sdim unsigned getCounterID() const { return ID; } 113303231Sdim 114303231Sdim unsigned getExpressionID() const { return ID; } 115303231Sdim 116303231Sdim friend bool operator==(const Counter &LHS, const Counter &RHS) { 117303231Sdim return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; 118303231Sdim } 119303231Sdim 120303231Sdim friend bool operator!=(const Counter &LHS, const Counter &RHS) { 121303231Sdim return !(LHS == RHS); 122303231Sdim } 123303231Sdim 124303231Sdim friend bool operator<(const Counter &LHS, const Counter &RHS) { 125303231Sdim return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); 126303231Sdim } 127303231Sdim 128327952Sdim /// Return the counter that represents the number zero. 129303231Sdim static Counter getZero() { return Counter(); } 130303231Sdim 131327952Sdim /// Return the counter that corresponds to a specific profile counter. 132303231Sdim static Counter getCounter(unsigned CounterId) { 133303231Sdim return Counter(CounterValueReference, CounterId); 134303231Sdim } 135303231Sdim 136327952Sdim /// Return the counter that corresponds to a specific addition counter 137327952Sdim /// expression. 138303231Sdim static Counter getExpression(unsigned ExpressionId) { 139303231Sdim return Counter(Expression, ExpressionId); 140303231Sdim } 141303231Sdim}; 142303231Sdim 143327952Sdim/// A Counter expression is a value that represents an arithmetic operation 144327952Sdim/// with two counters. 145303231Sdimstruct CounterExpression { 146303231Sdim enum ExprKind { Subtract, Add }; 147303231Sdim ExprKind Kind; 148303231Sdim Counter LHS, RHS; 149303231Sdim 150303231Sdim CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) 151303231Sdim : Kind(Kind), LHS(LHS), RHS(RHS) {} 152303231Sdim}; 153303231Sdim 154327952Sdim/// A Counter expression builder is used to construct the counter expressions. 155327952Sdim/// It avoids unnecessary duplication and simplifies algebraic expressions. 156303231Sdimclass CounterExpressionBuilder { 157327952Sdim /// A list of all the counter expressions 158303231Sdim std::vector<CounterExpression> Expressions; 159321369Sdim 160327952Sdim /// A lookup table for the index of a given expression. 161321369Sdim DenseMap<CounterExpression, unsigned> ExpressionIndices; 162303231Sdim 163327952Sdim /// Return the counter which corresponds to the given expression. 164303231Sdim /// 165303231Sdim /// If the given expression is already stored in the builder, a counter 166303231Sdim /// that references that expression is returned. Otherwise, the given 167303231Sdim /// expression is added to the builder's collection of expressions. 168303231Sdim Counter get(const CounterExpression &E); 169303231Sdim 170321369Sdim /// Represents a term in a counter expression tree. 171321369Sdim struct Term { 172321369Sdim unsigned CounterID; 173321369Sdim int Factor; 174321369Sdim 175321369Sdim Term(unsigned CounterID, int Factor) 176321369Sdim : CounterID(CounterID), Factor(Factor) {} 177321369Sdim }; 178321369Sdim 179327952Sdim /// Gather the terms of the expression tree for processing. 180303231Sdim /// 181303231Sdim /// This collects each addition and subtraction referenced by the counter into 182303231Sdim /// a sequence that can be sorted and combined to build a simplified counter 183303231Sdim /// expression. 184321369Sdim void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms); 185303231Sdim 186327952Sdim /// Simplifies the given expression tree 187303231Sdim /// by getting rid of algebraically redundant operations. 188303231Sdim Counter simplify(Counter ExpressionTree); 189303231Sdim 190303231Sdimpublic: 191303231Sdim ArrayRef<CounterExpression> getExpressions() const { return Expressions; } 192303231Sdim 193327952Sdim /// Return a counter that represents the expression that adds LHS and RHS. 194303231Sdim Counter add(Counter LHS, Counter RHS); 195303231Sdim 196327952Sdim /// Return a counter that represents the expression that subtracts RHS from 197327952Sdim /// LHS. 198303231Sdim Counter subtract(Counter LHS, Counter RHS); 199303231Sdim}; 200303231Sdim 201327952Sdimusing LineColPair = std::pair<unsigned, unsigned>; 202327952Sdim 203327952Sdim/// A Counter mapping region associates a source range with a specific counter. 204303231Sdimstruct CounterMappingRegion { 205303231Sdim enum RegionKind { 206327952Sdim /// A CodeRegion associates some code with a counter 207303231Sdim CodeRegion, 208303231Sdim 209341825Sdim /// An ExpansionRegion represents a file expansion region that associates 210327952Sdim /// a source range with the expansion of a virtual source file, such as 211327952Sdim /// for a macro instantiation or #include file. 212303231Sdim ExpansionRegion, 213303231Sdim 214327952Sdim /// A SkippedRegion represents a source range with code that was skipped 215327952Sdim /// by a preprocessor or similar means. 216327952Sdim SkippedRegion, 217327952Sdim 218327952Sdim /// A GapRegion is like a CodeRegion, but its count is only set as the 219327952Sdim /// line execution count when its the only region in the line. 220327952Sdim GapRegion 221303231Sdim }; 222303231Sdim 223303231Sdim Counter Count; 224303231Sdim unsigned FileID, ExpandedFileID; 225303231Sdim unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; 226303231Sdim RegionKind Kind; 227303231Sdim 228303231Sdim CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, 229303231Sdim unsigned LineStart, unsigned ColumnStart, 230303231Sdim unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) 231303231Sdim : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), 232303231Sdim LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), 233303231Sdim ColumnEnd(ColumnEnd), Kind(Kind) {} 234303231Sdim 235303231Sdim static CounterMappingRegion 236303231Sdim makeRegion(Counter Count, unsigned FileID, unsigned LineStart, 237303231Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 238303231Sdim return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 239303231Sdim LineEnd, ColumnEnd, CodeRegion); 240303231Sdim } 241303231Sdim 242303231Sdim static CounterMappingRegion 243303231Sdim makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, 244303231Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 245303231Sdim return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, 246303231Sdim ColumnStart, LineEnd, ColumnEnd, 247303231Sdim ExpansionRegion); 248303231Sdim } 249303231Sdim 250303231Sdim static CounterMappingRegion 251303231Sdim makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, 252303231Sdim unsigned LineEnd, unsigned ColumnEnd) { 253303231Sdim return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, 254303231Sdim LineEnd, ColumnEnd, SkippedRegion); 255303231Sdim } 256303231Sdim 257327952Sdim static CounterMappingRegion 258327952Sdim makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, 259327952Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 260327952Sdim return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 261327952Sdim LineEnd, (1U << 31) | ColumnEnd, GapRegion); 262303231Sdim } 263303231Sdim 264327952Sdim inline LineColPair startLoc() const { 265327952Sdim return LineColPair(LineStart, ColumnStart); 266303231Sdim } 267327952Sdim 268327952Sdim inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } 269303231Sdim}; 270303231Sdim 271327952Sdim/// Associates a source range with an execution count. 272303231Sdimstruct CountedRegion : public CounterMappingRegion { 273303231Sdim uint64_t ExecutionCount; 274303231Sdim 275303231Sdim CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) 276303231Sdim : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {} 277303231Sdim}; 278303231Sdim 279327952Sdim/// A Counter mapping context is used to connect the counters, expressions 280327952Sdim/// and the obtained counter values. 281303231Sdimclass CounterMappingContext { 282303231Sdim ArrayRef<CounterExpression> Expressions; 283303231Sdim ArrayRef<uint64_t> CounterValues; 284303231Sdim 285303231Sdimpublic: 286303231Sdim CounterMappingContext(ArrayRef<CounterExpression> Expressions, 287303231Sdim ArrayRef<uint64_t> CounterValues = None) 288303231Sdim : Expressions(Expressions), CounterValues(CounterValues) {} 289303231Sdim 290303231Sdim void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } 291303231Sdim 292321369Sdim void dump(const Counter &C, raw_ostream &OS) const; 293303231Sdim void dump(const Counter &C) const { dump(C, dbgs()); } 294303231Sdim 295327952Sdim /// Return the number of times that a region of code associated with this 296327952Sdim /// counter was executed. 297303231Sdim Expected<int64_t> evaluate(const Counter &C) const; 298303231Sdim}; 299303231Sdim 300327952Sdim/// Code coverage information for a single function. 301303231Sdimstruct FunctionRecord { 302327952Sdim /// Raw function name. 303303231Sdim std::string Name; 304327952Sdim /// Associated files. 305303231Sdim std::vector<std::string> Filenames; 306327952Sdim /// Regions in the function along with their counts. 307303231Sdim std::vector<CountedRegion> CountedRegions; 308327952Sdim /// The number of times this function was executed. 309303231Sdim uint64_t ExecutionCount; 310303231Sdim 311303231Sdim FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 312303231Sdim : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 313303231Sdim 314314564Sdim FunctionRecord(FunctionRecord &&FR) = default; 315314564Sdim FunctionRecord &operator=(FunctionRecord &&) = default; 316314564Sdim 317303231Sdim void pushRegion(CounterMappingRegion Region, uint64_t Count) { 318303231Sdim if (CountedRegions.empty()) 319303231Sdim ExecutionCount = Count; 320303231Sdim CountedRegions.emplace_back(Region, Count); 321303231Sdim } 322303231Sdim}; 323303231Sdim 324327952Sdim/// Iterator over Functions, optionally filtered to a single file. 325303231Sdimclass FunctionRecordIterator 326303231Sdim : public iterator_facade_base<FunctionRecordIterator, 327303231Sdim std::forward_iterator_tag, FunctionRecord> { 328303231Sdim ArrayRef<FunctionRecord> Records; 329303231Sdim ArrayRef<FunctionRecord>::iterator Current; 330303231Sdim StringRef Filename; 331303231Sdim 332327952Sdim /// Skip records whose primary file is not \c Filename. 333303231Sdim void skipOtherFiles(); 334303231Sdim 335303231Sdimpublic: 336303231Sdim FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 337303231Sdim StringRef Filename = "") 338303231Sdim : Records(Records_), Current(Records.begin()), Filename(Filename) { 339303231Sdim skipOtherFiles(); 340303231Sdim } 341303231Sdim 342303231Sdim FunctionRecordIterator() : Current(Records.begin()) {} 343303231Sdim 344303231Sdim bool operator==(const FunctionRecordIterator &RHS) const { 345303231Sdim return Current == RHS.Current && Filename == RHS.Filename; 346303231Sdim } 347303231Sdim 348303231Sdim const FunctionRecord &operator*() const { return *Current; } 349303231Sdim 350303231Sdim FunctionRecordIterator &operator++() { 351303231Sdim assert(Current != Records.end() && "incremented past end"); 352303231Sdim ++Current; 353303231Sdim skipOtherFiles(); 354303231Sdim return *this; 355303231Sdim } 356303231Sdim}; 357303231Sdim 358327952Sdim/// Coverage information for a macro expansion or #included file. 359303231Sdim/// 360303231Sdim/// When covered code has pieces that can be expanded for more detail, such as a 361303231Sdim/// preprocessor macro use and its definition, these are represented as 362303231Sdim/// expansions whose coverage can be looked up independently. 363303231Sdimstruct ExpansionRecord { 364327952Sdim /// The abstract file this expansion covers. 365303231Sdim unsigned FileID; 366327952Sdim /// The region that expands to this record. 367303231Sdim const CountedRegion &Region; 368327952Sdim /// Coverage for the expansion. 369303231Sdim const FunctionRecord &Function; 370303231Sdim 371303231Sdim ExpansionRecord(const CountedRegion &Region, 372303231Sdim const FunctionRecord &Function) 373303231Sdim : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} 374303231Sdim}; 375303231Sdim 376327952Sdim/// The execution count information starting at a point in a file. 377303231Sdim/// 378303231Sdim/// A sequence of CoverageSegments gives execution counts for a file in format 379303231Sdim/// that's simple to iterate through for processing. 380303231Sdimstruct CoverageSegment { 381327952Sdim /// The line where this segment begins. 382303231Sdim unsigned Line; 383327952Sdim /// The column where this segment begins. 384303231Sdim unsigned Col; 385327952Sdim /// The execution count, or zero if no count was recorded. 386303231Sdim uint64_t Count; 387327952Sdim /// When false, the segment was uninstrumented or skipped. 388303231Sdim bool HasCount; 389327952Sdim /// Whether this enters a new region or returns to a previous count. 390303231Sdim bool IsRegionEntry; 391327952Sdim /// Whether this enters a gap region. 392327952Sdim bool IsGapRegion; 393303231Sdim 394303231Sdim CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 395303231Sdim : Line(Line), Col(Col), Count(0), HasCount(false), 396327952Sdim IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 397303231Sdim 398303231Sdim CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 399327952Sdim bool IsRegionEntry, bool IsGapRegion = false) 400303231Sdim : Line(Line), Col(Col), Count(Count), HasCount(true), 401327952Sdim IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 402303231Sdim 403303231Sdim friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { 404327952Sdim return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, 405327952Sdim L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, 406327952Sdim R.HasCount, R.IsRegionEntry, 407327952Sdim R.IsGapRegion); 408303231Sdim } 409303231Sdim}; 410303231Sdim 411327952Sdim/// An instantiation group contains a \c FunctionRecord list, such that each 412327952Sdim/// record corresponds to a distinct instantiation of the same function. 413303231Sdim/// 414327952Sdim/// Note that it's possible for a function to have more than one instantiation 415327952Sdim/// (consider C++ template specializations or static inline functions). 416327952Sdimclass InstantiationGroup { 417327952Sdim friend class CoverageMapping; 418327952Sdim 419327952Sdim unsigned Line; 420327952Sdim unsigned Col; 421327952Sdim std::vector<const FunctionRecord *> Instantiations; 422327952Sdim 423327952Sdim InstantiationGroup(unsigned Line, unsigned Col, 424327952Sdim std::vector<const FunctionRecord *> Instantiations) 425327952Sdim : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} 426327952Sdim 427327952Sdimpublic: 428327952Sdim InstantiationGroup(const InstantiationGroup &) = delete; 429327952Sdim InstantiationGroup(InstantiationGroup &&) = default; 430327952Sdim 431327952Sdim /// Get the number of instantiations in this group. 432327952Sdim size_t size() const { return Instantiations.size(); } 433327952Sdim 434327952Sdim /// Get the line where the common function was defined. 435327952Sdim unsigned getLine() const { return Line; } 436327952Sdim 437327952Sdim /// Get the column where the common function was defined. 438327952Sdim unsigned getColumn() const { return Col; } 439327952Sdim 440327952Sdim /// Check if the instantiations in this group have a common mangled name. 441327952Sdim bool hasName() const { 442327952Sdim for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) 443327952Sdim if (Instantiations[I]->Name != Instantiations[0]->Name) 444327952Sdim return false; 445327952Sdim return true; 446327952Sdim } 447327952Sdim 448327952Sdim /// Get the common mangled name for instantiations in this group. 449327952Sdim StringRef getName() const { 450327952Sdim assert(hasName() && "Instantiations don't have a shared name"); 451327952Sdim return Instantiations[0]->Name; 452327952Sdim } 453327952Sdim 454327952Sdim /// Get the total execution count of all instantiations in this group. 455327952Sdim uint64_t getTotalExecutionCount() const { 456327952Sdim uint64_t Count = 0; 457327952Sdim for (const FunctionRecord *F : Instantiations) 458327952Sdim Count += F->ExecutionCount; 459327952Sdim return Count; 460327952Sdim } 461327952Sdim 462327952Sdim /// Get the instantiations in this group. 463327952Sdim ArrayRef<const FunctionRecord *> getInstantiations() const { 464327952Sdim return Instantiations; 465327952Sdim } 466327952Sdim}; 467327952Sdim 468327952Sdim/// Coverage information to be processed or displayed. 469327952Sdim/// 470303231Sdim/// This represents the coverage of an entire file, expansion, or function. It 471303231Sdim/// provides a sequence of CoverageSegments to iterate through, as well as the 472303231Sdim/// list of expansions that can be further processed. 473303231Sdimclass CoverageData { 474321369Sdim friend class CoverageMapping; 475321369Sdim 476303231Sdim std::string Filename; 477303231Sdim std::vector<CoverageSegment> Segments; 478303231Sdim std::vector<ExpansionRecord> Expansions; 479303231Sdim 480303231Sdimpublic: 481321369Sdim CoverageData() = default; 482303231Sdim 483303231Sdim CoverageData(StringRef Filename) : Filename(Filename) {} 484303231Sdim 485327952Sdim /// Get the name of the file this data covers. 486303231Sdim StringRef getFilename() const { return Filename; } 487303231Sdim 488327952Sdim /// Get an iterator over the coverage segments for this object. The segments 489327952Sdim /// are guaranteed to be uniqued and sorted by location. 490314564Sdim std::vector<CoverageSegment>::const_iterator begin() const { 491314564Sdim return Segments.begin(); 492314564Sdim } 493321369Sdim 494314564Sdim std::vector<CoverageSegment>::const_iterator end() const { 495314564Sdim return Segments.end(); 496314564Sdim } 497321369Sdim 498314564Sdim bool empty() const { return Segments.empty(); } 499303231Sdim 500327952Sdim /// Expansions that can be further processed. 501314564Sdim ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } 502303231Sdim}; 503303231Sdim 504327952Sdim/// The mapping of profile information to coverage data. 505303231Sdim/// 506303231Sdim/// This is the main interface to get coverage information, using a profile to 507303231Sdim/// fill out execution counts. 508303231Sdimclass CoverageMapping { 509341825Sdim DenseMap<size_t, DenseSet<size_t>> RecordProvenance; 510303231Sdim std::vector<FunctionRecord> Functions; 511327952Sdim std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; 512303231Sdim 513321369Sdim CoverageMapping() = default; 514303231Sdim 515327952Sdim /// Add a function record corresponding to \p Record. 516314564Sdim Error loadFunctionRecord(const CoverageMappingRecord &Record, 517314564Sdim IndexedInstrProfReader &ProfileReader); 518314564Sdim 519303231Sdimpublic: 520321369Sdim CoverageMapping(const CoverageMapping &) = delete; 521321369Sdim CoverageMapping &operator=(const CoverageMapping &) = delete; 522321369Sdim 523327952Sdim /// Load the coverage mapping using the given readers. 524303231Sdim static Expected<std::unique_ptr<CoverageMapping>> 525314564Sdim load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 526314564Sdim IndexedInstrProfReader &ProfileReader); 527314564Sdim 528327952Sdim /// Load the coverage mapping from the given object files and profile. If 529327952Sdim /// \p Arches is non-empty, it must specify an architecture for each object. 530303231Sdim static Expected<std::unique_ptr<CoverageMapping>> 531314564Sdim load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 532327952Sdim ArrayRef<StringRef> Arches = None); 533303231Sdim 534327952Sdim /// The number of functions that couldn't have their profiles mapped. 535303231Sdim /// 536303231Sdim /// This is a count of functions whose profile is out of date or otherwise 537303231Sdim /// can't be associated with any coverage information. 538344779Sdim unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } 539303231Sdim 540327952Sdim /// A hash mismatch occurs when a profile record for a symbol does not have 541327952Sdim /// the same hash as a coverage mapping record for the same symbol. This 542327952Sdim /// returns a list of hash mismatches, where each mismatch is a pair of the 543327952Sdim /// symbol name and its coverage mapping hash. 544327952Sdim ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { 545327952Sdim return FuncHashMismatches; 546327952Sdim } 547327952Sdim 548327952Sdim /// Returns a lexicographically sorted, unique list of files that are 549314564Sdim /// covered. 550303231Sdim std::vector<StringRef> getUniqueSourceFiles() const; 551303231Sdim 552327952Sdim /// Get the coverage for a particular file. 553303231Sdim /// 554303231Sdim /// The given filename must be the name as recorded in the coverage 555303231Sdim /// information. That is, only names returned from getUniqueSourceFiles will 556303231Sdim /// yield a result. 557303231Sdim CoverageData getCoverageForFile(StringRef Filename) const; 558303231Sdim 559327952Sdim /// Get the coverage for a particular function. 560327952Sdim CoverageData getCoverageForFunction(const FunctionRecord &Function) const; 561327952Sdim 562327952Sdim /// Get the coverage for an expansion within a coverage set. 563327952Sdim CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; 564327952Sdim 565327952Sdim /// Gets all of the functions covered by this profile. 566303231Sdim iterator_range<FunctionRecordIterator> getCoveredFunctions() const { 567303231Sdim return make_range(FunctionRecordIterator(Functions), 568303231Sdim FunctionRecordIterator()); 569303231Sdim } 570303231Sdim 571327952Sdim /// Gets all of the functions in a particular file. 572303231Sdim iterator_range<FunctionRecordIterator> 573303231Sdim getCoveredFunctions(StringRef Filename) const { 574303231Sdim return make_range(FunctionRecordIterator(Functions, Filename), 575303231Sdim FunctionRecordIterator()); 576303231Sdim } 577303231Sdim 578327952Sdim /// Get the list of function instantiation groups in a particular file. 579303231Sdim /// 580327952Sdim /// Every instantiation group in a program is attributed to exactly one file: 581327952Sdim /// the file in which the definition for the common function begins. 582327952Sdim std::vector<InstantiationGroup> 583327952Sdim getInstantiationGroups(StringRef Filename) const; 584327952Sdim}; 585303231Sdim 586327952Sdim/// Coverage statistics for a single line. 587327952Sdimclass LineCoverageStats { 588327952Sdim uint64_t ExecutionCount; 589327952Sdim bool HasMultipleRegions; 590327952Sdim bool Mapped; 591327952Sdim unsigned Line; 592327952Sdim ArrayRef<const CoverageSegment *> LineSegments; 593327952Sdim const CoverageSegment *WrappedSegment; 594303231Sdim 595327952Sdim friend class LineCoverageIterator; 596327952Sdim LineCoverageStats() = default; 597327952Sdim 598327952Sdimpublic: 599327952Sdim LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, 600327952Sdim const CoverageSegment *WrappedSegment, unsigned Line); 601327952Sdim 602327952Sdim uint64_t getExecutionCount() const { return ExecutionCount; } 603327952Sdim 604327952Sdim bool hasMultipleRegions() const { return HasMultipleRegions; } 605327952Sdim 606327952Sdim bool isMapped() const { return Mapped; } 607327952Sdim 608327952Sdim unsigned getLine() const { return Line; } 609327952Sdim 610327952Sdim ArrayRef<const CoverageSegment *> getLineSegments() const { 611327952Sdim return LineSegments; 612327952Sdim } 613327952Sdim 614327952Sdim const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } 615303231Sdim}; 616303231Sdim 617327952Sdim/// An iterator over the \c LineCoverageStats objects for lines described by 618327952Sdim/// a \c CoverageData instance. 619327952Sdimclass LineCoverageIterator 620327952Sdim : public iterator_facade_base< 621327952Sdim LineCoverageIterator, std::forward_iterator_tag, LineCoverageStats> { 622327952Sdimpublic: 623327952Sdim LineCoverageIterator(const CoverageData &CD) 624327952Sdim : LineCoverageIterator(CD, CD.begin()->Line) {} 625327952Sdim 626327952Sdim LineCoverageIterator(const CoverageData &CD, unsigned Line) 627327952Sdim : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), 628327952Sdim Line(Line), Segments(), Stats() { 629327952Sdim this->operator++(); 630327952Sdim } 631327952Sdim 632327952Sdim bool operator==(const LineCoverageIterator &R) const { 633327952Sdim return &CD == &R.CD && Next == R.Next && Ended == R.Ended; 634327952Sdim } 635327952Sdim 636327952Sdim const LineCoverageStats &operator*() const { return Stats; } 637327952Sdim 638327952Sdim LineCoverageStats &operator*() { return Stats; } 639327952Sdim 640327952Sdim LineCoverageIterator &operator++(); 641327952Sdim 642327952Sdim LineCoverageIterator getEnd() const { 643327952Sdim auto EndIt = *this; 644327952Sdim EndIt.Next = CD.end(); 645327952Sdim EndIt.Ended = true; 646327952Sdim return EndIt; 647327952Sdim } 648327952Sdim 649327952Sdimprivate: 650327952Sdim const CoverageData &CD; 651327952Sdim const CoverageSegment *WrappedSegment; 652327952Sdim std::vector<CoverageSegment>::const_iterator Next; 653327952Sdim bool Ended; 654327952Sdim unsigned Line; 655327952Sdim SmallVector<const CoverageSegment *, 4> Segments; 656327952Sdim LineCoverageStats Stats; 657327952Sdim}; 658327952Sdim 659327952Sdim/// Get a \c LineCoverageIterator range for the lines described by \p CD. 660327952Sdimstatic inline iterator_range<LineCoverageIterator> 661327952SdimgetLineCoverageStats(const coverage::CoverageData &CD) { 662327952Sdim auto Begin = LineCoverageIterator(CD); 663327952Sdim auto End = Begin.getEnd(); 664327952Sdim return make_range(Begin, End); 665327952Sdim} 666327952Sdim 667303231Sdim// Profile coverage map has the following layout: 668303231Sdim// [CoverageMapFileHeader] 669303231Sdim// [ArrayStart] 670303231Sdim// [CovMapFunctionRecord] 671303231Sdim// [CovMapFunctionRecord] 672303231Sdim// ... 673303231Sdim// [ArrayEnd] 674303231Sdim// [Encoded Region Mapping Data] 675303231SdimLLVM_PACKED_START 676303231Sdimtemplate <class IntPtrT> struct CovMapFunctionRecordV1 { 677303231Sdim#define COVMAP_V1 678303231Sdim#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 679303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 680303231Sdim#undef COVMAP_V1 681303231Sdim 682303231Sdim // Return the structural hash associated with the function. 683303231Sdim template <support::endianness Endian> uint64_t getFuncHash() const { 684303231Sdim return support::endian::byte_swap<uint64_t, Endian>(FuncHash); 685303231Sdim } 686321369Sdim 687303231Sdim // Return the coverage map data size for the funciton. 688303231Sdim template <support::endianness Endian> uint32_t getDataSize() const { 689303231Sdim return support::endian::byte_swap<uint32_t, Endian>(DataSize); 690303231Sdim } 691321369Sdim 692303231Sdim // Return function lookup key. The value is consider opaque. 693303231Sdim template <support::endianness Endian> IntPtrT getFuncNameRef() const { 694303231Sdim return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); 695303231Sdim } 696321369Sdim 697303231Sdim // Return the PGO name of the function */ 698303231Sdim template <support::endianness Endian> 699303231Sdim Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 700303231Sdim IntPtrT NameRef = getFuncNameRef<Endian>(); 701303231Sdim uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); 702303231Sdim FuncName = ProfileNames.getFuncName(NameRef, NameS); 703303231Sdim if (NameS && FuncName.empty()) 704303231Sdim return make_error<CoverageMapError>(coveragemap_error::malformed); 705303231Sdim return Error::success(); 706303231Sdim } 707303231Sdim}; 708303231Sdim 709303231Sdimstruct CovMapFunctionRecord { 710303231Sdim#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 711303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 712303231Sdim 713303231Sdim // Return the structural hash associated with the function. 714303231Sdim template <support::endianness Endian> uint64_t getFuncHash() const { 715303231Sdim return support::endian::byte_swap<uint64_t, Endian>(FuncHash); 716303231Sdim } 717321369Sdim 718303231Sdim // Return the coverage map data size for the funciton. 719303231Sdim template <support::endianness Endian> uint32_t getDataSize() const { 720303231Sdim return support::endian::byte_swap<uint32_t, Endian>(DataSize); 721303231Sdim } 722321369Sdim 723303231Sdim // Return function lookup key. The value is consider opaque. 724303231Sdim template <support::endianness Endian> uint64_t getFuncNameRef() const { 725303231Sdim return support::endian::byte_swap<uint64_t, Endian>(NameRef); 726303231Sdim } 727321369Sdim 728303231Sdim // Return the PGO name of the function */ 729303231Sdim template <support::endianness Endian> 730303231Sdim Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 731303231Sdim uint64_t NameRef = getFuncNameRef<Endian>(); 732303231Sdim FuncName = ProfileNames.getFuncName(NameRef); 733303231Sdim return Error::success(); 734303231Sdim } 735303231Sdim}; 736303231Sdim 737303231Sdim// Per module coverage mapping data header, i.e. CoverageMapFileHeader 738303231Sdim// documented above. 739303231Sdimstruct CovMapHeader { 740303231Sdim#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; 741303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 742303231Sdim template <support::endianness Endian> uint32_t getNRecords() const { 743303231Sdim return support::endian::byte_swap<uint32_t, Endian>(NRecords); 744303231Sdim } 745321369Sdim 746303231Sdim template <support::endianness Endian> uint32_t getFilenamesSize() const { 747303231Sdim return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); 748303231Sdim } 749321369Sdim 750303231Sdim template <support::endianness Endian> uint32_t getCoverageSize() const { 751303231Sdim return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); 752303231Sdim } 753321369Sdim 754303231Sdim template <support::endianness Endian> uint32_t getVersion() const { 755303231Sdim return support::endian::byte_swap<uint32_t, Endian>(Version); 756303231Sdim } 757303231Sdim}; 758303231Sdim 759303231SdimLLVM_PACKED_END 760303231Sdim 761303231Sdimenum CovMapVersion { 762303231Sdim Version1 = 0, 763303231Sdim // Function's name reference from CovMapFuncRecord is changed from raw 764303231Sdim // name string pointer to MD5 to support name section compression. Name 765303231Sdim // section is also compressed. 766303231Sdim Version2 = 1, 767327952Sdim // A new interpretation of the columnEnd field is added in order to mark 768327952Sdim // regions as gap areas. 769327952Sdim Version3 = 2, 770327952Sdim // The current version is Version3 771303231Sdim CurrentVersion = INSTR_PROF_COVMAP_VERSION 772303231Sdim}; 773303231Sdim 774303231Sdimtemplate <int CovMapVersion, class IntPtrT> struct CovMapTraits { 775321369Sdim using CovMapFuncRecordType = CovMapFunctionRecord; 776321369Sdim using NameRefType = uint64_t; 777303231Sdim}; 778303231Sdim 779303231Sdimtemplate <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { 780321369Sdim using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; 781321369Sdim using NameRefType = IntPtrT; 782303231Sdim}; 783303231Sdim 784303231Sdim} // end namespace coverage 785303231Sdim 786327952Sdim/// Provide DenseMapInfo for CounterExpression 787303231Sdimtemplate<> struct DenseMapInfo<coverage::CounterExpression> { 788303231Sdim static inline coverage::CounterExpression getEmptyKey() { 789303231Sdim using namespace coverage; 790321369Sdim 791303231Sdim return CounterExpression(CounterExpression::ExprKind::Subtract, 792303231Sdim Counter::getCounter(~0U), 793303231Sdim Counter::getCounter(~0U)); 794303231Sdim } 795303231Sdim 796303231Sdim static inline coverage::CounterExpression getTombstoneKey() { 797303231Sdim using namespace coverage; 798321369Sdim 799303231Sdim return CounterExpression(CounterExpression::ExprKind::Add, 800303231Sdim Counter::getCounter(~0U), 801303231Sdim Counter::getCounter(~0U)); 802303231Sdim } 803303231Sdim 804303231Sdim static unsigned getHashValue(const coverage::CounterExpression &V) { 805303231Sdim return static_cast<unsigned>( 806303231Sdim hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), 807303231Sdim V.RHS.getKind(), V.RHS.getCounterID())); 808303231Sdim } 809303231Sdim 810303231Sdim static bool isEqual(const coverage::CounterExpression &LHS, 811303231Sdim const coverage::CounterExpression &RHS) { 812303231Sdim return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; 813303231Sdim } 814303231Sdim}; 815303231Sdim 816303231Sdim} // end namespace llvm 817303231Sdim 818321369Sdim#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 819