CoverageMapping.h revision 344779
1321369Sdim//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// 2303231Sdim// 3303231Sdim// The LLVM Compiler Infrastructure 4303231Sdim// 5303231Sdim// This file is distributed under the University of Illinois Open Source 6303231Sdim// License. See LICENSE.TXT for details. 7303231Sdim// 8303231Sdim//===----------------------------------------------------------------------===// 9303231Sdim// 10303231Sdim// Code coverage mapping data is generated by clang and read by 11303231Sdim// llvm-cov to show code coverage statistics for a file. 12303231Sdim// 13303231Sdim//===----------------------------------------------------------------------===// 14303231Sdim 15321369Sdim#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 16321369Sdim#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 17303231Sdim 18303231Sdim#include "llvm/ADT/ArrayRef.h" 19303231Sdim#include "llvm/ADT/DenseMap.h" 20341825Sdim#include "llvm/ADT/DenseSet.h" 21303231Sdim#include "llvm/ADT/Hashing.h" 22321369Sdim#include "llvm/ADT/None.h" 23321369Sdim#include "llvm/ADT/StringRef.h" 24314564Sdim#include "llvm/ADT/StringSet.h" 25303231Sdim#include "llvm/ADT/iterator.h" 26321369Sdim#include "llvm/ADT/iterator_range.h" 27303231Sdim#include "llvm/ProfileData/InstrProf.h" 28321369Sdim#include "llvm/Support/Compiler.h" 29303231Sdim#include "llvm/Support/Debug.h" 30303231Sdim#include "llvm/Support/Endian.h" 31321369Sdim#include "llvm/Support/Error.h" 32303231Sdim#include "llvm/Support/raw_ostream.h" 33321369Sdim#include <cassert> 34321369Sdim#include <cstdint> 35321369Sdim#include <iterator> 36321369Sdim#include <memory> 37321369Sdim#include <string> 38303231Sdim#include <system_error> 39303231Sdim#include <tuple> 40321369Sdim#include <utility> 41321369Sdim#include <vector> 42303231Sdim 43303231Sdimnamespace llvm { 44321369Sdim 45321369Sdimclass IndexedInstrProfReader; 46321369Sdim 47303231Sdimnamespace coverage { 48303231Sdim 49321369Sdimclass CoverageMappingReader; 50321369Sdimstruct CoverageMappingRecord; 51321369Sdim 52303231Sdimenum class coveragemap_error { 53303231Sdim success = 0, 54303231Sdim eof, 55303231Sdim no_data_found, 56303231Sdim unsupported_version, 57303231Sdim truncated, 58303231Sdim malformed 59303231Sdim}; 60303231Sdim 61303231Sdimconst std::error_category &coveragemap_category(); 62303231Sdim 63303231Sdiminline std::error_code make_error_code(coveragemap_error E) { 64303231Sdim return std::error_code(static_cast<int>(E), coveragemap_category()); 65303231Sdim} 66303231Sdim 67303231Sdimclass CoverageMapError : public ErrorInfo<CoverageMapError> { 68303231Sdimpublic: 69303231Sdim CoverageMapError(coveragemap_error Err) : Err(Err) { 70303231Sdim assert(Err != coveragemap_error::success && "Not an error"); 71303231Sdim } 72303231Sdim 73303231Sdim std::string message() const override; 74303231Sdim 75303231Sdim void log(raw_ostream &OS) const override { OS << message(); } 76303231Sdim 77303231Sdim std::error_code convertToErrorCode() const override { 78303231Sdim return make_error_code(Err); 79303231Sdim } 80303231Sdim 81303231Sdim coveragemap_error get() const { return Err; } 82303231Sdim 83303231Sdim static char ID; 84303231Sdim 85303231Sdimprivate: 86303231Sdim coveragemap_error Err; 87303231Sdim}; 88303231Sdim 89327952Sdim/// A Counter is an abstract value that describes how to compute the 90303231Sdim/// execution count for a region of code using the collected profile count data. 91303231Sdimstruct Counter { 92303231Sdim enum CounterKind { Zero, CounterValueReference, Expression }; 93303231Sdim static const unsigned EncodingTagBits = 2; 94303231Sdim static const unsigned EncodingTagMask = 0x3; 95303231Sdim static const unsigned EncodingCounterTagAndExpansionRegionTagBits = 96303231Sdim EncodingTagBits + 1; 97303231Sdim 98303231Sdimprivate: 99321369Sdim CounterKind Kind = Zero; 100321369Sdim unsigned ID = 0; 101303231Sdim 102303231Sdim Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} 103303231Sdim 104303231Sdimpublic: 105321369Sdim Counter() = default; 106303231Sdim 107303231Sdim CounterKind getKind() const { return Kind; } 108303231Sdim 109303231Sdim bool isZero() const { return Kind == Zero; } 110303231Sdim 111303231Sdim bool isExpression() const { return Kind == Expression; } 112303231Sdim 113303231Sdim unsigned getCounterID() const { return ID; } 114303231Sdim 115303231Sdim unsigned getExpressionID() const { return ID; } 116303231Sdim 117303231Sdim friend bool operator==(const Counter &LHS, const Counter &RHS) { 118303231Sdim return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; 119303231Sdim } 120303231Sdim 121303231Sdim friend bool operator!=(const Counter &LHS, const Counter &RHS) { 122303231Sdim return !(LHS == RHS); 123303231Sdim } 124303231Sdim 125303231Sdim friend bool operator<(const Counter &LHS, const Counter &RHS) { 126303231Sdim return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); 127303231Sdim } 128303231Sdim 129327952Sdim /// Return the counter that represents the number zero. 130303231Sdim static Counter getZero() { return Counter(); } 131303231Sdim 132327952Sdim /// Return the counter that corresponds to a specific profile counter. 133303231Sdim static Counter getCounter(unsigned CounterId) { 134303231Sdim return Counter(CounterValueReference, CounterId); 135303231Sdim } 136303231Sdim 137327952Sdim /// Return the counter that corresponds to a specific addition counter 138327952Sdim /// expression. 139303231Sdim static Counter getExpression(unsigned ExpressionId) { 140303231Sdim return Counter(Expression, ExpressionId); 141303231Sdim } 142303231Sdim}; 143303231Sdim 144327952Sdim/// A Counter expression is a value that represents an arithmetic operation 145327952Sdim/// with two counters. 146303231Sdimstruct CounterExpression { 147303231Sdim enum ExprKind { Subtract, Add }; 148303231Sdim ExprKind Kind; 149303231Sdim Counter LHS, RHS; 150303231Sdim 151303231Sdim CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) 152303231Sdim : Kind(Kind), LHS(LHS), RHS(RHS) {} 153303231Sdim}; 154303231Sdim 155327952Sdim/// A Counter expression builder is used to construct the counter expressions. 156327952Sdim/// It avoids unnecessary duplication and simplifies algebraic expressions. 157303231Sdimclass CounterExpressionBuilder { 158327952Sdim /// A list of all the counter expressions 159303231Sdim std::vector<CounterExpression> Expressions; 160321369Sdim 161327952Sdim /// A lookup table for the index of a given expression. 162321369Sdim DenseMap<CounterExpression, unsigned> ExpressionIndices; 163303231Sdim 164327952Sdim /// Return the counter which corresponds to the given expression. 165303231Sdim /// 166303231Sdim /// If the given expression is already stored in the builder, a counter 167303231Sdim /// that references that expression is returned. Otherwise, the given 168303231Sdim /// expression is added to the builder's collection of expressions. 169303231Sdim Counter get(const CounterExpression &E); 170303231Sdim 171321369Sdim /// Represents a term in a counter expression tree. 172321369Sdim struct Term { 173321369Sdim unsigned CounterID; 174321369Sdim int Factor; 175321369Sdim 176321369Sdim Term(unsigned CounterID, int Factor) 177321369Sdim : CounterID(CounterID), Factor(Factor) {} 178321369Sdim }; 179321369Sdim 180327952Sdim /// Gather the terms of the expression tree for processing. 181303231Sdim /// 182303231Sdim /// This collects each addition and subtraction referenced by the counter into 183303231Sdim /// a sequence that can be sorted and combined to build a simplified counter 184303231Sdim /// expression. 185321369Sdim void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms); 186303231Sdim 187327952Sdim /// Simplifies the given expression tree 188303231Sdim /// by getting rid of algebraically redundant operations. 189303231Sdim Counter simplify(Counter ExpressionTree); 190303231Sdim 191303231Sdimpublic: 192303231Sdim ArrayRef<CounterExpression> getExpressions() const { return Expressions; } 193303231Sdim 194327952Sdim /// Return a counter that represents the expression that adds LHS and RHS. 195303231Sdim Counter add(Counter LHS, Counter RHS); 196303231Sdim 197327952Sdim /// Return a counter that represents the expression that subtracts RHS from 198327952Sdim /// LHS. 199303231Sdim Counter subtract(Counter LHS, Counter RHS); 200303231Sdim}; 201303231Sdim 202327952Sdimusing LineColPair = std::pair<unsigned, unsigned>; 203327952Sdim 204327952Sdim/// A Counter mapping region associates a source range with a specific counter. 205303231Sdimstruct CounterMappingRegion { 206303231Sdim enum RegionKind { 207327952Sdim /// A CodeRegion associates some code with a counter 208303231Sdim CodeRegion, 209303231Sdim 210341825Sdim /// An ExpansionRegion represents a file expansion region that associates 211327952Sdim /// a source range with the expansion of a virtual source file, such as 212327952Sdim /// for a macro instantiation or #include file. 213303231Sdim ExpansionRegion, 214303231Sdim 215327952Sdim /// A SkippedRegion represents a source range with code that was skipped 216327952Sdim /// by a preprocessor or similar means. 217327952Sdim SkippedRegion, 218327952Sdim 219327952Sdim /// A GapRegion is like a CodeRegion, but its count is only set as the 220327952Sdim /// line execution count when its the only region in the line. 221327952Sdim GapRegion 222303231Sdim }; 223303231Sdim 224303231Sdim Counter Count; 225303231Sdim unsigned FileID, ExpandedFileID; 226303231Sdim unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; 227303231Sdim RegionKind Kind; 228303231Sdim 229303231Sdim CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, 230303231Sdim unsigned LineStart, unsigned ColumnStart, 231303231Sdim unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) 232303231Sdim : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), 233303231Sdim LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), 234303231Sdim ColumnEnd(ColumnEnd), Kind(Kind) {} 235303231Sdim 236303231Sdim static CounterMappingRegion 237303231Sdim makeRegion(Counter Count, unsigned FileID, unsigned LineStart, 238303231Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 239303231Sdim return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 240303231Sdim LineEnd, ColumnEnd, CodeRegion); 241303231Sdim } 242303231Sdim 243303231Sdim static CounterMappingRegion 244303231Sdim makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, 245303231Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 246303231Sdim return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, 247303231Sdim ColumnStart, LineEnd, ColumnEnd, 248303231Sdim ExpansionRegion); 249303231Sdim } 250303231Sdim 251303231Sdim static CounterMappingRegion 252303231Sdim makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, 253303231Sdim unsigned LineEnd, unsigned ColumnEnd) { 254303231Sdim return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, 255303231Sdim LineEnd, ColumnEnd, SkippedRegion); 256303231Sdim } 257303231Sdim 258327952Sdim static CounterMappingRegion 259327952Sdim makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, 260327952Sdim unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 261327952Sdim return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 262327952Sdim LineEnd, (1U << 31) | ColumnEnd, GapRegion); 263303231Sdim } 264303231Sdim 265327952Sdim inline LineColPair startLoc() const { 266327952Sdim return LineColPair(LineStart, ColumnStart); 267303231Sdim } 268327952Sdim 269327952Sdim inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } 270303231Sdim}; 271303231Sdim 272327952Sdim/// Associates a source range with an execution count. 273303231Sdimstruct CountedRegion : public CounterMappingRegion { 274303231Sdim uint64_t ExecutionCount; 275303231Sdim 276303231Sdim CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) 277303231Sdim : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {} 278303231Sdim}; 279303231Sdim 280327952Sdim/// A Counter mapping context is used to connect the counters, expressions 281327952Sdim/// and the obtained counter values. 282303231Sdimclass CounterMappingContext { 283303231Sdim ArrayRef<CounterExpression> Expressions; 284303231Sdim ArrayRef<uint64_t> CounterValues; 285303231Sdim 286303231Sdimpublic: 287303231Sdim CounterMappingContext(ArrayRef<CounterExpression> Expressions, 288303231Sdim ArrayRef<uint64_t> CounterValues = None) 289303231Sdim : Expressions(Expressions), CounterValues(CounterValues) {} 290303231Sdim 291303231Sdim void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } 292303231Sdim 293321369Sdim void dump(const Counter &C, raw_ostream &OS) const; 294303231Sdim void dump(const Counter &C) const { dump(C, dbgs()); } 295303231Sdim 296327952Sdim /// Return the number of times that a region of code associated with this 297327952Sdim /// counter was executed. 298303231Sdim Expected<int64_t> evaluate(const Counter &C) const; 299303231Sdim}; 300303231Sdim 301327952Sdim/// Code coverage information for a single function. 302303231Sdimstruct FunctionRecord { 303327952Sdim /// Raw function name. 304303231Sdim std::string Name; 305327952Sdim /// Associated files. 306303231Sdim std::vector<std::string> Filenames; 307327952Sdim /// Regions in the function along with their counts. 308303231Sdim std::vector<CountedRegion> CountedRegions; 309327952Sdim /// The number of times this function was executed. 310303231Sdim uint64_t ExecutionCount; 311303231Sdim 312303231Sdim FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 313303231Sdim : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 314303231Sdim 315314564Sdim FunctionRecord(FunctionRecord &&FR) = default; 316314564Sdim FunctionRecord &operator=(FunctionRecord &&) = default; 317314564Sdim 318303231Sdim void pushRegion(CounterMappingRegion Region, uint64_t Count) { 319303231Sdim if (CountedRegions.empty()) 320303231Sdim ExecutionCount = Count; 321303231Sdim CountedRegions.emplace_back(Region, Count); 322303231Sdim } 323303231Sdim}; 324303231Sdim 325327952Sdim/// Iterator over Functions, optionally filtered to a single file. 326303231Sdimclass FunctionRecordIterator 327303231Sdim : public iterator_facade_base<FunctionRecordIterator, 328303231Sdim std::forward_iterator_tag, FunctionRecord> { 329303231Sdim ArrayRef<FunctionRecord> Records; 330303231Sdim ArrayRef<FunctionRecord>::iterator Current; 331303231Sdim StringRef Filename; 332303231Sdim 333327952Sdim /// Skip records whose primary file is not \c Filename. 334303231Sdim void skipOtherFiles(); 335303231Sdim 336303231Sdimpublic: 337303231Sdim FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 338303231Sdim StringRef Filename = "") 339303231Sdim : Records(Records_), Current(Records.begin()), Filename(Filename) { 340303231Sdim skipOtherFiles(); 341303231Sdim } 342303231Sdim 343303231Sdim FunctionRecordIterator() : Current(Records.begin()) {} 344303231Sdim 345303231Sdim bool operator==(const FunctionRecordIterator &RHS) const { 346303231Sdim return Current == RHS.Current && Filename == RHS.Filename; 347303231Sdim } 348303231Sdim 349303231Sdim const FunctionRecord &operator*() const { return *Current; } 350303231Sdim 351303231Sdim FunctionRecordIterator &operator++() { 352303231Sdim assert(Current != Records.end() && "incremented past end"); 353303231Sdim ++Current; 354303231Sdim skipOtherFiles(); 355303231Sdim return *this; 356303231Sdim } 357303231Sdim}; 358303231Sdim 359327952Sdim/// Coverage information for a macro expansion or #included file. 360303231Sdim/// 361303231Sdim/// When covered code has pieces that can be expanded for more detail, such as a 362303231Sdim/// preprocessor macro use and its definition, these are represented as 363303231Sdim/// expansions whose coverage can be looked up independently. 364303231Sdimstruct ExpansionRecord { 365327952Sdim /// The abstract file this expansion covers. 366303231Sdim unsigned FileID; 367327952Sdim /// The region that expands to this record. 368303231Sdim const CountedRegion &Region; 369327952Sdim /// Coverage for the expansion. 370303231Sdim const FunctionRecord &Function; 371303231Sdim 372303231Sdim ExpansionRecord(const CountedRegion &Region, 373303231Sdim const FunctionRecord &Function) 374303231Sdim : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} 375303231Sdim}; 376303231Sdim 377327952Sdim/// The execution count information starting at a point in a file. 378303231Sdim/// 379303231Sdim/// A sequence of CoverageSegments gives execution counts for a file in format 380303231Sdim/// that's simple to iterate through for processing. 381303231Sdimstruct CoverageSegment { 382327952Sdim /// The line where this segment begins. 383303231Sdim unsigned Line; 384327952Sdim /// The column where this segment begins. 385303231Sdim unsigned Col; 386327952Sdim /// The execution count, or zero if no count was recorded. 387303231Sdim uint64_t Count; 388327952Sdim /// When false, the segment was uninstrumented or skipped. 389303231Sdim bool HasCount; 390327952Sdim /// Whether this enters a new region or returns to a previous count. 391303231Sdim bool IsRegionEntry; 392327952Sdim /// Whether this enters a gap region. 393327952Sdim bool IsGapRegion; 394303231Sdim 395303231Sdim CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 396303231Sdim : Line(Line), Col(Col), Count(0), HasCount(false), 397327952Sdim IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 398303231Sdim 399303231Sdim CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 400327952Sdim bool IsRegionEntry, bool IsGapRegion = false) 401303231Sdim : Line(Line), Col(Col), Count(Count), HasCount(true), 402327952Sdim IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 403303231Sdim 404303231Sdim friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { 405327952Sdim return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, 406327952Sdim L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, 407327952Sdim R.HasCount, R.IsRegionEntry, 408327952Sdim R.IsGapRegion); 409303231Sdim } 410303231Sdim}; 411303231Sdim 412327952Sdim/// An instantiation group contains a \c FunctionRecord list, such that each 413327952Sdim/// record corresponds to a distinct instantiation of the same function. 414303231Sdim/// 415327952Sdim/// Note that it's possible for a function to have more than one instantiation 416327952Sdim/// (consider C++ template specializations or static inline functions). 417327952Sdimclass InstantiationGroup { 418327952Sdim friend class CoverageMapping; 419327952Sdim 420327952Sdim unsigned Line; 421327952Sdim unsigned Col; 422327952Sdim std::vector<const FunctionRecord *> Instantiations; 423327952Sdim 424327952Sdim InstantiationGroup(unsigned Line, unsigned Col, 425327952Sdim std::vector<const FunctionRecord *> Instantiations) 426327952Sdim : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} 427327952Sdim 428327952Sdimpublic: 429327952Sdim InstantiationGroup(const InstantiationGroup &) = delete; 430327952Sdim InstantiationGroup(InstantiationGroup &&) = default; 431327952Sdim 432327952Sdim /// Get the number of instantiations in this group. 433327952Sdim size_t size() const { return Instantiations.size(); } 434327952Sdim 435327952Sdim /// Get the line where the common function was defined. 436327952Sdim unsigned getLine() const { return Line; } 437327952Sdim 438327952Sdim /// Get the column where the common function was defined. 439327952Sdim unsigned getColumn() const { return Col; } 440327952Sdim 441327952Sdim /// Check if the instantiations in this group have a common mangled name. 442327952Sdim bool hasName() const { 443327952Sdim for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) 444327952Sdim if (Instantiations[I]->Name != Instantiations[0]->Name) 445327952Sdim return false; 446327952Sdim return true; 447327952Sdim } 448327952Sdim 449327952Sdim /// Get the common mangled name for instantiations in this group. 450327952Sdim StringRef getName() const { 451327952Sdim assert(hasName() && "Instantiations don't have a shared name"); 452327952Sdim return Instantiations[0]->Name; 453327952Sdim } 454327952Sdim 455327952Sdim /// Get the total execution count of all instantiations in this group. 456327952Sdim uint64_t getTotalExecutionCount() const { 457327952Sdim uint64_t Count = 0; 458327952Sdim for (const FunctionRecord *F : Instantiations) 459327952Sdim Count += F->ExecutionCount; 460327952Sdim return Count; 461327952Sdim } 462327952Sdim 463327952Sdim /// Get the instantiations in this group. 464327952Sdim ArrayRef<const FunctionRecord *> getInstantiations() const { 465327952Sdim return Instantiations; 466327952Sdim } 467327952Sdim}; 468327952Sdim 469327952Sdim/// Coverage information to be processed or displayed. 470327952Sdim/// 471303231Sdim/// This represents the coverage of an entire file, expansion, or function. It 472303231Sdim/// provides a sequence of CoverageSegments to iterate through, as well as the 473303231Sdim/// list of expansions that can be further processed. 474303231Sdimclass CoverageData { 475321369Sdim friend class CoverageMapping; 476321369Sdim 477303231Sdim std::string Filename; 478303231Sdim std::vector<CoverageSegment> Segments; 479303231Sdim std::vector<ExpansionRecord> Expansions; 480303231Sdim 481303231Sdimpublic: 482321369Sdim CoverageData() = default; 483303231Sdim 484303231Sdim CoverageData(StringRef Filename) : Filename(Filename) {} 485303231Sdim 486327952Sdim /// Get the name of the file this data covers. 487303231Sdim StringRef getFilename() const { return Filename; } 488303231Sdim 489327952Sdim /// Get an iterator over the coverage segments for this object. The segments 490327952Sdim /// are guaranteed to be uniqued and sorted by location. 491314564Sdim std::vector<CoverageSegment>::const_iterator begin() const { 492314564Sdim return Segments.begin(); 493314564Sdim } 494321369Sdim 495314564Sdim std::vector<CoverageSegment>::const_iterator end() const { 496314564Sdim return Segments.end(); 497314564Sdim } 498321369Sdim 499314564Sdim bool empty() const { return Segments.empty(); } 500303231Sdim 501327952Sdim /// Expansions that can be further processed. 502314564Sdim ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } 503303231Sdim}; 504303231Sdim 505327952Sdim/// The mapping of profile information to coverage data. 506303231Sdim/// 507303231Sdim/// This is the main interface to get coverage information, using a profile to 508303231Sdim/// fill out execution counts. 509303231Sdimclass CoverageMapping { 510341825Sdim DenseMap<size_t, DenseSet<size_t>> RecordProvenance; 511303231Sdim std::vector<FunctionRecord> Functions; 512327952Sdim std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; 513303231Sdim 514321369Sdim CoverageMapping() = default; 515303231Sdim 516327952Sdim /// Add a function record corresponding to \p Record. 517314564Sdim Error loadFunctionRecord(const CoverageMappingRecord &Record, 518314564Sdim IndexedInstrProfReader &ProfileReader); 519314564Sdim 520303231Sdimpublic: 521321369Sdim CoverageMapping(const CoverageMapping &) = delete; 522321369Sdim CoverageMapping &operator=(const CoverageMapping &) = delete; 523321369Sdim 524327952Sdim /// Load the coverage mapping using the given readers. 525303231Sdim static Expected<std::unique_ptr<CoverageMapping>> 526314564Sdim load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 527314564Sdim IndexedInstrProfReader &ProfileReader); 528314564Sdim 529327952Sdim /// Load the coverage mapping from the given object files and profile. If 530327952Sdim /// \p Arches is non-empty, it must specify an architecture for each object. 531303231Sdim static Expected<std::unique_ptr<CoverageMapping>> 532314564Sdim load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 533327952Sdim ArrayRef<StringRef> Arches = None); 534303231Sdim 535327952Sdim /// The number of functions that couldn't have their profiles mapped. 536303231Sdim /// 537303231Sdim /// This is a count of functions whose profile is out of date or otherwise 538303231Sdim /// can't be associated with any coverage information. 539344779Sdim unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } 540303231Sdim 541327952Sdim /// A hash mismatch occurs when a profile record for a symbol does not have 542327952Sdim /// the same hash as a coverage mapping record for the same symbol. This 543327952Sdim /// returns a list of hash mismatches, where each mismatch is a pair of the 544327952Sdim /// symbol name and its coverage mapping hash. 545327952Sdim ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { 546327952Sdim return FuncHashMismatches; 547327952Sdim } 548327952Sdim 549327952Sdim /// Returns a lexicographically sorted, unique list of files that are 550314564Sdim /// covered. 551303231Sdim std::vector<StringRef> getUniqueSourceFiles() const; 552303231Sdim 553327952Sdim /// Get the coverage for a particular file. 554303231Sdim /// 555303231Sdim /// The given filename must be the name as recorded in the coverage 556303231Sdim /// information. That is, only names returned from getUniqueSourceFiles will 557303231Sdim /// yield a result. 558303231Sdim CoverageData getCoverageForFile(StringRef Filename) const; 559303231Sdim 560327952Sdim /// Get the coverage for a particular function. 561327952Sdim CoverageData getCoverageForFunction(const FunctionRecord &Function) const; 562327952Sdim 563327952Sdim /// Get the coverage for an expansion within a coverage set. 564327952Sdim CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; 565327952Sdim 566327952Sdim /// Gets all of the functions covered by this profile. 567303231Sdim iterator_range<FunctionRecordIterator> getCoveredFunctions() const { 568303231Sdim return make_range(FunctionRecordIterator(Functions), 569303231Sdim FunctionRecordIterator()); 570303231Sdim } 571303231Sdim 572327952Sdim /// Gets all of the functions in a particular file. 573303231Sdim iterator_range<FunctionRecordIterator> 574303231Sdim getCoveredFunctions(StringRef Filename) const { 575303231Sdim return make_range(FunctionRecordIterator(Functions, Filename), 576303231Sdim FunctionRecordIterator()); 577303231Sdim } 578303231Sdim 579327952Sdim /// Get the list of function instantiation groups in a particular file. 580303231Sdim /// 581327952Sdim /// Every instantiation group in a program is attributed to exactly one file: 582327952Sdim /// the file in which the definition for the common function begins. 583327952Sdim std::vector<InstantiationGroup> 584327952Sdim getInstantiationGroups(StringRef Filename) const; 585327952Sdim}; 586303231Sdim 587327952Sdim/// Coverage statistics for a single line. 588327952Sdimclass LineCoverageStats { 589327952Sdim uint64_t ExecutionCount; 590327952Sdim bool HasMultipleRegions; 591327952Sdim bool Mapped; 592327952Sdim unsigned Line; 593327952Sdim ArrayRef<const CoverageSegment *> LineSegments; 594327952Sdim const CoverageSegment *WrappedSegment; 595303231Sdim 596327952Sdim friend class LineCoverageIterator; 597327952Sdim LineCoverageStats() = default; 598327952Sdim 599327952Sdimpublic: 600327952Sdim LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, 601327952Sdim const CoverageSegment *WrappedSegment, unsigned Line); 602327952Sdim 603327952Sdim uint64_t getExecutionCount() const { return ExecutionCount; } 604327952Sdim 605327952Sdim bool hasMultipleRegions() const { return HasMultipleRegions; } 606327952Sdim 607327952Sdim bool isMapped() const { return Mapped; } 608327952Sdim 609327952Sdim unsigned getLine() const { return Line; } 610327952Sdim 611327952Sdim ArrayRef<const CoverageSegment *> getLineSegments() const { 612327952Sdim return LineSegments; 613327952Sdim } 614327952Sdim 615327952Sdim const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } 616303231Sdim}; 617303231Sdim 618327952Sdim/// An iterator over the \c LineCoverageStats objects for lines described by 619327952Sdim/// a \c CoverageData instance. 620327952Sdimclass LineCoverageIterator 621327952Sdim : public iterator_facade_base< 622327952Sdim LineCoverageIterator, std::forward_iterator_tag, LineCoverageStats> { 623327952Sdimpublic: 624327952Sdim LineCoverageIterator(const CoverageData &CD) 625327952Sdim : LineCoverageIterator(CD, CD.begin()->Line) {} 626327952Sdim 627327952Sdim LineCoverageIterator(const CoverageData &CD, unsigned Line) 628327952Sdim : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), 629327952Sdim Line(Line), Segments(), Stats() { 630327952Sdim this->operator++(); 631327952Sdim } 632327952Sdim 633327952Sdim bool operator==(const LineCoverageIterator &R) const { 634327952Sdim return &CD == &R.CD && Next == R.Next && Ended == R.Ended; 635327952Sdim } 636327952Sdim 637327952Sdim const LineCoverageStats &operator*() const { return Stats; } 638327952Sdim 639327952Sdim LineCoverageStats &operator*() { return Stats; } 640327952Sdim 641327952Sdim LineCoverageIterator &operator++(); 642327952Sdim 643327952Sdim LineCoverageIterator getEnd() const { 644327952Sdim auto EndIt = *this; 645327952Sdim EndIt.Next = CD.end(); 646327952Sdim EndIt.Ended = true; 647327952Sdim return EndIt; 648327952Sdim } 649327952Sdim 650327952Sdimprivate: 651327952Sdim const CoverageData &CD; 652327952Sdim const CoverageSegment *WrappedSegment; 653327952Sdim std::vector<CoverageSegment>::const_iterator Next; 654327952Sdim bool Ended; 655327952Sdim unsigned Line; 656327952Sdim SmallVector<const CoverageSegment *, 4> Segments; 657327952Sdim LineCoverageStats Stats; 658327952Sdim}; 659327952Sdim 660327952Sdim/// Get a \c LineCoverageIterator range for the lines described by \p CD. 661327952Sdimstatic inline iterator_range<LineCoverageIterator> 662327952SdimgetLineCoverageStats(const coverage::CoverageData &CD) { 663327952Sdim auto Begin = LineCoverageIterator(CD); 664327952Sdim auto End = Begin.getEnd(); 665327952Sdim return make_range(Begin, End); 666327952Sdim} 667327952Sdim 668303231Sdim// Profile coverage map has the following layout: 669303231Sdim// [CoverageMapFileHeader] 670303231Sdim// [ArrayStart] 671303231Sdim// [CovMapFunctionRecord] 672303231Sdim// [CovMapFunctionRecord] 673303231Sdim// ... 674303231Sdim// [ArrayEnd] 675303231Sdim// [Encoded Region Mapping Data] 676303231SdimLLVM_PACKED_START 677303231Sdimtemplate <class IntPtrT> struct CovMapFunctionRecordV1 { 678303231Sdim#define COVMAP_V1 679303231Sdim#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 680303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 681303231Sdim#undef COVMAP_V1 682303231Sdim 683303231Sdim // Return the structural hash associated with the function. 684303231Sdim template <support::endianness Endian> uint64_t getFuncHash() const { 685303231Sdim return support::endian::byte_swap<uint64_t, Endian>(FuncHash); 686303231Sdim } 687321369Sdim 688303231Sdim // Return the coverage map data size for the funciton. 689303231Sdim template <support::endianness Endian> uint32_t getDataSize() const { 690303231Sdim return support::endian::byte_swap<uint32_t, Endian>(DataSize); 691303231Sdim } 692321369Sdim 693303231Sdim // Return function lookup key. The value is consider opaque. 694303231Sdim template <support::endianness Endian> IntPtrT getFuncNameRef() const { 695303231Sdim return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); 696303231Sdim } 697321369Sdim 698303231Sdim // Return the PGO name of the function */ 699303231Sdim template <support::endianness Endian> 700303231Sdim Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 701303231Sdim IntPtrT NameRef = getFuncNameRef<Endian>(); 702303231Sdim uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); 703303231Sdim FuncName = ProfileNames.getFuncName(NameRef, NameS); 704303231Sdim if (NameS && FuncName.empty()) 705303231Sdim return make_error<CoverageMapError>(coveragemap_error::malformed); 706303231Sdim return Error::success(); 707303231Sdim } 708303231Sdim}; 709303231Sdim 710303231Sdimstruct CovMapFunctionRecord { 711303231Sdim#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 712303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 713303231Sdim 714303231Sdim // Return the structural hash associated with the function. 715303231Sdim template <support::endianness Endian> uint64_t getFuncHash() const { 716303231Sdim return support::endian::byte_swap<uint64_t, Endian>(FuncHash); 717303231Sdim } 718321369Sdim 719303231Sdim // Return the coverage map data size for the funciton. 720303231Sdim template <support::endianness Endian> uint32_t getDataSize() const { 721303231Sdim return support::endian::byte_swap<uint32_t, Endian>(DataSize); 722303231Sdim } 723321369Sdim 724303231Sdim // Return function lookup key. The value is consider opaque. 725303231Sdim template <support::endianness Endian> uint64_t getFuncNameRef() const { 726303231Sdim return support::endian::byte_swap<uint64_t, Endian>(NameRef); 727303231Sdim } 728321369Sdim 729303231Sdim // Return the PGO name of the function */ 730303231Sdim template <support::endianness Endian> 731303231Sdim Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 732303231Sdim uint64_t NameRef = getFuncNameRef<Endian>(); 733303231Sdim FuncName = ProfileNames.getFuncName(NameRef); 734303231Sdim return Error::success(); 735303231Sdim } 736303231Sdim}; 737303231Sdim 738303231Sdim// Per module coverage mapping data header, i.e. CoverageMapFileHeader 739303231Sdim// documented above. 740303231Sdimstruct CovMapHeader { 741303231Sdim#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; 742303231Sdim#include "llvm/ProfileData/InstrProfData.inc" 743303231Sdim template <support::endianness Endian> uint32_t getNRecords() const { 744303231Sdim return support::endian::byte_swap<uint32_t, Endian>(NRecords); 745303231Sdim } 746321369Sdim 747303231Sdim template <support::endianness Endian> uint32_t getFilenamesSize() const { 748303231Sdim return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); 749303231Sdim } 750321369Sdim 751303231Sdim template <support::endianness Endian> uint32_t getCoverageSize() const { 752303231Sdim return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); 753303231Sdim } 754321369Sdim 755303231Sdim template <support::endianness Endian> uint32_t getVersion() const { 756303231Sdim return support::endian::byte_swap<uint32_t, Endian>(Version); 757303231Sdim } 758303231Sdim}; 759303231Sdim 760303231SdimLLVM_PACKED_END 761303231Sdim 762303231Sdimenum CovMapVersion { 763303231Sdim Version1 = 0, 764303231Sdim // Function's name reference from CovMapFuncRecord is changed from raw 765303231Sdim // name string pointer to MD5 to support name section compression. Name 766303231Sdim // section is also compressed. 767303231Sdim Version2 = 1, 768327952Sdim // A new interpretation of the columnEnd field is added in order to mark 769327952Sdim // regions as gap areas. 770327952Sdim Version3 = 2, 771327952Sdim // The current version is Version3 772303231Sdim CurrentVersion = INSTR_PROF_COVMAP_VERSION 773303231Sdim}; 774303231Sdim 775303231Sdimtemplate <int CovMapVersion, class IntPtrT> struct CovMapTraits { 776321369Sdim using CovMapFuncRecordType = CovMapFunctionRecord; 777321369Sdim using NameRefType = uint64_t; 778303231Sdim}; 779303231Sdim 780303231Sdimtemplate <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { 781321369Sdim using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; 782321369Sdim using NameRefType = IntPtrT; 783303231Sdim}; 784303231Sdim 785303231Sdim} // end namespace coverage 786303231Sdim 787327952Sdim/// Provide DenseMapInfo for CounterExpression 788303231Sdimtemplate<> struct DenseMapInfo<coverage::CounterExpression> { 789303231Sdim static inline coverage::CounterExpression getEmptyKey() { 790303231Sdim using namespace coverage; 791321369Sdim 792303231Sdim return CounterExpression(CounterExpression::ExprKind::Subtract, 793303231Sdim Counter::getCounter(~0U), 794303231Sdim Counter::getCounter(~0U)); 795303231Sdim } 796303231Sdim 797303231Sdim static inline coverage::CounterExpression getTombstoneKey() { 798303231Sdim using namespace coverage; 799321369Sdim 800303231Sdim return CounterExpression(CounterExpression::ExprKind::Add, 801303231Sdim Counter::getCounter(~0U), 802303231Sdim Counter::getCounter(~0U)); 803303231Sdim } 804303231Sdim 805303231Sdim static unsigned getHashValue(const coverage::CounterExpression &V) { 806303231Sdim return static_cast<unsigned>( 807303231Sdim hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), 808303231Sdim V.RHS.getKind(), V.RHS.getCounterID())); 809303231Sdim } 810303231Sdim 811303231Sdim static bool isEqual(const coverage::CounterExpression &LHS, 812303231Sdim const coverage::CounterExpression &RHS) { 813303231Sdim return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; 814303231Sdim } 815303231Sdim}; 816303231Sdim 817303231Sdim} // end namespace llvm 818303231Sdim 819321369Sdim#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 820