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