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/None.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/ADT/iterator.h" 24 #include "llvm/ADT/iterator_range.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 coverage { 47 48 class CoverageMappingReader; 49 struct CoverageMappingRecord; 50 51 enum class coveragemap_error { 52 success = 0, 53 eof, 54 no_data_found, 55 unsupported_version, 56 truncated, 57 malformed, 58 decompression_failed, 59 invalid_or_missing_arch_specifier 60 }; 61 62 const std::error_category &coveragemap_category(); 63 64 inline std::error_code make_error_code(coveragemap_error E) { 65 return std::error_code(static_cast<int>(E), coveragemap_category()); 66 } 67 68 class CoverageMapError : public ErrorInfo<CoverageMapError> { 69 public: 70 CoverageMapError(coveragemap_error Err) : Err(Err) { 71 assert(Err != coveragemap_error::success && "Not an error"); 72 } 73 74 std::string message() const override; 75 76 void log(raw_ostream &OS) const override { OS << message(); } 77 78 std::error_code convertToErrorCode() const override { 79 return make_error_code(Err); 80 } 81 82 coveragemap_error get() const { return Err; } 83 84 static char ID; 85 86 private: 87 coveragemap_error Err; 88 }; 89 90 /// A Counter is an abstract value that describes how to compute the 91 /// execution count for a region of code using the collected profile count data. 92 struct Counter { 93 /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to 94 /// the CounterKind. This means CounterKind has to leave bit 0 free. 95 enum CounterKind { Zero, CounterValueReference, Expression }; 96 static const unsigned EncodingTagBits = 2; 97 static const unsigned EncodingTagMask = 0x3; 98 static const unsigned EncodingCounterTagAndExpansionRegionTagBits = 99 EncodingTagBits + 1; 100 101 private: 102 CounterKind Kind = Zero; 103 unsigned ID = 0; 104 105 Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} 106 107 public: 108 Counter() = default; 109 110 CounterKind getKind() const { return Kind; } 111 112 bool isZero() const { return Kind == Zero; } 113 114 bool isExpression() const { return Kind == Expression; } 115 116 unsigned getCounterID() const { return ID; } 117 118 unsigned getExpressionID() const { return ID; } 119 120 friend bool operator==(const Counter &LHS, const Counter &RHS) { 121 return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; 122 } 123 124 friend bool operator!=(const Counter &LHS, const Counter &RHS) { 125 return !(LHS == RHS); 126 } 127 128 friend bool operator<(const Counter &LHS, const Counter &RHS) { 129 return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); 130 } 131 132 /// Return the counter that represents the number zero. 133 static Counter getZero() { return Counter(); } 134 135 /// Return the counter that corresponds to a specific profile counter. 136 static Counter getCounter(unsigned CounterId) { 137 return Counter(CounterValueReference, CounterId); 138 } 139 140 /// Return the counter that corresponds to a specific addition counter 141 /// expression. 142 static Counter getExpression(unsigned ExpressionId) { 143 return Counter(Expression, ExpressionId); 144 } 145 }; 146 147 /// A Counter expression is a value that represents an arithmetic operation 148 /// with two counters. 149 struct CounterExpression { 150 enum ExprKind { Subtract, Add }; 151 ExprKind Kind; 152 Counter LHS, RHS; 153 154 CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) 155 : Kind(Kind), LHS(LHS), RHS(RHS) {} 156 }; 157 158 /// A Counter expression builder is used to construct the counter expressions. 159 /// It avoids unnecessary duplication and simplifies algebraic expressions. 160 class CounterExpressionBuilder { 161 /// A list of all the counter expressions 162 std::vector<CounterExpression> Expressions; 163 164 /// A lookup table for the index of a given expression. 165 DenseMap<CounterExpression, unsigned> ExpressionIndices; 166 167 /// Return the counter which corresponds to the given expression. 168 /// 169 /// If the given expression is already stored in the builder, a counter 170 /// that references that expression is returned. Otherwise, the given 171 /// expression is added to the builder's collection of expressions. 172 Counter get(const CounterExpression &E); 173 174 /// Represents a term in a counter expression tree. 175 struct Term { 176 unsigned CounterID; 177 int Factor; 178 179 Term(unsigned CounterID, int Factor) 180 : CounterID(CounterID), Factor(Factor) {} 181 }; 182 183 /// Gather the terms of the expression tree for processing. 184 /// 185 /// This collects each addition and subtraction referenced by the counter into 186 /// a sequence that can be sorted and combined to build a simplified counter 187 /// expression. 188 void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms); 189 190 /// Simplifies the given expression tree 191 /// by getting rid of algebraically redundant operations. 192 Counter simplify(Counter ExpressionTree); 193 194 public: 195 ArrayRef<CounterExpression> getExpressions() const { return Expressions; } 196 197 /// Return a counter that represents the expression that adds LHS and RHS. 198 Counter add(Counter LHS, Counter RHS, bool Simplify = true); 199 200 /// Return a counter that represents the expression that subtracts RHS from 201 /// LHS. 202 Counter subtract(Counter LHS, Counter RHS, bool Simplify = true); 203 }; 204 205 using LineColPair = std::pair<unsigned, unsigned>; 206 207 /// A Counter mapping region associates a source range with a specific counter. 208 struct CounterMappingRegion { 209 enum RegionKind { 210 /// A CodeRegion associates some code with a counter 211 CodeRegion, 212 213 /// An ExpansionRegion represents a file expansion region that associates 214 /// a source range with the expansion of a virtual source file, such as 215 /// for a macro instantiation or #include file. 216 ExpansionRegion, 217 218 /// A SkippedRegion represents a source range with code that was skipped 219 /// by a preprocessor or similar means. 220 SkippedRegion, 221 222 /// A GapRegion is like a CodeRegion, but its count is only set as the 223 /// line execution count when its the only region in the line. 224 GapRegion, 225 226 /// A BranchRegion represents leaf-level boolean expressions and is 227 /// associated with two counters, each representing the number of times the 228 /// expression evaluates to true or false. 229 BranchRegion 230 }; 231 232 /// Primary Counter that is also used for Branch Regions (TrueCount). 233 Counter Count; 234 235 /// Secondary Counter used for Branch Regions (FalseCount). 236 Counter FalseCount; 237 238 unsigned FileID, ExpandedFileID; 239 unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; 240 RegionKind Kind; 241 242 CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, 243 unsigned LineStart, unsigned ColumnStart, 244 unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) 245 : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), 246 LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), 247 ColumnEnd(ColumnEnd), Kind(Kind) {} 248 249 CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, 250 unsigned ExpandedFileID, unsigned LineStart, 251 unsigned ColumnStart, unsigned LineEnd, 252 unsigned ColumnEnd, RegionKind Kind) 253 : Count(Count), FalseCount(FalseCount), FileID(FileID), 254 ExpandedFileID(ExpandedFileID), LineStart(LineStart), 255 ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), 256 Kind(Kind) {} 257 258 static CounterMappingRegion 259 makeRegion(Counter Count, unsigned FileID, unsigned LineStart, 260 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 261 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 262 LineEnd, ColumnEnd, CodeRegion); 263 } 264 265 static CounterMappingRegion 266 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, 267 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 268 return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, 269 ColumnStart, LineEnd, ColumnEnd, 270 ExpansionRegion); 271 } 272 273 static CounterMappingRegion 274 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, 275 unsigned LineEnd, unsigned ColumnEnd) { 276 return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, 277 LineEnd, ColumnEnd, SkippedRegion); 278 } 279 280 static CounterMappingRegion 281 makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, 282 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 283 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 284 LineEnd, (1U << 31) | ColumnEnd, GapRegion); 285 } 286 287 static CounterMappingRegion 288 makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, 289 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, 290 unsigned ColumnEnd) { 291 return CounterMappingRegion(Count, FalseCount, FileID, 0, LineStart, 292 ColumnStart, LineEnd, ColumnEnd, BranchRegion); 293 } 294 295 inline LineColPair startLoc() const { 296 return LineColPair(LineStart, ColumnStart); 297 } 298 299 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } 300 }; 301 302 /// Associates a source range with an execution count. 303 struct CountedRegion : public CounterMappingRegion { 304 uint64_t ExecutionCount; 305 uint64_t FalseExecutionCount; 306 bool Folded; 307 308 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) 309 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 310 FalseExecutionCount(0), Folded(false) {} 311 312 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, 313 uint64_t FalseExecutionCount) 314 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 315 FalseExecutionCount(FalseExecutionCount), Folded(false) {} 316 }; 317 318 /// A Counter mapping context is used to connect the counters, expressions 319 /// and the obtained counter values. 320 class CounterMappingContext { 321 ArrayRef<CounterExpression> Expressions; 322 ArrayRef<uint64_t> CounterValues; 323 324 public: 325 CounterMappingContext(ArrayRef<CounterExpression> Expressions, 326 ArrayRef<uint64_t> CounterValues = None) 327 : Expressions(Expressions), CounterValues(CounterValues) {} 328 329 void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } 330 331 void dump(const Counter &C, raw_ostream &OS) const; 332 void dump(const Counter &C) const { dump(C, dbgs()); } 333 334 /// Return the number of times that a region of code associated with this 335 /// counter was executed. 336 Expected<int64_t> evaluate(const Counter &C) const; 337 338 unsigned getMaxCounterID(const Counter &C) const; 339 }; 340 341 /// Code coverage information for a single function. 342 struct FunctionRecord { 343 /// Raw function name. 344 std::string Name; 345 /// Mapping from FileID (i.e. vector index) to filename. Used to support 346 /// macro expansions within a function in which the macro and function are 347 /// defined in separate files. 348 /// 349 /// TODO: Uniquing filenames across all function records may be a performance 350 /// optimization. 351 std::vector<std::string> Filenames; 352 /// Regions in the function along with their counts. 353 std::vector<CountedRegion> CountedRegions; 354 /// Branch Regions in the function along with their counts. 355 std::vector<CountedRegion> CountedBranchRegions; 356 /// The number of times this function was executed. 357 uint64_t ExecutionCount = 0; 358 359 FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 360 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 361 362 FunctionRecord(FunctionRecord &&FR) = default; 363 FunctionRecord &operator=(FunctionRecord &&) = default; 364 365 void pushRegion(CounterMappingRegion Region, uint64_t Count, 366 uint64_t FalseCount) { 367 if (Region.Kind == CounterMappingRegion::BranchRegion) { 368 CountedBranchRegions.emplace_back(Region, Count, FalseCount); 369 // If both counters are hard-coded to zero, then this region represents a 370 // constant-folded branch. 371 if (Region.Count.isZero() && Region.FalseCount.isZero()) 372 CountedBranchRegions.back().Folded = true; 373 return; 374 } 375 if (CountedRegions.empty()) 376 ExecutionCount = Count; 377 CountedRegions.emplace_back(Region, Count, FalseCount); 378 } 379 }; 380 381 /// Iterator over Functions, optionally filtered to a single file. 382 class FunctionRecordIterator 383 : public iterator_facade_base<FunctionRecordIterator, 384 std::forward_iterator_tag, FunctionRecord> { 385 ArrayRef<FunctionRecord> Records; 386 ArrayRef<FunctionRecord>::iterator Current; 387 StringRef Filename; 388 389 /// Skip records whose primary file is not \c Filename. 390 void skipOtherFiles(); 391 392 public: 393 FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 394 StringRef Filename = "") 395 : Records(Records_), Current(Records.begin()), Filename(Filename) { 396 skipOtherFiles(); 397 } 398 399 FunctionRecordIterator() : Current(Records.begin()) {} 400 401 bool operator==(const FunctionRecordIterator &RHS) const { 402 return Current == RHS.Current && Filename == RHS.Filename; 403 } 404 405 const FunctionRecord &operator*() const { return *Current; } 406 407 FunctionRecordIterator &operator++() { 408 assert(Current != Records.end() && "incremented past end"); 409 ++Current; 410 skipOtherFiles(); 411 return *this; 412 } 413 }; 414 415 /// Coverage information for a macro expansion or #included file. 416 /// 417 /// When covered code has pieces that can be expanded for more detail, such as a 418 /// preprocessor macro use and its definition, these are represented as 419 /// expansions whose coverage can be looked up independently. 420 struct ExpansionRecord { 421 /// The abstract file this expansion covers. 422 unsigned FileID; 423 /// The region that expands to this record. 424 const CountedRegion &Region; 425 /// Coverage for the expansion. 426 const FunctionRecord &Function; 427 428 ExpansionRecord(const CountedRegion &Region, 429 const FunctionRecord &Function) 430 : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} 431 }; 432 433 /// The execution count information starting at a point in a file. 434 /// 435 /// A sequence of CoverageSegments gives execution counts for a file in format 436 /// that's simple to iterate through for processing. 437 struct CoverageSegment { 438 /// The line where this segment begins. 439 unsigned Line; 440 /// The column where this segment begins. 441 unsigned Col; 442 /// The execution count, or zero if no count was recorded. 443 uint64_t Count; 444 /// When false, the segment was uninstrumented or skipped. 445 bool HasCount; 446 /// Whether this enters a new region or returns to a previous count. 447 bool IsRegionEntry; 448 /// Whether this enters a gap region. 449 bool IsGapRegion; 450 451 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 452 : Line(Line), Col(Col), Count(0), HasCount(false), 453 IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 454 455 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 456 bool IsRegionEntry, bool IsGapRegion = false, 457 bool IsBranchRegion = false) 458 : Line(Line), Col(Col), Count(Count), HasCount(true), 459 IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 460 461 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { 462 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, 463 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, 464 R.HasCount, R.IsRegionEntry, 465 R.IsGapRegion); 466 } 467 }; 468 469 /// An instantiation group contains a \c FunctionRecord list, such that each 470 /// record corresponds to a distinct instantiation of the same function. 471 /// 472 /// Note that it's possible for a function to have more than one instantiation 473 /// (consider C++ template specializations or static inline functions). 474 class InstantiationGroup { 475 friend class CoverageMapping; 476 477 unsigned Line; 478 unsigned Col; 479 std::vector<const FunctionRecord *> Instantiations; 480 481 InstantiationGroup(unsigned Line, unsigned Col, 482 std::vector<const FunctionRecord *> Instantiations) 483 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} 484 485 public: 486 InstantiationGroup(const InstantiationGroup &) = delete; 487 InstantiationGroup(InstantiationGroup &&) = default; 488 489 /// Get the number of instantiations in this group. 490 size_t size() const { return Instantiations.size(); } 491 492 /// Get the line where the common function was defined. 493 unsigned getLine() const { return Line; } 494 495 /// Get the column where the common function was defined. 496 unsigned getColumn() const { return Col; } 497 498 /// Check if the instantiations in this group have a common mangled name. 499 bool hasName() const { 500 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) 501 if (Instantiations[I]->Name != Instantiations[0]->Name) 502 return false; 503 return true; 504 } 505 506 /// Get the common mangled name for instantiations in this group. 507 StringRef getName() const { 508 assert(hasName() && "Instantiations don't have a shared name"); 509 return Instantiations[0]->Name; 510 } 511 512 /// Get the total execution count of all instantiations in this group. 513 uint64_t getTotalExecutionCount() const { 514 uint64_t Count = 0; 515 for (const FunctionRecord *F : Instantiations) 516 Count += F->ExecutionCount; 517 return Count; 518 } 519 520 /// Get the instantiations in this group. 521 ArrayRef<const FunctionRecord *> getInstantiations() const { 522 return Instantiations; 523 } 524 }; 525 526 /// Coverage information to be processed or displayed. 527 /// 528 /// This represents the coverage of an entire file, expansion, or function. It 529 /// provides a sequence of CoverageSegments to iterate through, as well as the 530 /// list of expansions that can be further processed. 531 class CoverageData { 532 friend class CoverageMapping; 533 534 std::string Filename; 535 std::vector<CoverageSegment> Segments; 536 std::vector<ExpansionRecord> Expansions; 537 std::vector<CountedRegion> BranchRegions; 538 539 public: 540 CoverageData() = default; 541 542 CoverageData(StringRef Filename) : Filename(Filename) {} 543 544 /// Get the name of the file this data covers. 545 StringRef getFilename() const { return Filename; } 546 547 /// Get an iterator over the coverage segments for this object. The segments 548 /// are guaranteed to be uniqued and sorted by location. 549 std::vector<CoverageSegment>::const_iterator begin() const { 550 return Segments.begin(); 551 } 552 553 std::vector<CoverageSegment>::const_iterator end() const { 554 return Segments.end(); 555 } 556 557 bool empty() const { return Segments.empty(); } 558 559 /// Expansions that can be further processed. 560 ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } 561 562 /// Branches that can be further processed. 563 ArrayRef<CountedRegion> getBranches() const { return BranchRegions; } 564 }; 565 566 /// The mapping of profile information to coverage data. 567 /// 568 /// This is the main interface to get coverage information, using a profile to 569 /// fill out execution counts. 570 class CoverageMapping { 571 DenseMap<size_t, DenseSet<size_t>> RecordProvenance; 572 std::vector<FunctionRecord> Functions; 573 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices; 574 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; 575 576 CoverageMapping() = default; 577 578 // Load coverage records from readers. 579 static Error loadFromReaders( 580 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 581 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage); 582 583 /// Add a function record corresponding to \p Record. 584 Error loadFunctionRecord(const CoverageMappingRecord &Record, 585 IndexedInstrProfReader &ProfileReader); 586 587 /// Look up the indices for function records which are at least partially 588 /// defined in the specified file. This is guaranteed to return a superset of 589 /// such records: extra records not in the file may be included if there is 590 /// a hash collision on the filename. Clients must be robust to collisions. 591 ArrayRef<unsigned> 592 getImpreciseRecordIndicesForFilename(StringRef Filename) const; 593 594 public: 595 CoverageMapping(const CoverageMapping &) = delete; 596 CoverageMapping &operator=(const CoverageMapping &) = delete; 597 598 /// Load the coverage mapping using the given readers. 599 static Expected<std::unique_ptr<CoverageMapping>> 600 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 601 IndexedInstrProfReader &ProfileReader); 602 603 /// Load the coverage mapping from the given object files and profile. If 604 /// \p Arches is non-empty, it must specify an architecture for each object. 605 /// Ignores non-instrumented object files unless all are not instrumented. 606 static Expected<std::unique_ptr<CoverageMapping>> 607 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 608 ArrayRef<StringRef> Arches = None, 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