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" 23 #include "llvm/ADT/iterator_range.h" 24 #include "llvm/Object/BuildID.h" 25 #include "llvm/ProfileData/InstrProf.h" 26 #include "llvm/Support/Alignment.h" 27 #include "llvm/Support/Compiler.h" 28 #include "llvm/Support/Debug.h" 29 #include "llvm/Support/Endian.h" 30 #include "llvm/Support/Error.h" 31 #include "llvm/Support/raw_ostream.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 42 namespace llvm { 43 44 class IndexedInstrProfReader; 45 46 namespace object { 47 class BuildIDFetcher; 48 } // namespace object 49 50 namespace vfs { 51 class FileSystem; 52 } // namespace vfs 53 54 namespace coverage { 55 56 class CoverageMappingReader; 57 struct CoverageMappingRecord; 58 59 enum class coveragemap_error { 60 success = 0, 61 eof, 62 no_data_found, 63 unsupported_version, 64 truncated, 65 malformed, 66 decompression_failed, 67 invalid_or_missing_arch_specifier 68 }; 69 70 const std::error_category &coveragemap_category(); 71 72 inline std::error_code make_error_code(coveragemap_error E) { 73 return std::error_code(static_cast<int>(E), coveragemap_category()); 74 } 75 76 class CoverageMapError : public ErrorInfo<CoverageMapError> { 77 public: 78 CoverageMapError(coveragemap_error Err) : Err(Err) { 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 94 private: 95 coveragemap_error Err; 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. 100 struct 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. 103 enum CounterKind { Zero, CounterValueReference, Expression }; 104 static const unsigned EncodingTagBits = 2; 105 static const unsigned EncodingTagMask = 0x3; 106 static const unsigned EncodingCounterTagAndExpansionRegionTagBits = 107 EncodingTagBits + 1; 108 109 private: 110 CounterKind Kind = Zero; 111 unsigned ID = 0; 112 113 Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} 114 115 public: 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. 157 struct CounterExpression { 158 enum ExprKind { Subtract, Add }; 159 ExprKind Kind; 160 Counter LHS, RHS; 161 162 CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) 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. 168 class CounterExpressionBuilder { 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. 173 DenseMap<CounterExpression, unsigned> ExpressionIndices; 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 202 public: 203 ArrayRef<CounterExpression> getExpressions() const { return Expressions; } 204 205 /// Return a counter that represents the expression that adds LHS and RHS. 206 Counter add(Counter LHS, Counter RHS, bool Simplify = true); 207 208 /// Return a counter that represents the expression that subtracts RHS from 209 /// LHS. 210 Counter subtract(Counter LHS, Counter RHS, bool Simplify = true); 211 }; 212 213 using LineColPair = std::pair<unsigned, unsigned>; 214 215 /// A Counter mapping region associates a source range with a specific counter. 216 struct CounterMappingRegion { 217 enum RegionKind { 218 /// A CodeRegion associates some code with a counter 219 CodeRegion, 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. 224 ExpansionRegion, 225 226 /// A SkippedRegion represents a source range with code that was skipped 227 /// by a preprocessor or similar means. 228 SkippedRegion, 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. 232 GapRegion, 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. 237 BranchRegion 238 }; 239 240 /// Primary Counter that is also used for Branch Regions (TrueCount). 241 Counter Count; 242 243 /// Secondary Counter used for Branch Regions (FalseCount). 244 Counter FalseCount; 245 246 unsigned FileID, ExpandedFileID; 247 unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; 248 RegionKind Kind; 249 250 CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, 251 unsigned LineStart, unsigned ColumnStart, 252 unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) 253 : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), 254 LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), 255 ColumnEnd(ColumnEnd), Kind(Kind) {} 256 257 CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, 258 unsigned ExpandedFileID, unsigned LineStart, 259 unsigned ColumnStart, unsigned LineEnd, 260 unsigned ColumnEnd, RegionKind Kind) 261 : Count(Count), FalseCount(FalseCount), FileID(FileID), 262 ExpandedFileID(ExpandedFileID), LineStart(LineStart), 263 ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), 264 Kind(Kind) {} 265 266 static CounterMappingRegion 267 makeRegion(Counter Count, unsigned FileID, unsigned LineStart, 268 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 269 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 270 LineEnd, ColumnEnd, CodeRegion); 271 } 272 273 static CounterMappingRegion 274 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, 275 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 276 return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, 277 ColumnStart, LineEnd, ColumnEnd, 278 ExpansionRegion); 279 } 280 281 static CounterMappingRegion 282 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, 283 unsigned LineEnd, unsigned ColumnEnd) { 284 return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, 285 LineEnd, ColumnEnd, SkippedRegion); 286 } 287 288 static CounterMappingRegion 289 makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, 290 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 291 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 292 LineEnd, (1U << 31) | ColumnEnd, GapRegion); 293 } 294 295 static CounterMappingRegion 296 makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, 297 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, 298 unsigned ColumnEnd) { 299 return CounterMappingRegion(Count, FalseCount, FileID, 0, LineStart, 300 ColumnStart, LineEnd, ColumnEnd, BranchRegion); 301 } 302 303 inline LineColPair startLoc() const { 304 return LineColPair(LineStart, ColumnStart); 305 } 306 307 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } 308 }; 309 310 /// Associates a source range with an execution count. 311 struct CountedRegion : public CounterMappingRegion { 312 uint64_t ExecutionCount; 313 uint64_t FalseExecutionCount; 314 bool Folded; 315 316 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) 317 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 318 FalseExecutionCount(0), Folded(false) {} 319 320 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, 321 uint64_t FalseExecutionCount) 322 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 323 FalseExecutionCount(FalseExecutionCount), Folded(false) {} 324 }; 325 326 /// A Counter mapping context is used to connect the counters, expressions 327 /// and the obtained counter values. 328 class CounterMappingContext { 329 ArrayRef<CounterExpression> Expressions; 330 ArrayRef<uint64_t> CounterValues; 331 332 public: 333 CounterMappingContext(ArrayRef<CounterExpression> Expressions, 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. 350 struct FunctionRecord { 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. 365 uint64_t ExecutionCount = 0; 366 367 FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 368 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 369 370 FunctionRecord(FunctionRecord &&FR) = default; 371 FunctionRecord &operator=(FunctionRecord &&) = default; 372 373 void pushRegion(CounterMappingRegion Region, uint64_t Count, 374 uint64_t FalseCount) { 375 if (Region.Kind == CounterMappingRegion::BranchRegion) { 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. 390 class FunctionRecordIterator 391 : public iterator_facade_base<FunctionRecordIterator, 392 std::forward_iterator_tag, FunctionRecord> { 393 ArrayRef<FunctionRecord> Records; 394 ArrayRef<FunctionRecord>::iterator Current; 395 StringRef Filename; 396 397 /// Skip records whose primary file is not \c Filename. 398 void skipOtherFiles(); 399 400 public: 401 FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 402 StringRef Filename = "") 403 : Records(Records_), Current(Records.begin()), Filename(Filename) { 404 skipOtherFiles(); 405 } 406 407 FunctionRecordIterator() : Current(Records.begin()) {} 408 409 bool operator==(const FunctionRecordIterator &RHS) const { 410 return Current == RHS.Current && Filename == RHS.Filename; 411 } 412 413 const FunctionRecord &operator*() const { return *Current; } 414 415 FunctionRecordIterator &operator++() { 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. 428 struct ExpansionRecord { 429 /// The abstract file this expansion covers. 430 unsigned FileID; 431 /// The region that expands to this record. 432 const CountedRegion &Region; 433 /// Coverage for the expansion. 434 const FunctionRecord &Function; 435 436 ExpansionRecord(const CountedRegion &Region, 437 const FunctionRecord &Function) 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. 445 struct CoverageSegment { 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. 451 uint64_t Count; 452 /// When false, the segment was uninstrumented or skipped. 453 bool HasCount; 454 /// Whether this enters a new region or returns to a previous count. 455 bool IsRegionEntry; 456 /// Whether this enters a gap region. 457 bool IsGapRegion; 458 459 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 460 : Line(Line), Col(Col), Count(0), HasCount(false), 461 IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 462 463 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 464 bool IsRegionEntry, bool IsGapRegion = false, 465 bool IsBranchRegion = false) 466 : Line(Line), Col(Col), Count(Count), HasCount(true), 467 IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 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). 482 class InstantiationGroup { 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 493 public: 494 InstantiationGroup(const InstantiationGroup &) = delete; 495 InstantiationGroup(InstantiationGroup &&) = default; 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. 515 StringRef getName() const { 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. 521 uint64_t getTotalExecutionCount() const { 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. 529 ArrayRef<const FunctionRecord *> getInstantiations() const { 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. 539 class CoverageData { 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 547 public: 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. 578 class CoverageMapping { 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. 606 ArrayRef<unsigned> 607 getImpreciseRecordIndicesForFilename(StringRef Filename) const; 608 609 public: 610 CoverageMapping(const CoverageMapping &) = delete; 611 CoverageMapping &operator=(const CoverageMapping &) = delete; 612 613 /// Load the coverage mapping using the given readers. 614 static Expected<std::unique_ptr<CoverageMapping>> 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. 621 static Expected<std::unique_ptr<CoverageMapping>> 622 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 623 vfs::FileSystem &FS, ArrayRef<StringRef> Arches = std::nullopt, 624 StringRef CompilationDir = "", 625 const object::BuildIDFetcher *BIDFetcher = nullptr, 626 bool CheckBinaryIDs = false); 627 628 /// The number of functions that couldn't have their profiles mapped. 629 /// 630 /// This is a count of functions whose profile is out of date or otherwise 631 /// can't be associated with any coverage information. 632 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } 633 634 /// A hash mismatch occurs when a profile record for a symbol does not have 635 /// the same hash as a coverage mapping record for the same symbol. This 636 /// returns a list of hash mismatches, where each mismatch is a pair of the 637 /// symbol name and its coverage mapping hash. 638 ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { 639 return FuncHashMismatches; 640 } 641 642 /// Returns a lexicographically sorted, unique list of files that are 643 /// covered. 644 std::vector<StringRef> getUniqueSourceFiles() const; 645 646 /// Get the coverage for a particular file. 647 /// 648 /// The given filename must be the name as recorded in the coverage 649 /// information. That is, only names returned from getUniqueSourceFiles will 650 /// yield a result. 651 CoverageData getCoverageForFile(StringRef Filename) const; 652 653 /// Get the coverage for a particular function. 654 CoverageData getCoverageForFunction(const FunctionRecord &Function) const; 655 656 /// Get the coverage for an expansion within a coverage set. 657 CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; 658 659 /// Gets all of the functions covered by this profile. 660 iterator_range<FunctionRecordIterator> getCoveredFunctions() const { 661 return make_range(FunctionRecordIterator(Functions), 662 FunctionRecordIterator()); 663 } 664 665 /// Gets all of the functions in a particular file. 666 iterator_range<FunctionRecordIterator> 667 getCoveredFunctions(StringRef Filename) const { 668 return make_range(FunctionRecordIterator(Functions, Filename), 669 FunctionRecordIterator()); 670 } 671 672 /// Get the list of function instantiation groups in a particular file. 673 /// 674 /// Every instantiation group in a program is attributed to exactly one file: 675 /// the file in which the definition for the common function begins. 676 std::vector<InstantiationGroup> 677 getInstantiationGroups(StringRef Filename) const; 678 }; 679 680 /// Coverage statistics for a single line. 681 class LineCoverageStats { 682 uint64_t ExecutionCount; 683 bool HasMultipleRegions; 684 bool Mapped; 685 unsigned Line; 686 ArrayRef<const CoverageSegment *> LineSegments; 687 const CoverageSegment *WrappedSegment; 688 689 friend class LineCoverageIterator; 690 LineCoverageStats() = default; 691 692 public: 693 LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, 694 const CoverageSegment *WrappedSegment, unsigned Line); 695 696 uint64_t getExecutionCount() const { return ExecutionCount; } 697 698 bool hasMultipleRegions() const { return HasMultipleRegions; } 699 700 bool isMapped() const { return Mapped; } 701 702 unsigned getLine() const { return Line; } 703 704 ArrayRef<const CoverageSegment *> getLineSegments() const { 705 return LineSegments; 706 } 707 708 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } 709 }; 710 711 /// An iterator over the \c LineCoverageStats objects for lines described by 712 /// a \c CoverageData instance. 713 class LineCoverageIterator 714 : public iterator_facade_base<LineCoverageIterator, 715 std::forward_iterator_tag, 716 const LineCoverageStats> { 717 public: 718 LineCoverageIterator(const CoverageData &CD) 719 : LineCoverageIterator(CD, CD.begin()->Line) {} 720 721 LineCoverageIterator(const CoverageData &CD, unsigned Line) 722 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), 723 Line(Line) { 724 this->operator++(); 725 } 726 727 bool operator==(const LineCoverageIterator &R) const { 728 return &CD == &R.CD && Next == R.Next && Ended == R.Ended; 729 } 730 731 const LineCoverageStats &operator*() const { return Stats; } 732 733 LineCoverageIterator &operator++(); 734 735 LineCoverageIterator getEnd() const { 736 auto EndIt = *this; 737 EndIt.Next = CD.end(); 738 EndIt.Ended = true; 739 return EndIt; 740 } 741 742 private: 743 const CoverageData &CD; 744 const CoverageSegment *WrappedSegment; 745 std::vector<CoverageSegment>::const_iterator Next; 746 bool Ended; 747 unsigned Line; 748 SmallVector<const CoverageSegment *, 4> Segments; 749 LineCoverageStats Stats; 750 }; 751 752 /// Get a \c LineCoverageIterator range for the lines described by \p CD. 753 static inline iterator_range<LineCoverageIterator> 754 getLineCoverageStats(const coverage::CoverageData &CD) { 755 auto Begin = LineCoverageIterator(CD); 756 auto End = Begin.getEnd(); 757 return make_range(Begin, End); 758 } 759 760 // Coverage mappping data (V2) has the following layout: 761 // IPSK_covmap: 762 // [CoverageMapFileHeader] 763 // [ArrayStart] 764 // [CovMapFunctionRecordV2] 765 // [CovMapFunctionRecordV2] 766 // ... 767 // [ArrayEnd] 768 // [Encoded Filenames and Region Mapping Data] 769 // 770 // Coverage mappping data (V3) has the following layout: 771 // IPSK_covmap: 772 // [CoverageMapFileHeader] 773 // [Encoded Filenames] 774 // IPSK_covfun: 775 // [ArrayStart] 776 // odr_name_1: [CovMapFunctionRecordV3] 777 // odr_name_2: [CovMapFunctionRecordV3] 778 // ... 779 // [ArrayEnd] 780 // 781 // Both versions of the coverage mapping format encode the same information, 782 // but the V3 format does so more compactly by taking advantage of linkonce_odr 783 // semantics (it allows exactly 1 function record per name reference). 784 785 /// This namespace defines accessors shared by different versions of coverage 786 /// mapping records. 787 namespace accessors { 788 789 /// Return the structural hash associated with the function. 790 template <class FuncRecordTy, support::endianness Endian> 791 uint64_t getFuncHash(const FuncRecordTy *Record) { 792 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash); 793 } 794 795 /// Return the coverage map data size for the function. 796 template <class FuncRecordTy, support::endianness Endian> 797 uint64_t getDataSize(const FuncRecordTy *Record) { 798 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize); 799 } 800 801 /// Return the function lookup key. The value is considered opaque. 802 template <class FuncRecordTy, support::endianness Endian> 803 uint64_t getFuncNameRef(const FuncRecordTy *Record) { 804 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef); 805 } 806 807 /// Return the PGO name of the function. Used for formats in which the name is 808 /// a hash. 809 template <class FuncRecordTy, support::endianness Endian> 810 Error getFuncNameViaRef(const FuncRecordTy *Record, 811 InstrProfSymtab &ProfileNames, StringRef &FuncName) { 812 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record); 813 FuncName = ProfileNames.getFuncName(NameRef); 814 return Error::success(); 815 } 816 817 /// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the 818 /// coverage mapping is attached to the file header, instead of to the function 819 /// record. 820 template <class FuncRecordTy, support::endianness Endian> 821 StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record, 822 const char *MappingBuf) { 823 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))}; 824 } 825 826 /// Advance to the next out-of-line coverage mapping and its associated 827 /// function record. 828 template <class FuncRecordTy, support::endianness Endian> 829 std::pair<const char *, const FuncRecordTy *> 830 advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) { 831 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1}; 832 } 833 834 } // end namespace accessors 835 836 LLVM_PACKED_START 837 template <class IntPtrT> 838 struct CovMapFunctionRecordV1 { 839 using ThisT = CovMapFunctionRecordV1<IntPtrT>; 840 841 #define COVMAP_V1 842 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 843 #include "llvm/ProfileData/InstrProfData.inc" 844 #undef COVMAP_V1 845 CovMapFunctionRecordV1() = delete; 846 847 template <support::endianness Endian> uint64_t getFuncHash() const { 848 return accessors::getFuncHash<ThisT, Endian>(this); 849 } 850 851 template <support::endianness Endian> uint64_t getDataSize() const { 852 return accessors::getDataSize<ThisT, Endian>(this); 853 } 854 855 /// Return function lookup key. The value is consider opaque. 856 template <support::endianness Endian> IntPtrT getFuncNameRef() const { 857 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); 858 } 859 860 /// Return the PGO name of the function. 861 template <support::endianness Endian> 862 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 863 IntPtrT NameRef = getFuncNameRef<Endian>(); 864 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); 865 FuncName = ProfileNames.getFuncName(NameRef, NameS); 866 if (NameS && FuncName.empty()) 867 return make_error<CoverageMapError>(coveragemap_error::malformed); 868 return Error::success(); 869 } 870 871 template <support::endianness Endian> 872 std::pair<const char *, const ThisT *> 873 advanceByOne(const char *MappingBuf) const { 874 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 875 } 876 877 template <support::endianness Endian> uint64_t getFilenamesRef() const { 878 llvm_unreachable("V1 function format does not contain a filenames ref"); 879 } 880 881 template <support::endianness Endian> 882 StringRef getCoverageMapping(const char *MappingBuf) const { 883 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 884 MappingBuf); 885 } 886 }; 887 888 struct CovMapFunctionRecordV2 { 889 using ThisT = CovMapFunctionRecordV2; 890 891 #define COVMAP_V2 892 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 893 #include "llvm/ProfileData/InstrProfData.inc" 894 #undef COVMAP_V2 895 CovMapFunctionRecordV2() = delete; 896 897 template <support::endianness Endian> uint64_t getFuncHash() const { 898 return accessors::getFuncHash<ThisT, Endian>(this); 899 } 900 901 template <support::endianness Endian> uint64_t getDataSize() const { 902 return accessors::getDataSize<ThisT, Endian>(this); 903 } 904 905 template <support::endianness Endian> uint64_t getFuncNameRef() const { 906 return accessors::getFuncNameRef<ThisT, Endian>(this); 907 } 908 909 template <support::endianness Endian> 910 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 911 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 912 FuncName); 913 } 914 915 template <support::endianness Endian> 916 std::pair<const char *, const ThisT *> 917 advanceByOne(const char *MappingBuf) const { 918 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 919 } 920 921 template <support::endianness Endian> uint64_t getFilenamesRef() const { 922 llvm_unreachable("V2 function format does not contain a filenames ref"); 923 } 924 925 template <support::endianness Endian> 926 StringRef getCoverageMapping(const char *MappingBuf) const { 927 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 928 MappingBuf); 929 } 930 }; 931 932 struct CovMapFunctionRecordV3 { 933 using ThisT = CovMapFunctionRecordV3; 934 935 #define COVMAP_V3 936 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 937 #include "llvm/ProfileData/InstrProfData.inc" 938 #undef COVMAP_V3 939 CovMapFunctionRecordV3() = delete; 940 941 template <support::endianness Endian> uint64_t getFuncHash() const { 942 return accessors::getFuncHash<ThisT, Endian>(this); 943 } 944 945 template <support::endianness Endian> uint64_t getDataSize() const { 946 return accessors::getDataSize<ThisT, Endian>(this); 947 } 948 949 template <support::endianness Endian> uint64_t getFuncNameRef() const { 950 return accessors::getFuncNameRef<ThisT, Endian>(this); 951 } 952 953 template <support::endianness Endian> 954 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 955 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 956 FuncName); 957 } 958 959 /// Get the filename set reference. 960 template <support::endianness Endian> uint64_t getFilenamesRef() const { 961 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef); 962 } 963 964 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for 965 /// out-of-line coverage mapping data only. 966 template <support::endianness Endian> 967 StringRef getCoverageMapping(const char *) const { 968 return StringRef(&CoverageMapping, getDataSize<Endian>()); 969 } 970 971 // Advance to the next inline coverage mapping and its associated function 972 // record. Ignore the out-of-line coverage mapping buffer. 973 template <support::endianness Endian> 974 std::pair<const char *, const CovMapFunctionRecordV3 *> 975 advanceByOne(const char *) const { 976 assert(isAddrAligned(Align(8), this) && "Function record not aligned"); 977 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) - 978 sizeof(char) + getDataSize<Endian>(); 979 // Each function record has an alignment of 8, so we need to adjust 980 // alignment before reading the next record. 981 Next += offsetToAlignedAddr(Next, Align(8)); 982 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)}; 983 } 984 }; 985 986 // Per module coverage mapping data header, i.e. CoverageMapFileHeader 987 // documented above. 988 struct CovMapHeader { 989 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; 990 #include "llvm/ProfileData/InstrProfData.inc" 991 template <support::endianness Endian> uint32_t getNRecords() const { 992 return support::endian::byte_swap<uint32_t, Endian>(NRecords); 993 } 994 995 template <support::endianness Endian> uint32_t getFilenamesSize() const { 996 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); 997 } 998 999 template <support::endianness Endian> uint32_t getCoverageSize() const { 1000 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); 1001 } 1002 1003 template <support::endianness Endian> uint32_t getVersion() const { 1004 return support::endian::byte_swap<uint32_t, Endian>(Version); 1005 } 1006 }; 1007 1008 LLVM_PACKED_END 1009 1010 enum CovMapVersion { 1011 Version1 = 0, 1012 // Function's name reference from CovMapFuncRecord is changed from raw 1013 // name string pointer to MD5 to support name section compression. Name 1014 // section is also compressed. 1015 Version2 = 1, 1016 // A new interpretation of the columnEnd field is added in order to mark 1017 // regions as gap areas. 1018 Version3 = 2, 1019 // Function records are named, uniqued, and moved to a dedicated section. 1020 Version4 = 3, 1021 // Branch regions referring to two counters are added 1022 Version5 = 4, 1023 // Compilation directory is stored separately and combined with relative 1024 // filenames to produce an absolute file path. 1025 Version6 = 5, 1026 // The current version is Version6. 1027 CurrentVersion = INSTR_PROF_COVMAP_VERSION 1028 }; 1029 1030 template <int CovMapVersion, class IntPtrT> struct CovMapTraits { 1031 using CovMapFuncRecordType = CovMapFunctionRecordV3; 1032 using NameRefType = uint64_t; 1033 }; 1034 1035 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> { 1036 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1037 using NameRefType = uint64_t; 1038 }; 1039 1040 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> { 1041 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1042 using NameRefType = uint64_t; 1043 }; 1044 1045 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { 1046 using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; 1047 using NameRefType = IntPtrT; 1048 }; 1049 1050 } // end namespace coverage 1051 1052 /// Provide DenseMapInfo for CounterExpression 1053 template<> struct DenseMapInfo<coverage::CounterExpression> { 1054 static inline coverage::CounterExpression getEmptyKey() { 1055 using namespace coverage; 1056 1057 return CounterExpression(CounterExpression::ExprKind::Subtract, 1058 Counter::getCounter(~0U), 1059 Counter::getCounter(~0U)); 1060 } 1061 1062 static inline coverage::CounterExpression getTombstoneKey() { 1063 using namespace coverage; 1064 1065 return CounterExpression(CounterExpression::ExprKind::Add, 1066 Counter::getCounter(~0U), 1067 Counter::getCounter(~0U)); 1068 } 1069 1070 static unsigned getHashValue(const coverage::CounterExpression &V) { 1071 return static_cast<unsigned>( 1072 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), 1073 V.RHS.getKind(), V.RHS.getCounterID())); 1074 } 1075 1076 static bool isEqual(const coverage::CounterExpression &LHS, 1077 const coverage::CounterExpression &RHS) { 1078 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; 1079 } 1080 }; 1081 1082 } // end namespace llvm 1083 1084 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 1085