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); 199 200 /// Return a counter that represents the expression that subtracts RHS from 201 /// LHS. 202 Counter subtract(Counter LHS, Counter RHS); 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 339 /// Code coverage information for a single function. 340 struct FunctionRecord { 341 /// Raw function name. 342 std::string Name; 343 /// Mapping from FileID (i.e. vector index) to filename. Used to support 344 /// macro expansions within a function in which the macro and function are 345 /// defined in separate files. 346 /// 347 /// TODO: Uniquing filenames across all function records may be a performance 348 /// optimization. 349 std::vector<std::string> Filenames; 350 /// Regions in the function along with their counts. 351 std::vector<CountedRegion> CountedRegions; 352 /// Branch Regions in the function along with their counts. 353 std::vector<CountedRegion> CountedBranchRegions; 354 /// The number of times this function was executed. 355 uint64_t ExecutionCount = 0; 356 357 FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 358 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 359 360 FunctionRecord(FunctionRecord &&FR) = default; 361 FunctionRecord &operator=(FunctionRecord &&) = default; 362 363 void pushRegion(CounterMappingRegion Region, uint64_t Count, 364 uint64_t FalseCount) { 365 if (Region.Kind == CounterMappingRegion::BranchRegion) { 366 CountedBranchRegions.emplace_back(Region, Count, FalseCount); 367 // If both counters are hard-coded to zero, then this region represents a 368 // constant-folded branch. 369 if (Region.Count.isZero() && Region.FalseCount.isZero()) 370 CountedBranchRegions.back().Folded = true; 371 return; 372 } 373 if (CountedRegions.empty()) 374 ExecutionCount = Count; 375 CountedRegions.emplace_back(Region, Count, FalseCount); 376 } 377 }; 378 379 /// Iterator over Functions, optionally filtered to a single file. 380 class FunctionRecordIterator 381 : public iterator_facade_base<FunctionRecordIterator, 382 std::forward_iterator_tag, FunctionRecord> { 383 ArrayRef<FunctionRecord> Records; 384 ArrayRef<FunctionRecord>::iterator Current; 385 StringRef Filename; 386 387 /// Skip records whose primary file is not \c Filename. 388 void skipOtherFiles(); 389 390 public: 391 FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 392 StringRef Filename = "") 393 : Records(Records_), Current(Records.begin()), Filename(Filename) { 394 skipOtherFiles(); 395 } 396 397 FunctionRecordIterator() : Current(Records.begin()) {} 398 399 bool operator==(const FunctionRecordIterator &RHS) const { 400 return Current == RHS.Current && Filename == RHS.Filename; 401 } 402 403 const FunctionRecord &operator*() const { return *Current; } 404 405 FunctionRecordIterator &operator++() { 406 assert(Current != Records.end() && "incremented past end"); 407 ++Current; 408 skipOtherFiles(); 409 return *this; 410 } 411 }; 412 413 /// Coverage information for a macro expansion or #included file. 414 /// 415 /// When covered code has pieces that can be expanded for more detail, such as a 416 /// preprocessor macro use and its definition, these are represented as 417 /// expansions whose coverage can be looked up independently. 418 struct ExpansionRecord { 419 /// The abstract file this expansion covers. 420 unsigned FileID; 421 /// The region that expands to this record. 422 const CountedRegion &Region; 423 /// Coverage for the expansion. 424 const FunctionRecord &Function; 425 426 ExpansionRecord(const CountedRegion &Region, 427 const FunctionRecord &Function) 428 : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} 429 }; 430 431 /// The execution count information starting at a point in a file. 432 /// 433 /// A sequence of CoverageSegments gives execution counts for a file in format 434 /// that's simple to iterate through for processing. 435 struct CoverageSegment { 436 /// The line where this segment begins. 437 unsigned Line; 438 /// The column where this segment begins. 439 unsigned Col; 440 /// The execution count, or zero if no count was recorded. 441 uint64_t Count; 442 /// When false, the segment was uninstrumented or skipped. 443 bool HasCount; 444 /// Whether this enters a new region or returns to a previous count. 445 bool IsRegionEntry; 446 /// Whether this enters a gap region. 447 bool IsGapRegion; 448 449 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 450 : Line(Line), Col(Col), Count(0), HasCount(false), 451 IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 452 453 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 454 bool IsRegionEntry, bool IsGapRegion = false, 455 bool IsBranchRegion = false) 456 : Line(Line), Col(Col), Count(Count), HasCount(true), 457 IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 458 459 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { 460 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, 461 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, 462 R.HasCount, R.IsRegionEntry, 463 R.IsGapRegion); 464 } 465 }; 466 467 /// An instantiation group contains a \c FunctionRecord list, such that each 468 /// record corresponds to a distinct instantiation of the same function. 469 /// 470 /// Note that it's possible for a function to have more than one instantiation 471 /// (consider C++ template specializations or static inline functions). 472 class InstantiationGroup { 473 friend class CoverageMapping; 474 475 unsigned Line; 476 unsigned Col; 477 std::vector<const FunctionRecord *> Instantiations; 478 479 InstantiationGroup(unsigned Line, unsigned Col, 480 std::vector<const FunctionRecord *> Instantiations) 481 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} 482 483 public: 484 InstantiationGroup(const InstantiationGroup &) = delete; 485 InstantiationGroup(InstantiationGroup &&) = default; 486 487 /// Get the number of instantiations in this group. 488 size_t size() const { return Instantiations.size(); } 489 490 /// Get the line where the common function was defined. 491 unsigned getLine() const { return Line; } 492 493 /// Get the column where the common function was defined. 494 unsigned getColumn() const { return Col; } 495 496 /// Check if the instantiations in this group have a common mangled name. 497 bool hasName() const { 498 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) 499 if (Instantiations[I]->Name != Instantiations[0]->Name) 500 return false; 501 return true; 502 } 503 504 /// Get the common mangled name for instantiations in this group. 505 StringRef getName() const { 506 assert(hasName() && "Instantiations don't have a shared name"); 507 return Instantiations[0]->Name; 508 } 509 510 /// Get the total execution count of all instantiations in this group. 511 uint64_t getTotalExecutionCount() const { 512 uint64_t Count = 0; 513 for (const FunctionRecord *F : Instantiations) 514 Count += F->ExecutionCount; 515 return Count; 516 } 517 518 /// Get the instantiations in this group. 519 ArrayRef<const FunctionRecord *> getInstantiations() const { 520 return Instantiations; 521 } 522 }; 523 524 /// Coverage information to be processed or displayed. 525 /// 526 /// This represents the coverage of an entire file, expansion, or function. It 527 /// provides a sequence of CoverageSegments to iterate through, as well as the 528 /// list of expansions that can be further processed. 529 class CoverageData { 530 friend class CoverageMapping; 531 532 std::string Filename; 533 std::vector<CoverageSegment> Segments; 534 std::vector<ExpansionRecord> Expansions; 535 std::vector<CountedRegion> BranchRegions; 536 537 public: 538 CoverageData() = default; 539 540 CoverageData(StringRef Filename) : Filename(Filename) {} 541 542 /// Get the name of the file this data covers. 543 StringRef getFilename() const { return Filename; } 544 545 /// Get an iterator over the coverage segments for this object. The segments 546 /// are guaranteed to be uniqued and sorted by location. 547 std::vector<CoverageSegment>::const_iterator begin() const { 548 return Segments.begin(); 549 } 550 551 std::vector<CoverageSegment>::const_iterator end() const { 552 return Segments.end(); 553 } 554 555 bool empty() const { return Segments.empty(); } 556 557 /// Expansions that can be further processed. 558 ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } 559 560 /// Branches that can be further processed. 561 ArrayRef<CountedRegion> getBranches() const { return BranchRegions; } 562 }; 563 564 /// The mapping of profile information to coverage data. 565 /// 566 /// This is the main interface to get coverage information, using a profile to 567 /// fill out execution counts. 568 class CoverageMapping { 569 DenseMap<size_t, DenseSet<size_t>> RecordProvenance; 570 std::vector<FunctionRecord> Functions; 571 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices; 572 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; 573 574 CoverageMapping() = default; 575 576 /// Add a function record corresponding to \p Record. 577 Error loadFunctionRecord(const CoverageMappingRecord &Record, 578 IndexedInstrProfReader &ProfileReader); 579 580 /// Look up the indices for function records which are at least partially 581 /// defined in the specified file. This is guaranteed to return a superset of 582 /// such records: extra records not in the file may be included if there is 583 /// a hash collision on the filename. Clients must be robust to collisions. 584 ArrayRef<unsigned> 585 getImpreciseRecordIndicesForFilename(StringRef Filename) const; 586 587 public: 588 CoverageMapping(const CoverageMapping &) = delete; 589 CoverageMapping &operator=(const CoverageMapping &) = delete; 590 591 /// Load the coverage mapping using the given readers. 592 static Expected<std::unique_ptr<CoverageMapping>> 593 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 594 IndexedInstrProfReader &ProfileReader); 595 596 /// Load the coverage mapping from the given object files and profile. If 597 /// \p Arches is non-empty, it must specify an architecture for each object. 598 /// Ignores non-instrumented object files unless all are not instrumented. 599 static Expected<std::unique_ptr<CoverageMapping>> 600 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 601 ArrayRef<StringRef> Arches = None); 602 603 /// The number of functions that couldn't have their profiles mapped. 604 /// 605 /// This is a count of functions whose profile is out of date or otherwise 606 /// can't be associated with any coverage information. 607 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } 608 609 /// A hash mismatch occurs when a profile record for a symbol does not have 610 /// the same hash as a coverage mapping record for the same symbol. This 611 /// returns a list of hash mismatches, where each mismatch is a pair of the 612 /// symbol name and its coverage mapping hash. 613 ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { 614 return FuncHashMismatches; 615 } 616 617 /// Returns a lexicographically sorted, unique list of files that are 618 /// covered. 619 std::vector<StringRef> getUniqueSourceFiles() const; 620 621 /// Get the coverage for a particular file. 622 /// 623 /// The given filename must be the name as recorded in the coverage 624 /// information. That is, only names returned from getUniqueSourceFiles will 625 /// yield a result. 626 CoverageData getCoverageForFile(StringRef Filename) const; 627 628 /// Get the coverage for a particular function. 629 CoverageData getCoverageForFunction(const FunctionRecord &Function) const; 630 631 /// Get the coverage for an expansion within a coverage set. 632 CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; 633 634 /// Gets all of the functions covered by this profile. 635 iterator_range<FunctionRecordIterator> getCoveredFunctions() const { 636 return make_range(FunctionRecordIterator(Functions), 637 FunctionRecordIterator()); 638 } 639 640 /// Gets all of the functions in a particular file. 641 iterator_range<FunctionRecordIterator> 642 getCoveredFunctions(StringRef Filename) const { 643 return make_range(FunctionRecordIterator(Functions, Filename), 644 FunctionRecordIterator()); 645 } 646 647 /// Get the list of function instantiation groups in a particular file. 648 /// 649 /// Every instantiation group in a program is attributed to exactly one file: 650 /// the file in which the definition for the common function begins. 651 std::vector<InstantiationGroup> 652 getInstantiationGroups(StringRef Filename) const; 653 }; 654 655 /// Coverage statistics for a single line. 656 class LineCoverageStats { 657 uint64_t ExecutionCount; 658 bool HasMultipleRegions; 659 bool Mapped; 660 unsigned Line; 661 ArrayRef<const CoverageSegment *> LineSegments; 662 const CoverageSegment *WrappedSegment; 663 664 friend class LineCoverageIterator; 665 LineCoverageStats() = default; 666 667 public: 668 LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, 669 const CoverageSegment *WrappedSegment, unsigned Line); 670 671 uint64_t getExecutionCount() const { return ExecutionCount; } 672 673 bool hasMultipleRegions() const { return HasMultipleRegions; } 674 675 bool isMapped() const { return Mapped; } 676 677 unsigned getLine() const { return Line; } 678 679 ArrayRef<const CoverageSegment *> getLineSegments() const { 680 return LineSegments; 681 } 682 683 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } 684 }; 685 686 /// An iterator over the \c LineCoverageStats objects for lines described by 687 /// a \c CoverageData instance. 688 class LineCoverageIterator 689 : public iterator_facade_base< 690 LineCoverageIterator, std::forward_iterator_tag, LineCoverageStats> { 691 public: 692 LineCoverageIterator(const CoverageData &CD) 693 : LineCoverageIterator(CD, CD.begin()->Line) {} 694 695 LineCoverageIterator(const CoverageData &CD, unsigned Line) 696 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), 697 Line(Line), Segments(), Stats() { 698 this->operator++(); 699 } 700 701 bool operator==(const LineCoverageIterator &R) const { 702 return &CD == &R.CD && Next == R.Next && Ended == R.Ended; 703 } 704 705 const LineCoverageStats &operator*() const { return Stats; } 706 707 LineCoverageStats &operator*() { return Stats; } 708 709 LineCoverageIterator &operator++(); 710 711 LineCoverageIterator getEnd() const { 712 auto EndIt = *this; 713 EndIt.Next = CD.end(); 714 EndIt.Ended = true; 715 return EndIt; 716 } 717 718 private: 719 const CoverageData &CD; 720 const CoverageSegment *WrappedSegment; 721 std::vector<CoverageSegment>::const_iterator Next; 722 bool Ended; 723 unsigned Line; 724 SmallVector<const CoverageSegment *, 4> Segments; 725 LineCoverageStats Stats; 726 }; 727 728 /// Get a \c LineCoverageIterator range for the lines described by \p CD. 729 static inline iterator_range<LineCoverageIterator> 730 getLineCoverageStats(const coverage::CoverageData &CD) { 731 auto Begin = LineCoverageIterator(CD); 732 auto End = Begin.getEnd(); 733 return make_range(Begin, End); 734 } 735 736 // Coverage mappping data (V2) has the following layout: 737 // IPSK_covmap: 738 // [CoverageMapFileHeader] 739 // [ArrayStart] 740 // [CovMapFunctionRecordV2] 741 // [CovMapFunctionRecordV2] 742 // ... 743 // [ArrayEnd] 744 // [Encoded Filenames and Region Mapping Data] 745 // 746 // Coverage mappping data (V3) has the following layout: 747 // IPSK_covmap: 748 // [CoverageMapFileHeader] 749 // [Encoded Filenames] 750 // IPSK_covfun: 751 // [ArrayStart] 752 // odr_name_1: [CovMapFunctionRecordV3] 753 // odr_name_2: [CovMapFunctionRecordV3] 754 // ... 755 // [ArrayEnd] 756 // 757 // Both versions of the coverage mapping format encode the same information, 758 // but the V3 format does so more compactly by taking advantage of linkonce_odr 759 // semantics (it allows exactly 1 function record per name reference). 760 761 /// This namespace defines accessors shared by different versions of coverage 762 /// mapping records. 763 namespace accessors { 764 765 /// Return the structural hash associated with the function. 766 template <class FuncRecordTy, support::endianness Endian> 767 uint64_t getFuncHash(const FuncRecordTy *Record) { 768 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash); 769 } 770 771 /// Return the coverage map data size for the function. 772 template <class FuncRecordTy, support::endianness Endian> 773 uint64_t getDataSize(const FuncRecordTy *Record) { 774 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize); 775 } 776 777 /// Return the function lookup key. The value is considered opaque. 778 template <class FuncRecordTy, support::endianness Endian> 779 uint64_t getFuncNameRef(const FuncRecordTy *Record) { 780 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef); 781 } 782 783 /// Return the PGO name of the function. Used for formats in which the name is 784 /// a hash. 785 template <class FuncRecordTy, support::endianness Endian> 786 Error getFuncNameViaRef(const FuncRecordTy *Record, 787 InstrProfSymtab &ProfileNames, StringRef &FuncName) { 788 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record); 789 FuncName = ProfileNames.getFuncName(NameRef); 790 return Error::success(); 791 } 792 793 /// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the 794 /// coverage mapping is attached to the file header, instead of to the function 795 /// record. 796 template <class FuncRecordTy, support::endianness Endian> 797 StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record, 798 const char *MappingBuf) { 799 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))}; 800 } 801 802 /// Advance to the next out-of-line coverage mapping and its associated 803 /// function record. 804 template <class FuncRecordTy, support::endianness Endian> 805 std::pair<const char *, const FuncRecordTy *> 806 advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) { 807 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1}; 808 } 809 810 } // end namespace accessors 811 812 LLVM_PACKED_START 813 template <class IntPtrT> 814 struct CovMapFunctionRecordV1 { 815 using ThisT = CovMapFunctionRecordV1<IntPtrT>; 816 817 #define COVMAP_V1 818 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 819 #include "llvm/ProfileData/InstrProfData.inc" 820 #undef COVMAP_V1 821 CovMapFunctionRecordV1() = delete; 822 823 template <support::endianness Endian> uint64_t getFuncHash() const { 824 return accessors::getFuncHash<ThisT, Endian>(this); 825 } 826 827 template <support::endianness Endian> uint64_t getDataSize() const { 828 return accessors::getDataSize<ThisT, Endian>(this); 829 } 830 831 /// Return function lookup key. The value is consider opaque. 832 template <support::endianness Endian> IntPtrT getFuncNameRef() const { 833 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); 834 } 835 836 /// Return the PGO name of the function. 837 template <support::endianness Endian> 838 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 839 IntPtrT NameRef = getFuncNameRef<Endian>(); 840 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); 841 FuncName = ProfileNames.getFuncName(NameRef, NameS); 842 if (NameS && FuncName.empty()) 843 return make_error<CoverageMapError>(coveragemap_error::malformed); 844 return Error::success(); 845 } 846 847 template <support::endianness Endian> 848 std::pair<const char *, const ThisT *> 849 advanceByOne(const char *MappingBuf) const { 850 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 851 } 852 853 template <support::endianness Endian> uint64_t getFilenamesRef() const { 854 llvm_unreachable("V1 function format does not contain a filenames ref"); 855 } 856 857 template <support::endianness Endian> 858 StringRef getCoverageMapping(const char *MappingBuf) const { 859 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 860 MappingBuf); 861 } 862 }; 863 864 struct CovMapFunctionRecordV2 { 865 using ThisT = CovMapFunctionRecordV2; 866 867 #define COVMAP_V2 868 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 869 #include "llvm/ProfileData/InstrProfData.inc" 870 #undef COVMAP_V2 871 CovMapFunctionRecordV2() = delete; 872 873 template <support::endianness Endian> uint64_t getFuncHash() const { 874 return accessors::getFuncHash<ThisT, Endian>(this); 875 } 876 877 template <support::endianness Endian> uint64_t getDataSize() const { 878 return accessors::getDataSize<ThisT, Endian>(this); 879 } 880 881 template <support::endianness Endian> uint64_t getFuncNameRef() const { 882 return accessors::getFuncNameRef<ThisT, Endian>(this); 883 } 884 885 template <support::endianness Endian> 886 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 887 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 888 FuncName); 889 } 890 891 template <support::endianness Endian> 892 std::pair<const char *, const ThisT *> 893 advanceByOne(const char *MappingBuf) const { 894 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 895 } 896 897 template <support::endianness Endian> uint64_t getFilenamesRef() const { 898 llvm_unreachable("V2 function format does not contain a filenames ref"); 899 } 900 901 template <support::endianness Endian> 902 StringRef getCoverageMapping(const char *MappingBuf) const { 903 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 904 MappingBuf); 905 } 906 }; 907 908 struct CovMapFunctionRecordV3 { 909 using ThisT = CovMapFunctionRecordV3; 910 911 #define COVMAP_V3 912 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 913 #include "llvm/ProfileData/InstrProfData.inc" 914 #undef COVMAP_V3 915 CovMapFunctionRecordV3() = delete; 916 917 template <support::endianness Endian> uint64_t getFuncHash() const { 918 return accessors::getFuncHash<ThisT, Endian>(this); 919 } 920 921 template <support::endianness Endian> uint64_t getDataSize() const { 922 return accessors::getDataSize<ThisT, Endian>(this); 923 } 924 925 template <support::endianness Endian> uint64_t getFuncNameRef() const { 926 return accessors::getFuncNameRef<ThisT, Endian>(this); 927 } 928 929 template <support::endianness Endian> 930 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 931 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 932 FuncName); 933 } 934 935 /// Get the filename set reference. 936 template <support::endianness Endian> uint64_t getFilenamesRef() const { 937 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef); 938 } 939 940 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for 941 /// out-of-line coverage mapping data only. 942 template <support::endianness Endian> 943 StringRef getCoverageMapping(const char *) const { 944 return StringRef(&CoverageMapping, getDataSize<Endian>()); 945 } 946 947 // Advance to the next inline coverage mapping and its associated function 948 // record. Ignore the out-of-line coverage mapping buffer. 949 template <support::endianness Endian> 950 std::pair<const char *, const CovMapFunctionRecordV3 *> 951 advanceByOne(const char *) const { 952 assert(isAddrAligned(Align(8), this) && "Function record not aligned"); 953 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) - 954 sizeof(char) + getDataSize<Endian>(); 955 // Each function record has an alignment of 8, so we need to adjust 956 // alignment before reading the next record. 957 Next += offsetToAlignedAddr(Next, Align(8)); 958 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)}; 959 } 960 }; 961 962 // Per module coverage mapping data header, i.e. CoverageMapFileHeader 963 // documented above. 964 struct CovMapHeader { 965 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; 966 #include "llvm/ProfileData/InstrProfData.inc" 967 template <support::endianness Endian> uint32_t getNRecords() const { 968 return support::endian::byte_swap<uint32_t, Endian>(NRecords); 969 } 970 971 template <support::endianness Endian> uint32_t getFilenamesSize() const { 972 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); 973 } 974 975 template <support::endianness Endian> uint32_t getCoverageSize() const { 976 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); 977 } 978 979 template <support::endianness Endian> uint32_t getVersion() const { 980 return support::endian::byte_swap<uint32_t, Endian>(Version); 981 } 982 }; 983 984 LLVM_PACKED_END 985 986 enum CovMapVersion { 987 Version1 = 0, 988 // Function's name reference from CovMapFuncRecord is changed from raw 989 // name string pointer to MD5 to support name section compression. Name 990 // section is also compressed. 991 Version2 = 1, 992 // A new interpretation of the columnEnd field is added in order to mark 993 // regions as gap areas. 994 Version3 = 2, 995 // Function records are named, uniqued, and moved to a dedicated section. 996 Version4 = 3, 997 // Branch regions referring to two counters are added 998 Version5 = 4, 999 // The current version is Version5. 1000 CurrentVersion = INSTR_PROF_COVMAP_VERSION 1001 }; 1002 1003 template <int CovMapVersion, class IntPtrT> struct CovMapTraits { 1004 using CovMapFuncRecordType = CovMapFunctionRecordV3; 1005 using NameRefType = uint64_t; 1006 }; 1007 1008 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> { 1009 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1010 using NameRefType = uint64_t; 1011 }; 1012 1013 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> { 1014 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1015 using NameRefType = uint64_t; 1016 }; 1017 1018 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { 1019 using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; 1020 using NameRefType = IntPtrT; 1021 }; 1022 1023 } // end namespace coverage 1024 1025 /// Provide DenseMapInfo for CounterExpression 1026 template<> struct DenseMapInfo<coverage::CounterExpression> { 1027 static inline coverage::CounterExpression getEmptyKey() { 1028 using namespace coverage; 1029 1030 return CounterExpression(CounterExpression::ExprKind::Subtract, 1031 Counter::getCounter(~0U), 1032 Counter::getCounter(~0U)); 1033 } 1034 1035 static inline coverage::CounterExpression getTombstoneKey() { 1036 using namespace coverage; 1037 1038 return CounterExpression(CounterExpression::ExprKind::Add, 1039 Counter::getCounter(~0U), 1040 Counter::getCounter(~0U)); 1041 } 1042 1043 static unsigned getHashValue(const coverage::CounterExpression &V) { 1044 return static_cast<unsigned>( 1045 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), 1046 V.RHS.getKind(), V.RHS.getCounterID())); 1047 } 1048 1049 static bool isEqual(const coverage::CounterExpression &LHS, 1050 const coverage::CounterExpression &RHS) { 1051 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; 1052 } 1053 }; 1054 1055 } // end namespace llvm 1056 1057 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 1058